Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--3rdparty/Dropbox/API.php380
-rw-r--r--3rdparty/Dropbox/Exception.php15
-rw-r--r--3rdparty/Dropbox/Exception/Forbidden.php18
-rw-r--r--3rdparty/Dropbox/Exception/NotFound.php20
-rw-r--r--3rdparty/Dropbox/Exception/OverQuota.php20
-rw-r--r--3rdparty/Dropbox/Exception/RequestToken.php18
-rw-r--r--3rdparty/Dropbox/LICENSE.txt19
-rw-r--r--3rdparty/Dropbox/OAuth.php151
-rw-r--r--3rdparty/Dropbox/OAuth/Consumer/Dropbox.php37
-rw-r--r--3rdparty/Dropbox/OAuth/Curl.php282
-rw-r--r--3rdparty/Dropbox/README.md31
-rw-r--r--3rdparty/Dropbox/autoload.php29
-rw-r--r--3rdparty/Google/LICENSE.txt21
-rwxr-xr-x3rdparty/Google/OAuth.php751
-rwxr-xr-x3rdparty/Google/common.inc.php185
-rw-r--r--3rdparty/aws-sdk/README.md136
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/README.md37
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php75
-rw-r--r--3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php789
-rwxr-xr-x3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php186
-rw-r--r--3rdparty/aws-sdk/_docs/CHANGELOG.md1405
-rw-r--r--3rdparty/aws-sdk/_docs/CONTRIBUTORS.md64
-rw-r--r--3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html235
-rw-r--r--3rdparty/aws-sdk/_docs/KNOWNISSUES.md65
-rw-r--r--3rdparty/aws-sdk/_docs/LICENSE.md151
-rw-r--r--3rdparty/aws-sdk/_docs/NOTICE.md444
-rw-r--r--3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html243
-rw-r--r--3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md2
-rw-r--r--3rdparty/aws-sdk/authentication/signable.interface.php48
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v2query.class.php163
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v3json.class.php235
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v3query.class.php192
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v4json.class.php353
-rw-r--r--3rdparty/aws-sdk/authentication/signature_v4query.class.php345
-rw-r--r--3rdparty/aws-sdk/authentication/signer.abstract.php68
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/LICENSE25
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/README1
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/README5
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql7
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql6
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql2
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php126
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachecore.class.php160
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachefile.class.php189
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachemc.class.php183
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php297
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php129
-rwxr-xr-x3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php66
-rw-r--r--3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php181
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/LICENSE25
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/README.md15
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/cacert.pem3390
-rwxr-xr-x3rdparty/aws-sdk/lib/requestcore/requestcore.class.php1028
-rw-r--r--3rdparty/aws-sdk/lib/yaml/LICENSE19
-rw-r--r--3rdparty/aws-sdk/lib/yaml/README.markdown15
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php135
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php60
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php442
-rw-r--r--3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php612
-rwxr-xr-x3rdparty/aws-sdk/sdk.class.php1435
-rwxr-xr-x3rdparty/aws-sdk/services/s3.class.php3979
-rw-r--r--3rdparty/aws-sdk/utilities/array.class.php312
-rw-r--r--3rdparty/aws-sdk/utilities/batchrequest.class.php126
-rw-r--r--3rdparty/aws-sdk/utilities/complextype.class.php123
-rw-r--r--3rdparty/aws-sdk/utilities/credential.class.php157
-rw-r--r--3rdparty/aws-sdk/utilities/credentials.class.php125
-rw-r--r--3rdparty/aws-sdk/utilities/gzipdecode.class.php377
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopbase.class.php67
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php127
-rw-r--r--3rdparty/aws-sdk/utilities/hadoopstep.class.php98
-rw-r--r--3rdparty/aws-sdk/utilities/info.class.php69
-rw-r--r--3rdparty/aws-sdk/utilities/json.class.php89
-rw-r--r--3rdparty/aws-sdk/utilities/manifest.class.php54
-rw-r--r--3rdparty/aws-sdk/utilities/mimetypes.class.php223
-rw-r--r--3rdparty/aws-sdk/utilities/policy.class.php134
-rw-r--r--3rdparty/aws-sdk/utilities/request.class.php70
-rw-r--r--3rdparty/aws-sdk/utilities/response.class.php29
-rw-r--r--3rdparty/aws-sdk/utilities/simplexml.class.php248
-rw-r--r--3rdparty/aws-sdk/utilities/stacktemplate.class.php52
-rw-r--r--3rdparty/aws-sdk/utilities/stepconfig.class.php91
-rwxr-xr-x3rdparty/aws-sdk/utilities/utilities.class.php399
-rw-r--r--3rdparty/mediawiki/CSSMin.php1
-rw-r--r--3rdparty/phpass/PasswordHash.php2
-rw-r--r--3rdparty/when/When.php12
-rw-r--r--apps/bookmarks/addBm.php2
-rw-r--r--apps/bookmarks/ajax/delBookmark.php2
-rw-r--r--apps/bookmarks/ajax/editBookmark.php8
-rw-r--r--apps/bookmarks/ajax/recordClick.php2
-rw-r--r--apps/bookmarks/ajax/updateList.php6
-rw-r--r--apps/bookmarks/appinfo/database.xml2
-rw-r--r--apps/bookmarks/js/addBm.js1
-rw-r--r--apps/bookmarks/js/bookmarks.js5
-rw-r--r--apps/bookmarks/js/bookmarksearch.js1
-rw-r--r--apps/calendar/ajax/calendar/edit.form.php2
-rw-r--r--apps/calendar/ajax/changeview.php2
-rw-r--r--apps/calendar/ajax/event/edit.form.php2
-rw-r--r--apps/calendar/ajax/events.php1
-rw-r--r--apps/calendar/ajax/import/import.php4
-rw-r--r--apps/calendar/ajax/settings/guesstimezone.php4
-rw-r--r--apps/calendar/ajax/share/activation.php4
-rw-r--r--apps/calendar/ajax/share/changepermission.php10
-rw-r--r--apps/calendar/ajax/share/dropdown.php2
-rw-r--r--apps/calendar/ajax/share/share.php8
-rw-r--r--apps/calendar/ajax/share/unshare.php8
-rw-r--r--apps/calendar/appinfo/database.xml4
-rw-r--r--apps/calendar/appinfo/version2
-rw-r--r--apps/calendar/index.php4
-rw-r--r--apps/calendar/js/calendar.js35
-rw-r--r--apps/calendar/js/geo.js2
-rw-r--r--apps/calendar/js/loader.js2
-rw-r--r--apps/calendar/lib/app.php19
-rw-r--r--apps/calendar/lib/object.php3
-rw-r--r--apps/calendar/templates/calendar.php38
-rw-r--r--apps/calendar/templates/part.choosecalendar.rowfields.php2
-rw-r--r--apps/calendar/templates/part.choosecalendar.rowfields.shared.php2
-rw-r--r--apps/calendar/templates/part.eventform.php8
-rw-r--r--apps/calendar/templates/part.import.php3
-rw-r--r--apps/calendar/templates/part.showevent.php29
-rw-r--r--apps/contacts/ajax/activation.php1
-rw-r--r--apps/contacts/ajax/addcontact.php1
-rw-r--r--apps/contacts/ajax/addproperty.php45
-rw-r--r--apps/contacts/ajax/createaddressbook.php1
-rw-r--r--apps/contacts/ajax/cropphoto.php2
-rw-r--r--apps/contacts/ajax/deletebook.php1
-rw-r--r--apps/contacts/ajax/deletecard.php13
-rw-r--r--apps/contacts/ajax/deleteproperty.php5
-rw-r--r--apps/contacts/ajax/savecrop.php1
-rw-r--r--apps/contacts/ajax/saveproperty.php9
-rw-r--r--apps/contacts/ajax/uploadphoto.php4
-rw-r--r--apps/contacts/import.php2
-rw-r--r--apps/contacts/js/contacts.js24
-rw-r--r--apps/contacts/js/loader.js14
-rw-r--r--apps/contacts/lib/vcard.php5
-rw-r--r--apps/contacts/templates/part.contact.php4
-rw-r--r--apps/contacts/templates/part.contacts.php2
-rw-r--r--apps/contacts/templates/part.cropphoto.php2
-rw-r--r--apps/contacts/templates/part.importaddressbook.php5
-rw-r--r--apps/external/ajax/setsites.php2
-rw-r--r--apps/files/ajax/list.php2
-rw-r--r--apps/files/index.php14
-rw-r--r--apps/files/js/fileactions.js8
-rw-r--r--apps/files/js/files.js2
-rw-r--r--apps/files/templates/index.php2
-rw-r--r--apps/files_archive/lib/storage.php2
-rw-r--r--apps/files_encryption/lib/cryptstream.php6
-rw-r--r--apps/files_encryption/lib/proxy.php2
-rw-r--r--apps/files_encryption/tests/proxy.php15
-rw-r--r--apps/files_external/ajax/addMountPoint.php13
-rw-r--r--apps/files_external/ajax/dropbox.php41
-rw-r--r--apps/files_external/ajax/google.php51
-rw-r--r--apps/files_external/ajax/removeMountPoint.php13
-rw-r--r--apps/files_external/appinfo/app.php8
-rw-r--r--apps/files_external/css/settings.css9
-rw-r--r--apps/files_external/js/dropbox.js53
-rw-r--r--apps/files_external/js/google.js48
-rw-r--r--apps/files_external/js/settings.js166
-rw-r--r--apps/files_external/lib/amazons3.php2
-rwxr-xr-xapps/files_external/lib/config.php238
-rwxr-xr-xapps/files_external/lib/dropbox.php203
-rw-r--r--apps/files_external/lib/ftp.php2
-rw-r--r--apps/files_external/lib/google.php2
-rw-r--r--apps/files_external/lib/smb.php20
-rw-r--r--apps/files_external/lib/swift.php2
-rw-r--r--apps/files_external/lib/webdav.php4
-rwxr-xr-xapps/files_external/personal.php34
-rw-r--r--apps/files_external/settings.php13
-rw-r--r--apps/files_external/templates/settings.php97
-rw-r--r--apps/files_external/tests/config.php3
-rw-r--r--apps/files_external/tests/smb.php2
-rw-r--r--apps/files_imageviewer/js/jquery.fancybox-1.3.4.js4
-rw-r--r--apps/files_imageviewer/js/jquery.fancybox-1.3.4.pack.js47
-rw-r--r--apps/files_pdfviewer/appinfo/app.php6
-rw-r--r--apps/files_pdfviewer/appinfo/info.xml2
-rw-r--r--apps/files_pdfviewer/css/viewer.css1
-rw-r--r--apps/files_pdfviewer/js/pdfjs/build/pdf.js2820
-rw-r--r--apps/files_pdfviewer/js/pdfjs/compatibility.js340
-rwxr-xr-xapps/files_pdfviewer/js/pdfjs/update.sh3
-rw-r--r--apps/files_pdfviewer/js/pdfjs/viewer.js1940
-rw-r--r--apps/files_pdfviewer/js/viewer.js19
-rw-r--r--apps/files_sharing/appinfo/database.xml2
-rw-r--r--apps/files_sharing/lib_share.php12
-rw-r--r--apps/files_texteditor/appinfo/app.php1
-rw-r--r--apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.eotbin0 -> 78034 bytes
-rw-r--r--apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.svg630
-rw-r--r--apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.ttfbin0 -> 77800 bytes
-rw-r--r--apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.woffbin0 -> 46192 bytes
-rw-r--r--apps/files_texteditor/css/DroidSansMono/Google Android License.txt18
-rw-r--r--apps/files_texteditor/css/DroidSansMono/demo.html33
-rw-r--r--apps/files_texteditor/css/DroidSansMono/stylesheet.css15
-rw-r--r--apps/files_texteditor/js/aceeditor/ace.js3
-rw-r--r--apps/gallery/appinfo/app.php4
-rw-r--r--apps/gallery/appinfo/database.xml2
-rw-r--r--apps/gallery/appinfo/update.php14
-rw-r--r--apps/gallery/css/styles.css18
-rw-r--r--apps/gallery/index.php4
-rw-r--r--apps/gallery/js/album_cover.js138
-rw-r--r--apps/gallery/js/pictures.js37
-rw-r--r--apps/gallery/lib/hooks_handlers.php130
-rw-r--r--apps/gallery/lib/managers.php22
-rw-r--r--apps/gallery/lib/tiles.php6
-rw-r--r--apps/gallery/templates/index.php35
-rw-r--r--apps/media/ajax/api.php4
-rw-r--r--apps/media/appinfo/database.xml2
-rw-r--r--apps/remoteStorage/appinfo/database.xml2
-rw-r--r--apps/remoteStorage/auth.php7
-rw-r--r--apps/tasks/ajax/addtask.php2
-rw-r--r--apps/tasks/ajax/delete.php2
-rw-r--r--apps/tasks/js/tasks.js11
-rw-r--r--apps/tasks/templates/part.taskform.php2
-rw-r--r--apps/user_ldap/group_ldap.php4
-rw-r--r--apps/user_ldap/lib_ldap.php4
-rw-r--r--apps/user_ldap/settings.php3
-rw-r--r--apps/user_ldap/templates/settings.php1
-rw-r--r--config/config.sample.php69
-rw-r--r--core/js/multiselect.js12
-rw-r--r--core/lostpassword/index.php2
-rw-r--r--core/templates/404.php2
-rw-r--r--core/templates/layout.guest.php4
-rw-r--r--core/templates/layout.user.php14
-rw-r--r--core/templates/login.php2
-rw-r--r--db_structure.xml4
-rwxr-xr-xindex.php5
-rwxr-xr-xlib/app.php7
-rw-r--r--lib/archive/tar.php4
-rw-r--r--lib/archive/zip.php2
-rw-r--r--lib/base.php11
-rw-r--r--lib/config.php6
-rw-r--r--lib/connector/sabre/file.php4
-rw-r--r--lib/connector/sabre/node.php24
-rw-r--r--lib/fileproxy.php33
-rw-r--r--lib/filesystem.php27
-rw-r--r--lib/filesystemview.php58
-rw-r--r--lib/helper.php74
-rw-r--r--lib/image.php4
-rw-r--r--lib/installer.php2
-rw-r--r--lib/json.php12
-rw-r--r--lib/ocsclient.php18
-rw-r--r--lib/public/json.php7
-rw-r--r--lib/public/util.php34
-rw-r--r--lib/setup.php4
-rw-r--r--lib/template.php55
-rw-r--r--lib/updater.php17
-rw-r--r--lib/user/database.php8
-rwxr-xr-x[-rw-r--r--]lib/util.php87
-rw-r--r--lib/vcategories.php8
-rw-r--r--remote.php7
-rw-r--r--settings/admin.php2
-rw-r--r--settings/apps.php5
-rw-r--r--settings/css/settings.css3
-rw-r--r--settings/js/users.js12
-rw-r--r--settings/templates/admin.php2
-rw-r--r--settings/templates/help.php6
-rw-r--r--settings/templates/users.php110
-rw-r--r--tests/index.php2
255 files changed, 29767 insertions, 1534 deletions
diff --git a/.gitignore b/.gitignore
index ac58f3e6a63..e2ff07d14d8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,6 +40,9 @@ nbproject
# Cloud9IDE
.settings.xml
+# vim ex mode
+.vimrc
+
# Mac OS
.DS_Store
diff --git a/3rdparty/Dropbox/API.php b/3rdparty/Dropbox/API.php
new file mode 100644
index 00000000000..cff6c35c7fb
--- /dev/null
+++ b/3rdparty/Dropbox/API.php
@@ -0,0 +1,380 @@
+<?php
+
+/**
+ * Dropbox API class
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+class Dropbox_API {
+
+ /**
+ * Sandbox root-path
+ */
+ const ROOT_SANDBOX = 'sandbox';
+
+ /**
+ * Dropbox root-path
+ */
+ const ROOT_DROPBOX = 'dropbox';
+
+ /**
+ * API URl
+ */
+ protected $api_url = 'https://api.dropbox.com/1/';
+
+ /**
+ * Content API URl
+ */
+ protected $api_content_url = 'https://api-content.dropbox.com/1/';
+
+ /**
+ * OAuth object
+ *
+ * @var Dropbox_OAuth
+ */
+ protected $oauth;
+
+ /**
+ * Default root-path, this will most likely be 'sandbox' or 'dropbox'
+ *
+ * @var string
+ */
+ protected $root;
+ protected $useSSL;
+
+ /**
+ * Constructor
+ *
+ * @param Dropbox_OAuth Dropbox_Auth object
+ * @param string $root default root path (sandbox or dropbox)
+ */
+ public function __construct(Dropbox_OAuth $oauth, $root = self::ROOT_DROPBOX, $useSSL = true) {
+
+ $this->oauth = $oauth;
+ $this->root = $root;
+ $this->useSSL = $useSSL;
+ if (!$this->useSSL)
+ {
+ throw new Dropbox_Exception('Dropbox REST API now requires that all requests use SSL');
+ }
+
+ }
+
+ /**
+ * Returns information about the current dropbox account
+ *
+ * @return stdclass
+ */
+ public function getAccountInfo() {
+
+ $data = $this->oauth->fetch($this->api_url . 'account/info');
+ return json_decode($data['body'],true);
+
+ }
+
+ /**
+ * Returns a file's contents
+ *
+ * @param string $path path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getFile($path = '', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $result = $this->oauth->fetch($this->api_content_url . 'files/' . $root . '/' . ltrim($path,'/'));
+ return $result['body'];
+
+ }
+
+ /**
+ * Uploads a new file
+ *
+ * @param string $path Target path (including filename)
+ * @param string $file Either a path to a file or a stream resource
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return bool
+ */
+ public function putFile($path, $file, $root = null) {
+
+ $directory = dirname($path);
+ $filename = basename($path);
+
+ if($directory==='.') $directory = '';
+ $directory = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($directory));
+// $filename = str_replace('~', '%7E', rawurlencode($filename));
+ if (is_null($root)) $root = $this->root;
+
+ if (is_string($file)) {
+
+ $file = fopen($file,'rb');
+
+ } elseif (!is_resource($file)) {
+ throw new Dropbox_Exception('File must be a file-resource or a string');
+ }
+ $result=$this->multipartFetch($this->api_content_url . 'files/' .
+ $root . '/' . trim($directory,'/'), $file, $filename);
+
+ if(!isset($result["httpStatus"]) || $result["httpStatus"] != 200)
+ throw new Dropbox_Exception("Uploading file to Dropbox failed");
+
+ return true;
+ }
+
+
+ /**
+ * Copies a file or directory from one location to another
+ *
+ * This method returns the file information of the newly created file.
+ *
+ * @param string $from source path
+ * @param string $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function copy($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/copy', array('from_path' => $from, 'to_path' => $to, 'root' => $root));
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates a new folder
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function createFolder($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ // Making sure the path starts with a /
+// $path = '/' . ltrim($path,'/');
+
+ $response = $this->oauth->fetch($this->api_url . 'fileops/create_folder', array('path' => $path, 'root' => $root),'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Deletes a file or folder.
+ *
+ * This method will return the metadata information from the deleted file or folder, if successful.
+ *
+ * @param string $path Path to new folder
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array
+ */
+ public function delete($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/delete', array('path' => $path, 'root' => $root));
+ return json_decode($response['body']);
+
+ }
+
+ /**
+ * Moves a file or directory to a new location
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param mixed $from Source path
+ * @param mixed $to destination path
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return stdclass
+ */
+ public function move($from, $to, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $response = $this->oauth->fetch($this->api_url . 'fileops/move', array('from_path' => rawurldecode($from), 'to_path' => rawurldecode($to), 'root' => $root));
+
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns file and directory information
+ *
+ * @param string $path Path to receive information from
+ * @param bool $list When set to true, this method returns information from all files in a directory. When set to false it will only return infromation from the specified directory.
+ * @param string $hash If a hash is supplied, this method simply returns true if nothing has changed since the last request. Good for caching.
+ * @param int $fileLimit Maximum number of file-information to receive
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return array|true
+ */
+ public function getMetaData($path, $list = true, $hash = null, $fileLimit = null, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+
+ $args = array(
+ 'list' => $list,
+ );
+
+ if (!is_null($hash)) $args['hash'] = $hash;
+ if (!is_null($fileLimit)) $args['file_limit'] = $fileLimit;
+
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url . 'metadata/' . $root . '/' . ltrim($path,'/'), $args);
+
+ /* 304 is not modified */
+ if ($response['httpStatus']==304) {
+ return true;
+ } else {
+ return json_decode($response['body'],true);
+ }
+
+ }
+
+ /**
+ * A way of letting you keep up with changes to files and folders in a user's Dropbox. You can periodically call /delta to get a list of "delta entries", which are instructions on how to update your local state to match the server's state.
+ *
+ * This method returns the information from the newly created directory
+ *
+ * @param string $cursor A string that is used to keep track of your current state. On the next call pass in this value to return delta entries that have been recorded since the cursor was returned.
+ * @return stdclass
+ */
+ public function delta($cursor) {
+
+ $arg['cursor'] = $cursor;
+
+ $response = $this->oauth->fetch($this->api_url . 'delta', $arg, 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a thumbnail (as a string) for a file path.
+ *
+ * @param string $path Path to file
+ * @param string $size small, medium or large
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @return string
+ */
+ public function getThumbnail($path, $size = 'small', $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_content_url . 'thumbnails/' . $root . '/' . ltrim($path,'/'),array('size' => $size));
+
+ return $response['body'];
+
+ }
+
+ /**
+ * This method is used to generate multipart POST requests for file upload
+ *
+ * @param string $uri
+ * @param array $arguments
+ * @return bool
+ */
+ protected function multipartFetch($uri, $file, $filename) {
+
+ /* random string */
+ $boundary = 'R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3';
+
+ $headers = array(
+ 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
+ );
+
+ $body="--" . $boundary . "\r\n";
+ $body.="Content-Disposition: form-data; name=file; filename=".rawurldecode($filename)."\r\n";
+ $body.="Content-type: application/octet-stream\r\n";
+ $body.="\r\n";
+ $body.=stream_get_contents($file);
+ $body.="\r\n";
+ $body.="--" . $boundary . "--";
+
+ // Dropbox requires the filename to also be part of the regular arguments, so it becomes
+ // part of the signature.
+ $uri.='?file=' . $filename;
+
+ return $this->oauth->fetch($uri, $body, 'POST', $headers);
+
+ }
+
+
+ /**
+ * Search
+ *
+ * Returns metadata for all files and folders that match the search query.
+ *
+ * @added by: diszo.sasil
+ *
+ * @param string $query
+ * @param string $root Use this to override the default root path (sandbox/dropbox)
+ * @param string $path
+ * @return array
+ */
+ public function search($query = '', $root = null, $path = ''){
+ if (is_null($root)) $root = $this->root;
+ if(!empty($path)){
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ }
+ $response = $this->oauth->fetch($this->api_url . 'search/' . $root . '/' . ltrim($path,'/'),array('query' => $query));
+ return json_decode($response['body'],true);
+ }
+
+ /**
+ * Creates and returns a shareable link to files or folders.
+ *
+ * Note: Links created by the /shares API call expire after thirty days.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function share($path, $root = null) {
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'shares/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Returns a link directly to a file.
+ * Similar to /shares. The difference is that this bypasses the Dropbox webserver, used to provide a preview of the file, so that you can effectively stream the contents of your media.
+ *
+ * Note: The /media link expires after four hours, allotting enough time to stream files, but not enough to leave a connection open indefinitely.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function media($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'media/'. $root . '/' . ltrim($path, '/'), array(), 'POST');
+ return json_decode($response['body'],true);
+
+ }
+
+ /**
+ * Creates and returns a copy_ref to a file. This reference string can be used to copy that file to another user's Dropbox by passing it in as the from_copy_ref parameter on /fileops/copy.
+ *
+ * @param type $path
+ * @param type $root
+ * @return type
+ */
+ public function copy_ref($path, $root = null) {
+
+ if (is_null($root)) $root = $this->root;
+ $path = str_replace(array('%2F','~'), array('/','%7E'), rawurlencode($path));
+ $response = $this->oauth->fetch($this->api_url. 'copy_ref/'. $root . '/' . ltrim($path, '/'));
+ return json_decode($response['body'],true);
+
+ }
+
+
+}
diff --git a/3rdparty/Dropbox/Exception.php b/3rdparty/Dropbox/Exception.php
new file mode 100644
index 00000000000..50cbc4c7915
--- /dev/null
+++ b/3rdparty/Dropbox/Exception.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * Dropbox base exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * Base exception class
+ */
+class Dropbox_Exception extends Exception { }
diff --git a/3rdparty/Dropbox/Exception/Forbidden.php b/3rdparty/Dropbox/Exception/Forbidden.php
new file mode 100644
index 00000000000..5f0378cfc74
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/Forbidden.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Dropbox Forbidden exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when we receive the 403 forbidden response
+ */
+class Dropbox_Exception_Forbidden extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/NotFound.php b/3rdparty/Dropbox/Exception/NotFound.php
new file mode 100644
index 00000000000..3deaf90d76b
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/NotFound.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Dropbox Not Found exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when a non-existant uri is accessed.
+ *
+ * Basically, this exception is used when we get back a 404.
+ */
+class Dropbox_Exception_NotFound extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/OverQuota.php b/3rdparty/Dropbox/Exception/OverQuota.php
new file mode 100644
index 00000000000..86e5425dbd8
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/OverQuota.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Dropbox Over Quota exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when the operation required more space than the available quota.
+ *
+ * Basically, this exception is used when we get back a 507.
+ */
+class Dropbox_Exception_OverQuota extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/Exception/RequestToken.php b/3rdparty/Dropbox/Exception/RequestToken.php
new file mode 100644
index 00000000000..5b117f2c6b0
--- /dev/null
+++ b/3rdparty/Dropbox/Exception/RequestToken.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Dropbox RequestToken exception
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * This exception is thrown when an error occured during the request_token process.
+ */
+class Dropbox_Exception_RequestToken extends Dropbox_Exception {
+
+
+}
diff --git a/3rdparty/Dropbox/LICENSE.txt b/3rdparty/Dropbox/LICENSE.txt
new file mode 100644
index 00000000000..cd3512acee6
--- /dev/null
+++ b/3rdparty/Dropbox/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Rooftop Solutions
+
+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.
diff --git a/3rdparty/Dropbox/OAuth.php b/3rdparty/Dropbox/OAuth.php
new file mode 100644
index 00000000000..905cc2da1c6
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * Dropbox OAuth
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+
+/**
+ * This class is an abstract OAuth class.
+ *
+ * It must be extended by classes who wish to provide OAuth functionality
+ * using different libraries.
+ */
+abstract class Dropbox_OAuth {
+
+ /**
+ * After a user has authorized access, dropbox can redirect the user back
+ * to this url.
+ *
+ * @var string
+ */
+ public $authorizeCallbackUrl = null;
+
+ /**
+ * Uri used to fetch request tokens
+ *
+ * @var string
+ */
+ const URI_REQUEST_TOKEN = 'https://api.dropbox.com/1/oauth/request_token';
+
+ /**
+ * Uri used to redirect the user to for authorization.
+ *
+ * @var string
+ */
+ const URI_AUTHORIZE = 'https://www.dropbox.com/1/oauth/authorize';
+
+ /**
+ * Uri used to
+ *
+ * @var string
+ */
+ const URI_ACCESS_TOKEN = 'https://api.dropbox.com/1/oauth/access_token';
+
+ /**
+ * An OAuth request token.
+ *
+ * @var string
+ */
+ protected $oauth_token = null;
+
+ /**
+ * OAuth token secret
+ *
+ * @var string
+ */
+ protected $oauth_token_secret = null;
+
+
+ /**
+ * Constructor
+ *
+ * @param string $consumerKey
+ * @param string $consumerSecret
+ */
+ abstract public function __construct($consumerKey, $consumerSecret);
+
+ /**
+ * Sets the request token and secret.
+ *
+ * The tokens can also be passed as an array into the first argument.
+ * The array must have the elements token and token_secret.
+ *
+ * @param string|array $token
+ * @param string $token_secret
+ * @return void
+ */
+ public function setToken($token, $token_secret = null) {
+
+ if (is_array($token)) {
+ $this->oauth_token = $token['token'];
+ $this->oauth_token_secret = $token['token_secret'];
+ } else {
+ $this->oauth_token = $token;
+ $this->oauth_token_secret = $token_secret;
+ }
+
+ }
+
+ /**
+ * Returns the oauth request tokens as an associative array.
+ *
+ * The array will contain the elements 'token' and 'token_secret'.
+ *
+ * @return array
+ */
+ public function getToken() {
+
+ return array(
+ 'token' => $this->oauth_token,
+ 'token_secret' => $this->oauth_token_secret,
+ );
+
+ }
+
+ /**
+ * Returns the authorization url
+ *
+ * @param string $callBack Specify a callback url to automatically redirect the user back
+ * @return string
+ */
+ public function getAuthorizeUrl($callBack = null) {
+
+ // Building the redirect uri
+ $token = $this->getToken();
+ $uri = self::URI_AUTHORIZE . '?oauth_token=' . $token['token'];
+ if ($callBack) $uri.='&oauth_callback=' . $callBack;
+ return $uri;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public abstract function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array());
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return array
+ */
+ abstract public function getRequestToken();
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * @return array
+ */
+ abstract public function getAccessToken();
+
+}
diff --git a/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php b/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php
new file mode 100644
index 00000000000..204a659de00
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth/Consumer/Dropbox.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * HTTP OAuth Consumer
+ *
+ * Adapted from halldirector's code in
+ * http://code.google.com/p/dropbox-php/issues/detail?id=36#c5
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2011 Joe Constant / halldirector. All rights reserved.
+ * @author Joe Constant / halldirector
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+require_once 'HTTP/OAuth.php';
+require_once 'HTTP/OAuth/Consumer.php';
+
+/*
+ * This class is to help work around aomw ssl issues.
+ */
+class Dropbox_OAuth_Consumer_Dropbox extends HTTP_OAuth_Consumer
+{
+ public function getOAuthConsumerRequest()
+ {
+ if (!$this->consumerRequest instanceof HTTP_OAuth_Consumer_Request) {
+ $this->consumerRequest = new HTTP_OAuth_Consumer_Request;
+ }
+
+ // TODO: Change this and add in code to validate the SSL cert.
+ // see https://github.com/bagder/curl/blob/master/lib/mk-ca-bundle.pl
+ $this->consumerRequest->setConfig(array(
+ 'ssl_verify_peer' => false,
+ 'ssl_verify_host' => false
+ ));
+
+ return $this->consumerRequest;
+ }
+}
diff --git a/3rdparty/Dropbox/OAuth/Curl.php b/3rdparty/Dropbox/OAuth/Curl.php
new file mode 100644
index 00000000000..b75b27bb363
--- /dev/null
+++ b/3rdparty/Dropbox/OAuth/Curl.php
@@ -0,0 +1,282 @@
+<?php
+
+/**
+ * Dropbox OAuth
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2011 Daniel Huesken
+ * @author Daniel Huesken (http://www.danielhuesken.de/)
+ * @license MIT
+ */
+
+/**
+ * This class is used to sign all requests to dropbox.
+ *
+ * This specific class uses WordPress WP_Http to authenticate.
+ */
+class Dropbox_OAuth_Curl extends Dropbox_OAuth {
+
+ /**
+ *
+ * @var string ConsumerKey
+ */
+ protected $consumerKey = null;
+ /**
+ *
+ * @var string ConsumerSecret
+ */
+ protected $consumerSecret = null;
+ /**
+ *
+ * @var string ProzessCallBack
+ */
+ public $ProgressFunction = false;
+
+ /**
+ * Constructor
+ *
+ * @param string $consumerKey
+ * @param string $consumerSecret
+ */
+ public function __construct($consumerKey, $consumerSecret) {
+ if (!function_exists('curl_exec'))
+ throw new Dropbox_Exception('The PHP curl functions not available!');
+
+ $this->consumerKey = $consumerKey;
+ $this->consumerSecret = $consumerSecret;
+ }
+
+ /**
+ * Fetches a secured oauth url and returns the response body.
+ *
+ * @param string $uri
+ * @param mixed $arguments
+ * @param string $method
+ * @param array $httpHeaders
+ * @return string
+ */
+ public function fetch($uri, $arguments = array(), $method = 'GET', $httpHeaders = array()) {
+
+ $uri=str_replace('http://', 'https://', $uri); // all https, upload makes problems if not
+ if (is_string($arguments) and strtoupper($method) == 'POST') {
+ preg_match("/\?file=(.*)$/i", $uri, $matches);
+ if (isset($matches[1])) {
+ $uri = str_replace($matches[0], "", $uri);
+ $filename = $matches[1];
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, array("file" => $filename), $method));
+ }
+ } else {
+ $httpHeaders=array_merge($httpHeaders,$this->getOAuthHeader($uri, $arguments, $method));
+ }
+ $ch = curl_init();
+ if (strtoupper($method) == 'POST') {
+ curl_setopt($ch, CURLOPT_URL, $uri);
+ curl_setopt($ch, CURLOPT_POST, true);
+// if (is_array($arguments))
+// $arguments=http_build_query($arguments);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $arguments);
+// $httpHeaders['Content-Length']=strlen($arguments);
+ } else {
+ curl_setopt($ch, CURLOPT_URL, $uri.'?'.http_build_query($arguments));
+ curl_setopt($ch, CURLOPT_POST, false);
+ }
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 300);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+// curl_setopt($ch, CURLOPT_CAINFO, "rootca");
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ //Build header
+ $headers = array();
+ foreach ($httpHeaders as $name => $value) {
+ $headers[] = "{$name}: $value";
+ }
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
+ if (function_exists($this->ProgressFunction) and defined('CURLOPT_PROGRESSFUNCTION')) {
+ curl_setopt($ch, CURLOPT_NOPROGRESS, false);
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $this->ProgressFunction);
+ curl_setopt($ch, CURLOPT_BUFFERSIZE, 512);
+ }
+ $response=curl_exec($ch);
+ $errorno=curl_errno($ch);
+ $error=curl_error($ch);
+ $status=curl_getinfo($ch,CURLINFO_HTTP_CODE);
+ curl_close($ch);
+
+
+ if (!empty($errorno))
+ throw new Dropbox_Exception_NotFound('Curl error: ('.$errorno.') '.$error."\n");
+
+ if ($status>=300) {
+ $body = json_decode($response,true);
+ switch ($status) {
+ // Not modified
+ case 304 :
+ return array(
+ 'httpStatus' => 304,
+ 'body' => null,
+ );
+ break;
+ case 403 :
+ throw new Dropbox_Exception_Forbidden('Forbidden.
+ This could mean a bad OAuth request, or a file or folder already existing at the target location.
+ ' . $body["error"] . "\n");
+ case 404 :
+ throw new Dropbox_Exception_NotFound('Resource at uri: ' . $uri . ' could not be found. ' .
+ $body["error"] . "\n");
+ case 507 :
+ throw new Dropbox_Exception_OverQuota('This dropbox is full. ' .
+ $body["error"] . "\n");
+ }
+ if (!empty($body["error"]))
+ throw new Dropbox_Exception_RequestToken('Error: ('.$status.') '.$body["error"]."\n");
+ }
+
+ return array(
+ 'body' => $response,
+ 'httpStatus' => $status
+ );
+ }
+
+ /**
+ * Returns named array with oauth parameters for further use
+ * @return array Array with oauth_ parameters
+ */
+ private function getOAuthBaseParams() {
+ $params['oauth_version'] = '1.0';
+ $params['oauth_signature_method'] = 'HMAC-SHA1';
+
+ $params['oauth_consumer_key'] = $this->consumerKey;
+ $tokens = $this->getToken();
+ if (isset($tokens['token']) && $tokens['token']) {
+ $params['oauth_token'] = $tokens['token'];
+ }
+ $params['oauth_timestamp'] = time();
+ $params['oauth_nonce'] = md5(microtime() . mt_rand());
+ return $params;
+ }
+
+ /**
+ * Creates valid Authorization header for OAuth, based on URI and Params
+ *
+ * @param string $uri
+ * @param array $params
+ * @param string $method GET or POST, standard is GET
+ * @param array $oAuthParams optional, pass your own oauth_params here
+ * @return array Array for request's headers section like
+ * array('Authorization' => 'OAuth ...');
+ */
+ private function getOAuthHeader($uri, $params, $method = 'GET', $oAuthParams = null) {
+ $oAuthParams = $oAuthParams ? $oAuthParams : $this->getOAuthBaseParams();
+
+ // create baseString to encode for the sent parameters
+ $baseString = $method . '&';
+ $baseString .= $this->oauth_urlencode($uri) . "&";
+
+ // OAuth header does not include GET-Parameters
+ $signatureParams = array_merge($params, $oAuthParams);
+
+ // sorting the parameters
+ ksort($signatureParams);
+
+ $encodedParams = array();
+ foreach ($signatureParams as $key => $value) {
+ $encodedParams[] = $this->oauth_urlencode($key) . '=' . $this->oauth_urlencode($value);
+ }
+
+ $baseString .= $this->oauth_urlencode(implode('&', $encodedParams));
+
+ // encode the signature
+ $tokens = $this->getToken();
+ $hash = $this->hash_hmac_sha1($this->consumerSecret.'&'.$tokens['token_secret'], $baseString);
+ $signature = base64_encode($hash);
+
+ // add signature to oAuthParams
+ $oAuthParams['oauth_signature'] = $signature;
+
+ $oAuthEncoded = array();
+ foreach ($oAuthParams as $key => $value) {
+ $oAuthEncoded[] = $key . '="' . $this->oauth_urlencode($value) . '"';
+ }
+
+ return array('Authorization' => 'OAuth ' . implode(', ', $oAuthEncoded));
+ }
+
+ /**
+ * Requests the OAuth request token.
+ *
+ * @return void
+ */
+ public function getRequestToken() {
+ $result = $this->fetch(self::URI_REQUEST_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Requests the OAuth access tokens.
+ *
+ * This method requires the 'unauthorized' request tokens
+ * and, if successful will set the authorized request tokens.
+ *
+ * @return void
+ */
+ public function getAccessToken() {
+ $result = $this->fetch(self::URI_ACCESS_TOKEN, array(), 'POST');
+ if ($result['httpStatus'] == "200") {
+ $tokens = array();
+ parse_str($result['body'], $tokens);
+ $this->setToken($tokens['oauth_token'], $tokens['oauth_token_secret']);
+ return $this->getToken();
+ } else {
+ throw new Dropbox_Exception_RequestToken('We were unable to fetch request tokens. This likely means that your consumer key and/or secret are incorrect.');
+ }
+ }
+
+ /**
+ * Helper function to properly urlencode parameters.
+ * See http://php.net/manual/en/function.oauth-urlencode.php
+ *
+ * @param string $string
+ * @return string
+ */
+ private function oauth_urlencode($string) {
+ return str_replace('%E7', '~', rawurlencode($string));
+ }
+
+ /**
+ * Hash function for hmac_sha1; uses native function if available.
+ *
+ * @param string $key
+ * @param string $data
+ * @return string
+ */
+ private function hash_hmac_sha1($key, $data) {
+ if (function_exists('hash_hmac') && in_array('sha1', hash_algos())) {
+ return hash_hmac('sha1', $data, $key, true);
+ } else {
+ $blocksize = 64;
+ $hashfunc = 'sha1';
+ if (strlen($key) > $blocksize) {
+ $key = pack('H*', $hashfunc($key));
+ }
+
+ $key = str_pad($key, $blocksize, chr(0x00));
+ $ipad = str_repeat(chr(0x36), $blocksize);
+ $opad = str_repeat(chr(0x5c), $blocksize);
+ $hash = pack('H*', $hashfunc(( $key ^ $opad ) . pack('H*', $hashfunc(($key ^ $ipad) . $data))));
+
+ return $hash;
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/3rdparty/Dropbox/README.md b/3rdparty/Dropbox/README.md
new file mode 100644
index 00000000000..54e05db762b
--- /dev/null
+++ b/3rdparty/Dropbox/README.md
@@ -0,0 +1,31 @@
+Dropbox-php
+===========
+
+This PHP library allows you to easily integrate dropbox with PHP.
+
+The following PHP extension is required:
+
+* json
+
+The library makes use of OAuth. At the moment you can use either of these libraries:
+
+[PHP OAuth extension](http://pecl.php.net/package/oauth)
+[PEAR's HTTP_OAUTH package](http://pear.php.net/package/http_oauth)
+
+The extension is recommended, but if you can't install php extensions you should go for the pear package.
+Installing
+----------
+
+ pear channel-discover pear.dropbox-php.com
+ pear install dropbox-php/Dropbox-alpha
+
+Documentation
+-------------
+Check out the [documentation](http://www.dropbox-php.com/docs).
+
+Questions?
+----------
+
+[Dropbox-php Mailing list](http://groups.google.com/group/dropbox-php)
+[Official Dropbox developer forum](http://forums.dropbox.com/forum.php?id=5)
+
diff --git a/3rdparty/Dropbox/autoload.php b/3rdparty/Dropbox/autoload.php
new file mode 100644
index 00000000000..5388ea6334a
--- /dev/null
+++ b/3rdparty/Dropbox/autoload.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * This file registers a new autoload function using spl_autoload_register.
+ *
+ * @package Dropbox
+ * @copyright Copyright (C) 2010 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/dropbox-php/wiki/License MIT
+ */
+
+/**
+ * Autoloader function
+ *
+ * @param $className string
+ * @return void
+ */
+function Dropbox_autoload($className) {
+
+ if(strpos($className,'Dropbox_')===0) {
+
+ include dirname(__FILE__) . '/' . str_replace('_','/',substr($className,8)) . '.php';
+
+ }
+
+}
+
+spl_autoload_register('Dropbox_autoload');
+
diff --git a/3rdparty/Google/LICENSE.txt b/3rdparty/Google/LICENSE.txt
new file mode 100644
index 00000000000..8891c7ddc90
--- /dev/null
+++ b/3rdparty/Google/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Andy Smith
+
+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.
diff --git a/3rdparty/Google/OAuth.php b/3rdparty/Google/OAuth.php
new file mode 100755
index 00000000000..c7e75dd8266
--- /dev/null
+++ b/3rdparty/Google/OAuth.php
@@ -0,0 +1,751 @@
+<?php
+// vim: foldmethod=marker
+
+/* Generic exception class
+ */
+class OAuthException extends Exception {/*{{{*/
+ // pass
+}/*}}}*/
+
+class OAuthConsumer {/*{{{*/
+ public $key;
+ public $secret;
+
+ public function __construct($key, $secret, $callback_url=NULL) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ $this->callback_url = $callback_url;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthToken {/*{{{*/
+ // access tokens and request tokens
+ public $key;
+ public $secret;
+
+ /**
+ * key = the token
+ * secret = the token secret
+ */
+ function __construct($key, $secret) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ }/*}}}*/
+
+ /**
+ * generates the basic string serialization of a token that a server
+ * would respond to request_token and access_token calls with
+ */
+ function to_string() {/*{{{*/
+ return "oauth_token=" . OAuthUtil::urlencodeRFC3986($this->key) .
+ "&oauth_token_secret=" . OAuthUtil::urlencodeRFC3986($this->secret);
+ }/*}}}*/
+
+ function __toString() {/*{{{*/
+ return $this->to_string();
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod {/*{{{*/
+ public function check_signature(&$request, $consumer, $token, $signature) {
+ $built = $this->build_signature($request, $consumer, $token);
+ return $built == $signature;
+ }
+}/*}}}*/
+
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ function get_name() {/*{{{*/
+ return "HMAC-SHA1";
+ }/*}}}*/
+
+ public function build_signature($request, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ $key_parts = array(
+ $consumer->secret,
+ ($token) ? $token->secret : ""
+ );
+
+ $key_parts = array_map(array('OAuthUtil','urlencodeRFC3986'), $key_parts);
+ $key = implode('&', $key_parts);
+
+ return base64_encode( hash_hmac('sha1', $base_string, $key, true));
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ public function get_name() {/*{{{*/
+ return "RSA-SHA1";
+ }/*}}}*/
+
+ protected function fetch_public_cert(&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_public_cert not implemented");
+ }/*}}}*/
+
+ protected function fetch_private_cert($privKey) {//&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_private_cert not implemented");
+ }/*}}}*/
+
+ public function build_signature(&$request, $consumer, $token, $privKey) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the private key cert based on the request
+ //$cert = $this->fetch_private_cert($consumer->privKey);
+
+ //Pull the private key ID from the certificate
+ //$privatekeyid = openssl_get_privatekey($cert);
+
+ // hacked in
+ if ($privKey == '') {
+ $fp = fopen($GLOBALS['PRIV_KEY_FILE'], "r");
+ $privKey = fread($fp, 8192);
+ fclose($fp);
+ }
+ $privatekeyid = openssl_get_privatekey($privKey);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_sign($base_string, $signature, $privatekeyid);
+
+ //Release the key resource
+ openssl_free_key($privatekeyid);
+
+ return base64_encode($signature);
+ } /*}}}*/
+
+ public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/
+ $decoded_sig = base64_decode($signature);
+
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+
+ //Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+
+ //Check the computer signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+ //Release the key resource
+ openssl_free_key($publickeyid);
+
+ return $ok == 1;
+ } /*}}}*/
+}/*}}}*/
+
+class OAuthRequest {/*{{{*/
+ private $parameters;
+ private $http_method;
+ private $http_url;
+ // for debug purposes
+ public $base_string;
+ public static $version = '1.0';
+
+ function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $this->parameters = $parameters;
+ $this->http_method = $http_method;
+ $this->http_url = $http_url;
+ }/*}}}*/
+
+
+ /**
+ * attempt to build up a request from what was passed to the server
+ */
+ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
+ @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
+
+ $request_headers = OAuthRequest::get_headers();
+
+ // let the library user override things however they'd like, if they know
+ // which parameters to use then go for it, for example XMLRPC might want to
+ // do this
+ if ($parameters) {
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ // next check for the auth header, we need to do some extra stuff
+ // if that is the case, namely suck in the parameters from GET or POST
+ // so that we can include them in the signature
+ else if (@substr($request_headers['Authorization'], 0, 5) == "OAuth") {
+ $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
+ if ($http_method == "GET") {
+ $req_parameters = $_GET;
+ }
+ else if ($http_method = "POST") {
+ $req_parameters = $_POST;
+ }
+ $parameters = array_merge($header_parameters, $req_parameters);
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ }
+ else if ($http_method == "GET") {
+ $req = new OAuthRequest($http_method, $http_url, $_GET);
+ }
+ else if ($http_method == "POST") {
+ $req = new OAuthRequest($http_method, $http_url, $_POST);
+ }
+ return $req;
+ }/*}}}*/
+
+ /**
+ * pretty much a helper function to set up the request
+ */
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $defaults = array("oauth_version" => OAuthRequest::$version,
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
+ "oauth_consumer_key" => $consumer->key);
+ $parameters = array_merge($defaults, $parameters);
+
+ if ($token) {
+ $parameters['oauth_token'] = $token->key;
+ }
+
+ // oauth v1.0a
+ /*if (isset($_REQUEST['oauth_verifier'])) {
+ $parameters['oauth_verifier'] = $_REQUEST['oauth_verifier'];
+ }*/
+
+
+ return new OAuthRequest($http_method, $http_url, $parameters);
+ }/*}}}*/
+
+ public function set_parameter($name, $value) {/*{{{*/
+ $this->parameters[$name] = $value;
+ }/*}}}*/
+
+ public function get_parameter($name) {/*{{{*/
+ return $this->parameters[$name];
+ }/*}}}*/
+
+ public function get_parameters() {/*{{{*/
+ return $this->parameters;
+ }/*}}}*/
+
+ /**
+ * Returns the normalized parameters of the request
+ *
+ * This will be all (except oauth_signature) parameters,
+ * sorted first by key, and if duplicate keys, then by
+ * value.
+ *
+ * The returned string will be all the key=value pairs
+ * concated by &.
+ *
+ * @return string
+ */
+ public function get_signable_parameters() {/*{{{*/
+ // Grab all parameters
+ $params = $this->parameters;
+
+ // Remove oauth_signature if present
+ if (isset($params['oauth_signature'])) {
+ unset($params['oauth_signature']);
+ }
+
+ // Urlencode both keys and values
+ $keys = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_keys($params));
+ $values = array_map(array('OAuthUtil', 'urlencodeRFC3986'), array_values($params));
+ $params = array_combine($keys, $values);
+
+ // Sort by keys (natsort)
+ uksort($params, 'strnatcmp');
+
+if(isset($params['title']) && isset($params['title-exact'])) {
+ $temp = $params['title-exact'];
+ $title = $params['title'];
+
+ unset($params['title']);
+ unset($params['title-exact']);
+
+ $params['title-exact'] = $temp;
+ $params['title'] = $title;
+}
+
+ // Generate key=value pairs
+ $pairs = array();
+ foreach ($params as $key=>$value ) {
+ if (is_array($value)) {
+ // If the value is an array, it's because there are multiple
+ // with the same key, sort them, then add all the pairs
+ natsort($value);
+ foreach ($value as $v2) {
+ $pairs[] = $key . '=' . $v2;
+ }
+ } else {
+ $pairs[] = $key . '=' . $value;
+ }
+ }
+
+ // Return the pairs, concated with &
+ return implode('&', $pairs);
+ }/*}}}*/
+
+ /**
+ * Returns the base string of this request
+ *
+ * The base string defined as the method, the url
+ * and the parameters (normalized), each urlencoded
+ * and the concated with &.
+ */
+ public function get_signature_base_string() {/*{{{*/
+ $parts = array(
+ $this->get_normalized_http_method(),
+ $this->get_normalized_http_url(),
+ $this->get_signable_parameters()
+ );
+
+ $parts = array_map(array('OAuthUtil', 'urlencodeRFC3986'), $parts);
+
+ return implode('&', $parts);
+ }/*}}}*/
+
+ /**
+ * just uppercases the http method
+ */
+ public function get_normalized_http_method() {/*{{{*/
+ return strtoupper($this->http_method);
+ }/*}}}*/
+
+/**
+ * parses the url and rebuilds it to be
+ * scheme://host/path
+ */
+ public function get_normalized_http_url() {
+ $parts = parse_url($this->http_url);
+
+ $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
+ $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80');
+ $host = (isset($parts['host'])) ? strtolower($parts['host']) : '';
+ $path = (isset($parts['path'])) ? $parts['path'] : '';
+
+ if (($scheme == 'https' && $port != '443')
+ || ($scheme == 'http' && $port != '80')) {
+ $host = "$host:$port";
+ }
+ return "$scheme://$host$path";
+ }
+
+ /**
+ * builds a url usable for a GET request
+ */
+ public function to_url() {/*{{{*/
+ $out = $this->get_normalized_http_url() . "?";
+ $out .= $this->to_postdata();
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the data one would send in a POST request
+ */
+ public function to_postdata() {/*{{{*/
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ $total[] = OAuthUtil::urlencodeRFC3986($k) . "=" . OAuthUtil::urlencodeRFC3986($v);
+ }
+ $out = implode("&", $total);
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the Authorization: header
+ */
+ public function to_header() {/*{{{*/
+ $out ='Authorization: OAuth ';
+ $total = array();
+
+ /*
+ $sig = $this->parameters['oauth_signature'];
+ unset($this->parameters['oauth_signature']);
+ uksort($this->parameters, 'strnatcmp');
+ $this->parameters['oauth_signature'] = $sig;
+ */
+
+ foreach ($this->parameters as $k => $v) {
+ if (substr($k, 0, 5) != "oauth") continue;
+ $out .= OAuthUtil::urlencodeRFC3986($k) . '="' . OAuthUtil::urlencodeRFC3986($v) . '", ';
+ }
+ $out = substr_replace($out, '', strlen($out) - 2);
+
+ return $out;
+ }/*}}}*/
+
+ public function __toString() {/*{{{*/
+ return $this->to_url();
+ }/*}}}*/
+
+
+ public function sign_request($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name());
+ $signature = $this->build_signature($signature_method, $consumer, $token, $privKey);
+ $this->set_parameter("oauth_signature", $signature);
+ }/*}}}*/
+
+ public function build_signature($signature_method, $consumer, $token, $privKey=NULL) {/*{{{*/
+ $signature = $signature_method->build_signature($this, $consumer, $token, $privKey);
+ return $signature;
+ }/*}}}*/
+
+ /**
+ * util function: current timestamp
+ */
+ private static function generate_timestamp() {/*{{{*/
+ return time();
+ }/*}}}*/
+
+ /**
+ * util function: current nonce
+ */
+ private static function generate_nonce() {/*{{{*/
+ $mt = microtime();
+ $rand = mt_rand();
+
+ return md5($mt . $rand); // md5s look nicer than numbers
+ }/*}}}*/
+
+ /**
+ * util function for turning the Authorization: header into
+ * parameters, has to do some unescaping
+ */
+ private static function split_header($header) {/*{{{*/
+ // this should be a regex
+ // error cases: commas in parameter values
+ $parts = explode(",", $header);
+ $out = array();
+ foreach ($parts as $param) {
+ $param = ltrim($param);
+ // skip the "realm" param, nobody ever uses it anyway
+ if (substr($param, 0, 5) != "oauth") continue;
+
+ $param_parts = explode("=", $param);
+
+ // rawurldecode() used because urldecode() will turn a "+" in the
+ // value into a space
+ $out[$param_parts[0]] = rawurldecode(substr($param_parts[1], 1, -1));
+ }
+ return $out;
+ }/*}}}*/
+
+ /**
+ * helper to try to sort out headers for people who aren't running apache
+ */
+ private static function get_headers() {/*{{{*/
+ if (function_exists('apache_request_headers')) {
+ // we need this to get the actual Authorization: header
+ // because apache tends to tell us it doesn't exist
+ return apache_request_headers();
+ }
+ // otherwise we don't have apache and are just going to have to hope
+ // that $_SERVER actually contains what we need
+ $out = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) == "HTTP_") {
+ // this is chaos, basically it is just there to capitalize the first
+ // letter of every word that is not an initial HTTP and strip HTTP
+ // code from przemek
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
+ $out[$key] = $value;
+ }
+ }
+ return $out;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthServer {/*{{{*/
+ protected $timestamp_threshold = 300; // in seconds, five minutes
+ protected $version = 1.0; // hi blaine
+ protected $signature_methods = array();
+
+ protected $data_store;
+
+ function __construct($data_store) {/*{{{*/
+ $this->data_store = $data_store;
+ }/*}}}*/
+
+ public function add_signature_method($signature_method) {/*{{{*/
+ $this->signature_methods[$signature_method->get_name()] =
+ $signature_method;
+ }/*}}}*/
+
+ // high level functions
+
+ /**
+ * process a request_token request
+ * returns the request token on success
+ */
+ public function fetch_request_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // no token required for the initial token request
+ $token = NULL;
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_request_token($consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * process an access_token request
+ * returns the access token on success
+ */
+ public function fetch_access_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // requires authorized request token
+ $token = $this->get_token($request, $consumer, "request");
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_access_token($token, $consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * verify an api call, checks all the parameters
+ */
+ public function verify_request(&$request) {/*{{{*/
+ $this->get_version($request);
+ $consumer = $this->get_consumer($request);
+ $token = $this->get_token($request, $consumer, "access");
+ $this->check_signature($request, $consumer, $token);
+ return array($consumer, $token);
+ }/*}}}*/
+
+ // Internals from here
+ /**
+ * version 1
+ */
+ private function get_version(&$request) {/*{{{*/
+ $version = $request->get_parameter("oauth_version");
+ if (!$version) {
+ $version = 1.0;
+ }
+ if ($version && $version != $this->version) {
+ throw new OAuthException("OAuth version '$version' not supported");
+ }
+ return $version;
+ }/*}}}*/
+
+ /**
+ * figure out the signature with some defaults
+ */
+ private function get_signature_method(&$request) {/*{{{*/
+ $signature_method =
+ @$request->get_parameter("oauth_signature_method");
+ if (!$signature_method) {
+ $signature_method = "PLAINTEXT";
+ }
+ if (!in_array($signature_method,
+ array_keys($this->signature_methods))) {
+ throw new OAuthException(
+ "Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods))
+ );
+ }
+ return $this->signature_methods[$signature_method];
+ }/*}}}*/
+
+ /**
+ * try to find the consumer for the provided request's consumer key
+ */
+ private function get_consumer(&$request) {/*{{{*/
+ $consumer_key = @$request->get_parameter("oauth_consumer_key");
+ if (!$consumer_key) {
+ throw new OAuthException("Invalid consumer key");
+ }
+
+ $consumer = $this->data_store->lookup_consumer($consumer_key);
+ if (!$consumer) {
+ throw new OAuthException("Invalid consumer");
+ }
+
+ return $consumer;
+ }/*}}}*/
+
+ /**
+ * try to find the token for the provided request's token key
+ */
+ private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/
+ $token_field = @$request->get_parameter('oauth_token');
+ $token = $this->data_store->lookup_token(
+ $consumer, $token_type, $token_field
+ );
+ if (!$token) {
+ throw new OAuthException("Invalid $token_type token: $token_field");
+ }
+ return $token;
+ }/*}}}*/
+
+ /**
+ * all-in-one function to check the signature on a request
+ * should guess the signature method appropriately
+ */
+ private function check_signature(&$request, $consumer, $token) {/*{{{*/
+ // this should probably be in a different method
+ $timestamp = @$request->get_parameter('oauth_timestamp');
+ $nonce = @$request->get_parameter('oauth_nonce');
+
+ $this->check_timestamp($timestamp);
+ $this->check_nonce($consumer, $token, $nonce, $timestamp);
+
+ $signature_method = $this->get_signature_method($request);
+
+ $signature = $request->get_parameter('oauth_signature');
+ $valid_sig = $signature_method->check_signature(
+ $request,
+ $consumer,
+ $token,
+ $signature
+ );
+
+ if (!$valid_sig) {
+ throw new OAuthException("Invalid signature");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the timestamp is new enough
+ */
+ private function check_timestamp($timestamp) {/*{{{*/
+ // verify that timestamp is recentish
+ $now = time();
+ if ($now - $timestamp > $this->timestamp_threshold) {
+ throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the nonce is not repeated
+ */
+ private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // verify that the nonce is uniqueish
+ $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
+ if ($found) {
+ throw new OAuthException("Nonce already used: $nonce");
+ }
+ }/*}}}*/
+
+
+
+}/*}}}*/
+
+class OAuthDataStore {/*{{{*/
+ function lookup_consumer($consumer_key) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function fetch_request_token($consumer) {/*{{{*/
+ // return a new token attached to this consumer
+ }/*}}}*/
+
+ function fetch_access_token($token, $consumer) {/*{{{*/
+ // return a new access token attached to this consumer
+ // for the user associated with this token if the request token
+ // is authorized
+ // should also invalidate the request token
+ }/*}}}*/
+
+}/*}}}*/
+
+
+/* A very naive dbm-based oauth storage
+ */
+class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
+ private $dbh;
+
+ function __construct($path = "oauth.gdbm") {/*{{{*/
+ $this->dbh = dba_popen($path, 'c', 'gdbm');
+ }/*}}}*/
+
+ function __destruct() {/*{{{*/
+ dba_close($this->dbh);
+ }/*}}}*/
+
+ function lookup_consumer($consumer_key) {/*{{{*/
+ $rv = dba_fetch("consumer_$consumer_key", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthConsumer)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ $rv = dba_fetch("${token_type}_${token}", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthToken)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ return dba_exists("nonce_$nonce", $this->dbh);
+ }/*}}}*/
+
+ function new_token($consumer, $type="request") {/*{{{*/
+ $key = md5(time());
+ $secret = time() + time();
+ $token = new OAuthToken($key, md5(md5($secret)));
+ if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
+ throw new OAuthException("doooom!");
+ }
+ return $token;
+ }/*}}}*/
+
+ function new_request_token($consumer) {/*{{{*/
+ return $this->new_token($consumer, "request");
+ }/*}}}*/
+
+ function new_access_token($token, $consumer) {/*{{{*/
+
+ $token = $this->new_token($consumer, 'access');
+ dba_delete("request_" . $token->key, $this->dbh);
+ return $token;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthUtil {/*{{{*/
+ public static function urlencodeRFC3986($string) {/*{{{*/
+ return str_replace('%7E', '~', rawurlencode($string));
+ }/*}}}*/
+
+ public static function urldecodeRFC3986($string) {/*{{{*/
+ return rawurldecode($string);
+ }/*}}}*/
+}/*}}}*/
+
+?> \ No newline at end of file
diff --git a/3rdparty/Google/common.inc.php b/3rdparty/Google/common.inc.php
new file mode 100755
index 00000000000..57185cdc4d8
--- /dev/null
+++ b/3rdparty/Google/common.inc.php
@@ -0,0 +1,185 @@
+<?php
+/* Copyright (c) 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Eric Bidelman <e.bidelman@google.com>
+ */
+
+$PRIV_KEY_FILE = '/path/to/your/rsa_private_key.pem';
+
+// OAuth library - http://oauth.googlecode.com/svn/code/php/
+require_once('OAuth.php');
+
+// Google's accepted signature methods
+$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
+$rsa_method = new OAuthSignatureMethod_RSA_SHA1();
+$SIG_METHODS = array($rsa_method->get_name() => $rsa_method,
+ $hmac_method->get_name() => $hmac_method);
+
+/**
+ * Makes an HTTP request to the specified URL
+ *
+ * @param string $http_method The HTTP method (GET, POST, PUT, DELETE)
+ * @param string $url Full URL of the resource to access
+ * @param array $extraHeaders (optional) Additional headers to include in each
+ * request. Elements are header/value pair strings ('Host: example.com')
+ * @param string $postData (optional) POST/PUT request body
+ * @param bool $returnResponseHeaders True if resp. headers should be returned.
+ * @return string Response body from the server
+ */
+function send_signed_request($http_method, $url, $extraHeaders=null,
+ $postData=null, $returnResponseHeaders=true) {
+ $curl = curl_init($url);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_FAILONERROR, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ // Return request headers in the reponse
+// curl_setopt($curl, CURLINFO_HEADER_OUT, true);
+
+ // Return response headers ni the response?
+ if ($returnResponseHeaders) {
+ curl_setopt($curl, CURLOPT_HEADER, true);
+ }
+
+ $headers = array();
+ //$headers[] = 'GData-Version: 2.0'; // use GData v2 by default
+ if (is_array($extraHeaders)) {
+ $headers = array_merge($headers, $extraHeaders);
+ }
+
+ // Setup default curl options for each type of HTTP request.
+ // This is also a great place to add additional headers for each request.
+ switch($http_method) {
+ case 'GET':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ break;
+ case 'POST':
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
+ break;
+ case 'PUT':
+ $headers[] = 'If-Match: *';
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+ 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);
+ break;
+ default:
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
+ }
+
+ // Execute the request. If an error occures, fill the response body with it.
+ $response = curl_exec($curl);
+ if (!$response) {
+ $response = curl_error($curl);
+ }
+
+ // Add server's response headers to our response body
+ $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response;
+
+ curl_close($curl);
+
+ return $response;
+}
+
+/**
+* Takes XML as a string and returns it nicely indented
+*
+* @param string $xml The xml to beautify
+* @param boolean $html_output True if returned XML should be escaped for HTML.
+* @return string The beautified xml
+*/
+function xml_pretty_printer($xml, $html_output=false) {
+ $xml_obj = new SimpleXMLElement($xml);
+ $level = 2;
+
+ // Get an array containing each XML element
+ $xml = explode("\n", preg_replace('/>\s*</', ">\n<", $xml_obj->asXML()));
+
+ // Hold current indentation level
+ $indent = 0;
+
+ $pretty = array();
+
+ // Shift off opening XML tag if present
+ if (count($xml) && preg_match('/^<\?\s*xml/', $xml[0])) {
+ $pretty[] = array_shift($xml);
+ }
+
+ foreach ($xml as $el) {
+ if (preg_match('/^<([\w])+[^>\/]*>$/U', $el)) {
+ // opening tag, increase indent
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ $indent += $level;
+ } else {
+ if (preg_match('/^<\/.+>$/', $el)) {
+ $indent -= $level; // closing tag, decrease indent
+ }
+ if ($indent < 0) {
+ $indent += $level;
+ }
+ $pretty[] = str_repeat(' ', $indent) . $el;
+ }
+ }
+
+ $xml = implode("\n", $pretty);
+ return $html_output ? htmlentities($xml) : $xml;
+}
+
+/**
+ * Joins key/value pairs by $inner_glue and each pair together by $outer_glue.
+ *
+ * Example: implode_assoc('=', '&', array('a' => 1, 'b' => 2)) === 'a=1&b=2'
+ *
+ * @param string $inner_glue What to implode each key/value pair with
+ * @param string $outer_glue What to impode each key/value string subset with
+ * @param array $array Associative array of query parameters
+ * @return string Urlencoded string of query parameters
+ */
+function implode_assoc($inner_glue, $outer_glue, $array) {
+ $output = array();
+ foreach($array as $key => $item) {
+ $output[] = $key . $inner_glue . urlencode($item);
+ }
+ return implode($outer_glue, $output);
+}
+
+/**
+ * Explodes a string of key/value url parameters into an associative array.
+ * This method performs the compliment operations of implode_assoc().
+ *
+ * Example: explode_assoc('=', '&', 'a=1&b=2') === array('a' => 1, 'b' => 2)
+ *
+ * @param string $inner_glue What each key/value pair is joined with
+ * @param string $outer_glue What each set of key/value pairs is joined with.
+ * @param array $array Associative array of query parameters
+ * @return array Urlencoded string of query parameters
+ */
+function explode_assoc($inner_glue, $outer_glue, $params) {
+ $tempArr = explode($outer_glue, $params);
+ foreach($tempArr as $val) {
+ $pos = strpos($val, $inner_glue);
+ $key = substr($val, 0, $pos);
+ $array2[$key] = substr($val, $pos + 1, strlen($val));
+ }
+ return $array2;
+}
+
+?> \ No newline at end of file
diff --git a/3rdparty/aws-sdk/README.md b/3rdparty/aws-sdk/README.md
new file mode 100644
index 00000000000..7e55f76b3b2
--- /dev/null
+++ b/3rdparty/aws-sdk/README.md
@@ -0,0 +1,136 @@
+# AWS SDK for PHP
+
+The AWS SDK for PHP enables developers to build solutions for Amazon Simple Storage Service (Amazon S3),
+Amazon Elastic Compute Cloud (Amazon EC2), Amazon SimpleDB, and more. With the AWS SDK for PHP, developers
+can get started in minutes with a single, downloadable package.
+
+The SDK features:
+
+* **AWS PHP Libraries:** Build PHP applications on top of APIs that take the complexity out of coding directly
+ against a web service interface. The toolkit provides APIs that hide much of the lower-level implementation.
+* **Code Samples:** Practical examples for how to use the toolkit to build applications.
+* **Documentation:** Complete SDK reference documentation with samples demonstrating how to use the SDK.
+* **PEAR package:** The ability to install the AWS SDK for PHP as a PEAR package.
+* **SDK Compatibility Test:** Includes both an HTML-based and a CLI-based SDK Compatibility Test that you can
+ run on your server to determine whether or not your PHP environment meets the minimum requirements.
+
+For more information about the AWS SDK for PHP, including a complete list of supported services, see
+[aws.amazon.com/sdkforphp](http://aws.amazon.com/sdkforphp).
+
+
+## Signing up for Amazon Web Services
+
+Before you can begin, you must sign up for each service you want to use.
+
+To sign up for a service:
+
+* Go to the home page for the service. You can find a list of services on
+ [aws.amazon.com/products](http://aws.amazon.com/products).
+* Click the Sign Up button on the top right corner of the page. If you don't already have an AWS account, you
+ are prompted to create one as part of the sign up process.
+* Follow the on-screen instructions.
+* AWS sends you a confirmation e-mail after the sign-up process is complete. At any time, you can view your
+ current account activity and manage your account by going to [aws.amazon.com](http://aws.amazon.com) and
+ clicking "Your Account".
+
+
+## Source
+The source tree for includes the following files and directories:
+
+* `_compatibility_test` -- Includes both an HTML-based and a CLI-based SDK Compatibility Test that you can
+ run on your server to determine whether or not your PHP environment meets the minimum requirements.
+* `_docs` -- Informational documents, the contents of which should be fairly self-explanatory.
+* `_samples` -- Code samples that you can run out of the box.
+* `extensions` -- Extra code that can be used to enhance usage of the SDK, but isn't a service class or a
+ third-party library.
+* `lib` -- Contains any third-party libraries that the SDK depends on. The licenses for these projects will
+ always be Apache 2.0-compatible.
+* `services` -- Contains the service-specific classes that communicate with AWS. These classes are always
+ prefixed with `Amazon`.
+* `utilities` -- Contains any utility-type methods that the SDK uses. Includes extensions to built-in PHP
+ classes, as well as new functionality that is entirely custom. These classes are always prefixed with `CF`.
+* `README` -- The document you're reading right now.
+* `config-sample.inc.php` -- A sample configuration file that should be filled out and renamed to `config.inc.php`.
+* `sdk.class.php` -- The SDK loader that you would include in your projects. Contains the base functionality
+ that the rest of the SDK depends on.
+
+
+## Minimum Requirements in a nutshell
+
+* You are at least an intermediate-level PHP developer and have a basic understanding of object-oriented PHP.
+* You have a valid AWS account, and you've already signed up for the services you want to use.
+* The PHP interpreter, version 5.2 or newer. PHP 5.2.17 or 5.3.x is highly recommended for use with the AWS SDK for PHP.
+* The cURL PHP extension (compiled with the [OpenSSL](http://openssl.org) libraries for HTTPS support).
+* The ability to read from and write to the file system via [file_get_contents()](http://php.net/file_get_contents) and [file_put_contents()](http://php.net/file_put_contents).
+
+If you're not sure whether your PHP environment meets these requirements, run the
+[SDK Compatibility Test](http://github.com/amazonwebservices/aws-sdk-for-php/tree/master/_compatibility_test/) script
+included in the SDK download.
+
+
+## Installation
+
+### Via GitHub
+
+[Git](http://git-scm.com) is an extremely fast, efficient, distributed version control system ideal for the
+collaborative development of software. [GitHub](http://github.com/amazonwebservices) is the best way to
+collaborate with others. Fork, send pull requests and manage all your public and private git repositories.
+We believe that GitHub is the ideal service for working collaboratively with the open source PHP community.
+
+Git is primarily a command-line tool. GitHub provides instructions for installing Git on
+[Mac OS X](http://help.github.com/mac-git-installation/), [Windows](http://help.github.com/win-git-installation/),
+and [Linux](http://help.github.com/linux-git-installation/). If you're unfamiliar with Git, there are a variety
+of resources on the net that will help you learn more:
+
+* [Git Immersion](http://gitimmersion.com) is a guided tour that walks through the fundamentals of Git, inspired
+ by the premise that to know a thing is to do it.
+* The [PeepCode screencast on Git](https://peepcode.com/products/git) ($12) will teach you how to install and
+ use Git. You'll learn how to create a repository, use branches, and work with remote repositories.
+* [Git Reference](http://gitref.org) is meant to be a quick reference for learning and remembering the most
+ important and commonly used Git commands.
+* [Git Ready](http://gitready.com) provides a collection of Git tips and tricks.
+* If you want to dig even further, I've [bookmarked other Git references](http://pinboard.in/u:skyzyx/t:git).
+
+If you're comfortable working with Git and/or GitHub, you can pull down the source code as follows:
+
+ git clone git://github.com/amazonwebservices/aws-sdk-for-php.git AWSSDKforPHP
+ cd ./AWSSDKforPHP
+
+### Via PEAR
+
+[PEAR](http://pear.php.net) stands for the _PHP Extension and Application Repository_ and is a framework and
+distribution system for reusable PHP components. It is the PHP equivalent to package management software such as
+[MacPorts](http://macports.org) and [Homebrew](https://github.com/mxcl/homebrew) for Mac OS X,
+[Yum](http://fedoraproject.org/wiki/Tools/yum) and [Apt](http://wiki.debian.org/Apt) for GNU/Linux,
+[RubyGems](http://rubygems.org) for Ruby, [Easy Install](http://packages.python.org/distribute/easy_install.html)
+for Python, [Maven](http://maven.apache.org) for Java, and [NPM](http://npm.mape.me) for Node.js.
+
+PEAR packages are very easy to install, and are available in your PHP environment path so that they are accessible
+to any PHP project. PEAR packages are not specific to your project, but rather to the machine that they're
+installed on.
+
+From the command-line, you can install the SDK with PEAR as follows:
+
+ pear channel-discover pear.amazonwebservices.com
+ pear install aws/sdk
+
+You may need to use `sudo` for the above commands. Once the SDK has been installed via PEAR, you can load it into
+your project with:
+
+ require_once 'AWSSDKforPHP/sdk.class.php';
+
+### Configuration
+
+1. Copy the contents of [config-sample.inc.php](https://github.com/amazonwebservices/aws-sdk-for-php/raw/master/config-sample.inc.php)
+ and add your credentials as instructed in the file.
+2. Move your file to `~/.aws/sdk/config.inc.php`.
+3. Make sure that `getenv('HOME')` points to your user directory. If not you'll need to set
+ `putenv('HOME=<your-user-directory>')`.
+
+
+## Additional Information
+
+* AWS SDK for PHP: <http://aws.amazon.com/sdkforphp>
+* Documentation: <http://docs.amazonwebservices.com/AWSSDKforPHP/latest/>
+* License: <http://aws.amazon.com/apache2.0/>
+* Discuss: <http://aws.amazon.com/forums>
diff --git a/3rdparty/aws-sdk/_compatibility_test/README.md b/3rdparty/aws-sdk/_compatibility_test/README.md
new file mode 100644
index 00000000000..9e2f2d89409
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/README.md
@@ -0,0 +1,37 @@
+# Compatibility Test
+
+## Via your web browser
+
+1. Upload `sdk_compatibility_test.php` to the web-accessible root of your website.
+For example, if your website is `www.example.com`, upload it so that you can get
+to it at `www.example.com/sdk_compatibility_test.php`
+
+2. Open your web browser and go to the page you just uploaded.
+
+
+## Via the command line
+
+### Windows
+
+1. Upload `sdk_compatibility_test_cli.php` to your server via SFTP.
+
+2. SSH/RDP into the machine, and find the directory where you uploaded the test.
+
+3. Run the test, and review the results:
+
+ php .\sdk_compatibility_test_cli.php
+
+
+### Non-Windows (Mac or *nix)
+
+1. Upload `sdk_compatibility_test_cli.php` to your server via SFTP.
+
+2. SSH into the machine, and find the directory where you uploaded the test.
+
+3. Set the executable bit:
+
+ chmod +x ./sdk_compatibility_test_cli.php
+
+4. Run the test, and review the results:
+
+ ./sdk_compatibility_test_cli.php
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php
new file mode 100644
index 00000000000..c17ec33d72e
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility.inc.php
@@ -0,0 +1,75 @@
+<?php
+
+define('REQUIREMENTS_ALL_MET', 100);
+define('REQUIREMENTS_MIN_MET', 10);
+define('REQUIREMENTS_NOT_MET', 0);
+
+// Required
+$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '5.2.0', '>='));
+$simplexml_ok = extension_loaded('simplexml');
+$dom_ok = extension_loaded('dom');
+$json_ok = (extension_loaded('json') && function_exists('json_encode') && function_exists('json_decode'));
+$spl_ok = extension_loaded('spl');
+$pcre_ok = extension_loaded('pcre');
+$curl_ok = false;
+if (function_exists('curl_version'))
+{
+ $curl_version = curl_version();
+ $curl_ok = (function_exists('curl_exec') && in_array('https', $curl_version['protocols'], true));
+}
+$file_ok = (function_exists('file_get_contents') && function_exists('file_put_contents'));
+
+// Optional, but recommended
+$openssl_ok = (extension_loaded('openssl') && function_exists('openssl_sign'));
+$zlib_ok = extension_loaded('zlib');
+
+// Optional
+$apc_ok = extension_loaded('apc');
+$xcache_ok = extension_loaded('xcache');
+$memcached_ok = extension_loaded('memcached');
+$memcache_ok = extension_loaded('memcache');
+$mc_ok = ($memcache_ok || $memcached_ok);
+$pdo_ok = extension_loaded('pdo');
+$pdo_sqlite_ok = extension_loaded('pdo_sqlite');
+$sqlite2_ok = extension_loaded('sqlite');
+$sqlite3_ok = extension_loaded('sqlite3');
+$sqlite_ok = ($pdo_ok && $pdo_sqlite_ok && ($sqlite2_ok || $sqlite3_ok));
+
+// Other
+$int64_ok = (PHP_INT_MAX === 9223372036854775807);
+$ini_memory_limit = get_ini('memory_limit');
+$ini_open_basedir = get_ini('open_basedir');
+$ini_safe_mode = get_ini('safe_mode');
+$ini_zend_enable_gc = get_ini('zend.enable_gc');
+
+if ($php_ok && $int64_ok && $curl_ok && $simplexml_ok && $dom_ok && $spl_ok && $json_ok && $pcre_ok && $file_ok && $openssl_ok && $zlib_ok && ($apc_ok || $xcache_ok || $mc_ok || $sqlite_ok))
+{
+ $compatiblity = REQUIREMENTS_ALL_MET;
+}
+elseif ($php_ok && $curl_ok && $simplexml_ok && $dom_ok && $spl_ok && $json_ok && $pcre_ok && $file_ok)
+{
+ $compatiblity = REQUIREMENTS_MIN_MET;
+}
+else
+{
+ $compatiblity = REQUIREMENTS_NOT_MET;
+}
+
+function get_ini($config)
+{
+ $cfg_value = ini_get($config);
+
+ if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
+ {
+ return false;
+ }
+ elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
+ {
+ return true;
+ }
+}
+
+function is_windows()
+{
+ return strtolower(substr(PHP_OS, 0, 3)) === 'win';
+}
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php
new file mode 100644
index 00000000000..b36a38ab35e
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test.php
@@ -0,0 +1,789 @@
+<?php
+if (isset($_GET['logopng']))
+{
+ $data = <<<IMAGE
+iVBORw0KGgoAAAANSUhEUgAAASwAAABwCAYAAACkRk1NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
+AAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAU
+dEVYdENyZWF0aW9uIFRpbWUAOS80LzEwZyhWjQAAGJpJREFUeNrtnQ2wXEWVgJvwjKksP2MKMAKV
+HXbZIqUgU1CLWBtkLLZc1IU3CK4ssDAEFVlhM7qIyhYwiqALCqOFIkbNGDSsSszsqllA1zfhT0SX
+DD8aFgJv+DU/JG9CfpYErNluc+6m35m+ffvvvrkz75yqU8mbudO3b9/u755z+txuxkhISEhISEhI
+SEgyJa8tnlvgWgUtZqxuOa4lqFtF1JXuGAnJ9AJUHgZ/g2uHa1ehTYBEoQ/1K3KtcW3F1K3Ntc61
+LK6F7igJyfABqgyDvB0DAZ12AG6VNAABFl4FINl10BYATlhiObrjJCSDBajIjdJZKT4qWzg5h/qZ
+WHg+2syie0tCQqKGwYoUIBCnq23AAKBaPUV1mwBok9VFQjIAVtZ5AK+JwCAY47rIxz0EsC5KAV7i
+WpdwHaVeQEIyuAAbhYHsCq8VAMBcCnXzhdc4QYqEZHBg1IR4kFFMyQJexpCCmJmIa3XQ50WIedVM
+Zhwt4CUgdaNFmVFQv0Y9hoSk/8CSB3PDdMpfgte4DaTA5YxmHicFzhXAUgXsS5ZurSuk8KRDk3oM
+CUm2gIWn/IOkI0iQauisnwRg4XQJI3gZ1q9gMDNKwCIhyTCwVPAqWJSdN4GUI7BUuV5WqRISpEzz
+ywhYJCQDAizsminjShp3Kk1gdWPc2pwmXuaSBEvAIiEZQGDJWkTleaUWBAKWEjCQEBqsPBISEgIW
+AYuEhISARcAiISFgEbBISEgIWAQsEhISApa7UqY7CQkBa2CAVaUeQ0JCwCJgkZCQELAIWCQkBCwC
+FgkJCQGLgEVCQkLAImCRkBCwCFgkJCQELAIWCQkJAYuARUJCwCJgkZCQELAIWCQkJNkE1jgqq+C5
+L2JoYFWox5CQ9BdYJc/dnn2Blbibjce+iCGAtdp341cSEpLw4MLbYqUJLOMttzzh5QqsFQQpEpLh
+hJcpsJwh5QEvG2Cltjs1CUnWB3wRD+SM1a8AdcwFgJcOWMEhZQmvJGCNEaRIpqtFUlLsZOy0X16K
+sSrVHnwN081SJXit1gBrDMBR7OO1jgJgawpgUUyKZFpCKtp/r2ETBA61k7IhXKJNTDsWm6VWLbZz
+p4FPQpJxV6rqukmo6WakASDaDFS/YFvBk5CQ9NeVCqkdVzg4bLfuWr9MuLYkJCR6GNwIweNuyhoF
+qE+0tKgWoZhSWjoBsalR6hkkJIMBr9BwCDaLlhK8CFIkJEMALx84GEPKNaAN9TvPMYPd2NKDwH5q
+LuLIjL1zXItcK1yrSMXn+am87+J8cF6hBYffR78t9qG9SlPdXinfi6LPvQhUh4JUh3y/YGQVEDeE
+l/juKsPyJgX2Fd83bWJehkmgVhCFwH5LldYQCApigLW4dg20DcfnLQd2VaM5xbFtxbk7XOvy8TED
+qxFTd3GN5QCQqli2V812gME5mgG1YQMa6Be1hOtsQj1zDuCJ6wsVRT3qcO/j+kN+qoGlms0rGQ7m
+CA5jptP+usB5DLCcAvYIXmMekIpNHPUceDXDQRenVYunc2I50JE7Buft4MEH19MwrHfL1kqQ2quT
+dnvB+bopaDWlftHBoEk4h/Y+oX5j2h/K/QJWkNk8xXmKJrN7BsDqKhJBvWfzLGYfiwFgVYixYFy0
+HgJYFrDqgRYMspbDIMtbtFcrUHu1TCySfgArQL9oGl5bMwlYUBfb85f6DSwVvIzhEJMN3w0MLGd4
+OaZIFD1hlfe0ElRaCwCspsvgh/JdLcWmocURur3qWQOWwwPDGciGwHIBZ8fWPU0TWEZwcIFUQGCp
+suyD1i8AsFopDYaCB7B8nupVz3oXfQZXiuedMmA5Wqg6bXi2acXj3JWsAiv1FTg9gZVK/XyAJfz8
+lAaC1mowAFY/taapd6kf7dUHYNVSOFfFA1g+D7AWAWt4gNUytFjyCDYmv2sPKLCantZVDbVXwfB3
+HZ/AtKO7lI8JERgFtaW0gqqB+xjrnqVotU4K2hOwBhhYhh2zrHEZ2q4dxRJYdRgQNccnbfR70wHf
+0VyzU3tZPBy84y0W7lMl5vd1F3ffMCheDQCshpTy0A7hbhOwBgNYRZ8AtGGsKOcJrIJHbKWFLQjT
+maaU2quc9sCymEBpekBZ5zLXXaxuC2CVHfsDAWtILKyWi7VgAZ2ix2/rnnG3gqsF4dhelbTaK7CL
+H5u+Ydi2ec8YX8ERWPV+PQgIWBmJYSkGVPRaSSWAheYLrKJHALrlY+lY5GIVobxU28uwPqazo6XQ
+FpKlhVZ1BFbBoz9UCVhDBqwUXEovYCWcu+3hthT7EaRNE1gWSZUNz3Y1yVPr2JZhAKyO5zlTBdYE
+ASs7wFK80FuHDtbqI7CaI+4JkakCS2qvcqj2MjhfeyRAEqVvQrArfAx+00yrP4QAVpOA1T9gQaym
+ArMxvpnOrsDqDAqwpJefGwFeb3IBVm0kTGJqMYRrZeLeOfymRsAiYKlAVR+ZguztADNufQfWVLZX
+gPSQWqCyTIBVd5j99QIOAWuaAcvz1YdpByxw9zpT1V4ay65jmN6Rm0JgVW2vk4BFwLKBVX0kvSzj
+oQNWinC3BVbDJ72DgEXAGuZ3CTsQKylDx86lPEuYSWBZvEsYLSQXpL086lG16AsELAJWphNHTV2K
+Wh/SGjIHLJv2UrlgoYDlm81OwCJgDSqwTGaXKn3Kw8oisCo+AzogsJojHtnsnrlcIdIauqGBQ8Ca
+HsBKmoJv9zFxNIvAavWrvRziZ2XHPhFigUMCFgErLLAMV2pIyn0pTzNg+a5nVfIBVqhs9oQ6ekHZ
+8EHYHDZgVT2z3UMCYUXG67faZSuyEPEKw9nFoQBWoPaqeQLLdQXQDrRXNWmNc8N7mkuIi6bxLmF2
+gSUN5FHYRHRiioGwAna2yWW0fsa7AaUFLIsAdIWAZWx56NaLqgZMnejEbTNmaAWWPK3uwlACywMO
+LkAwgpRB/cazWD/HAdjwnAmKXTVhSIHVChB7anvAzkXLDg+ipsd9aacBnMwByxJepkAwhgDsJ5g3
+rF8B9hscn6r6pQSsuKeh7TrwlSEAlmn8qOjR1jqXKc0loXMObmHZEcrlaQcsA3jpgGADqWjz0qZi
+U9eCBbxs6jeWFqQcYg3y2t3RWll1RxekMA2C7tG1Vj3bS/WuXZrAKjpMyET5ZkVwI02us+2xpvtw
+AAtZQNGOygX03ZgFpGz2BbTa1FWCq6p+XjGplGaEUtsRZkCB1ZjC9mr0C1gpxMxMYl/TC1ieoPPd
+FxDvi5gfhGtPeYuvpFjJIAJrKnf6qfYTWCk80OppAmeogQWuXhkA001JW+BOFjIOLd9OWTaYri8P
+Qx6W4XlN2qvq0F46NyvaRaYkuaKRqxbtFtRyAFaozVTrBv2QgKWB1ZIAq5ra5EmVMgys3Ij7FuCl
+BPB1hvDlZ9dB3JFBFFP/TpzbpIBUxeHVm2hhxqbFWum+0Kob1o2AlWKe15SmIEwRtGwsh6Zi+yzc
+sdueW9X7Aqvsce6OQXvVA7dXJ6G9amApFQPOEtcN3w3MOcS02klJqpbxQV9gVdgwSQB4DRSkNJ24
+prj5bSlTOulp3ICBkDMYBBVpQ0yshYTfFzS/rRicX3fukmF75aX26ni0V8PWWurjg62isbg6cC1l
+h7J197NqcD+9fp81GDVtAuIArxsNkkBtUiT+P7DPSEiGQADYUbwsRy0SFliqgLgJvOQk0Amwwkxe
+28lJgf2O7mVqEhISEh2wnOBlcJ6cyewj3REvmc31QK5voKYgmY7A6rpmsUPZqmz4LgErFbmG6wau
+W+HfedQkwWQG13O5rgE9m5ok+8AygpcEqVaI9bVIjOXHXLuSvoeaJJj8GddXpLYVD4UjqFkGB1hT
+tiAgibGsJGClJl9CbSv0FGoWAhYBi4CVRZnDdZPUti+z3fFCEgIWCQErk7If11u4fp2agoBFwCJg
+kZAQsAZQ5nO9nO0OoovZvse43s71Aq4HOAJLTI6czvVUrkdynRmgngdx/dMArpG4JtGHjuU6bAmW
+oo1EmsnrPMqYy/VdcN/28ShHTBzMI2ANN7D+iu2exv4t12Wa40a53s11jOtZmuMENO7kegdX/IrL
+/mx3asILrDfAG+kTXBdaAOtvuK7l2pE+38ZVLFf8dw7tIcq7B+q4GeI6W7g+znU517dw3dugHDHw
+ylx/zfVZqNME1xe53g9toxvkZ3A9h+vBXPeCzy7m+ijUZ5zrvvD5J7neB/UuG9TtMK5LoT2jd+xE
+WkMVyl/N9TLN74/i+hVoE9H2T3N9jutd0DdmGcbMLoW+Jx5aO6C918F1HGvYzlWpP70C7bwT6nSd
+1EZ/lIPnHFDm2kQqPqvB//NwXDH6joCVLfmBNNB3wUBRyf3ScaJTjyiOEZ/9r3TcF6XvZsGA36mB
+VVfqeGcaAEuU/7KmHHE9N1hYQT/huj2hbuL77yaUdQiAfVdC3e6MsbgE1F+F40R7/gW0HS7v43D8
+i9JnG8Ha1Mld0vF/gM9yAI2udF4se8EDqYXucxed/46E8x8HD0hdX9iZ0M7HAOiS+tJ6+QELIKpy
+bYNWJTh1xd9wXF3+m4CVHbkYWSfLYwbgk9Ix68BVwnIydJAuWAGyhXWbooM+A+f7BXR0+TtRp7cl
+AGtnwt8RGC4zaId7DDq/fJ4vayyH31uU9ZDCfV0qff8S11tjri0C1n3o808ngFmu35gErO3ooYHl
+eAOgR78dA4say59D3zBtn9sUD8f5YLWaliEs2wXI0vqjdYX+7gDEcgArAlYGgXUkuBfRzX1Rccz7
+EVCEVXOu4rgrpCfvBohNRE/UHagT3Q6xD9lNeRgd83gCsOSnurBKTgIXB8PvNa6Ha9rgVMVA/B3X
+xVy/wPU/wV3Bg3Kewg28QwHMu+EcZ8BA3oaOuVYDrC2Kc++Ez6NBuAhZPPdrrvU0qX3ENXzYEFiH
+Iis76gfiem8GV162dkXi6T8pYNlSPJiEZftutju7/lfIknxVESL4maI9xO++yXbPcD7JJifBdsFl
+TQJWZFXVAF5NAlY2g+6y9STAkkffq5IK64py5Cf9g1Js5CH027jtsMSgaKO6HJ8ArE0KGB2rAKRu
+qn4MHbtSEYeZCxYhPk6WhWiwCVBeqDjfpZLLFw3aA2KA9Qfkji6DwS0f/1aweuXBGRd8riNL+WBD
+YC1ClriwcE5Ex1yPjmmhIPo1CCTbwSrH8m1kUa6VytkXrE45Xnk+ineNQPxvAt2Lv04AlnAPWwCt
+OgEru8Bagp5WH9bEr2QLZCayLmTL5ibJnXwZxUaO0dTlixowrlRYL+8ziM1FlmNcMPgFdP3HxRz3
+dmkgiXOvQt//Cp1zVUzgeCbEAeVjL4sBljzg4t7vmwUxIRmA5yiOez2yYtdI3yUB62H03eWK8l+H
+Hk6bJSDtB1aYfE1LYq5nNopP7YJZxMhal/vZU4bxWdHv3msArAoAq0TAyi6wFqIn479J3x2k6Ghd
+iIPI75qdInWyrWxPysEV6HfPxgTsI1mABs46DbB+l+DqTiBr7a0xx76EgPXOmONmwGzpVxXHFFBs
+5hWYTdO5obI1dl8CsFYk3MOvo+OXxwSqn5eO+awhsI5Cv9scE5+KZjfljPnPS/1jK3L1kmb/5Ov5
+AXw+itrtSQCxSgQk/4XrJyB2JruEBaHo7zzEr4ryZwSs7MnhyBV7nu2ZSh+VgrTbpEEpOvSHUPxK
+DhRHs18/QR3vFxCwj9N3INB0ARQqYH0l4bqeQ8cvijluHB13vxR/M5V/VABdJ/OQ5bmR7UlzWKqw
+JJPyi96F2u1Z1pvTdKkU61qHJjV0wKqgGNk9mnrMRX1pKXx+C7qm3yRczwmoPmsk6G5GbXMp88vf
+ypYQsIzkURRbiAbs51CQVY6V3Cr9/t6YGNXjikDtRo2+hOIX2yAgrwJW0lLGOAC+2CCuI7uQPwdX
+bQHTJ7QKaSgmDD6o0UuQRbYVYngqYD0tPUCYxi2cQLE9HGNaJX0/jr7TAesbhuCP5GRot49wfTN8
+9iAq496E9rkStc8mcKVnIgsugtYasMLOAotwNgFruIH1NTR4TofPH5A+F0mQjyCXbBYM5rXS51+K
+Cei7qADW0THASno151Z0/PdjjjsMYkRxdRDtsR4GnQgcz0+YcHDVY2OAdZvhPfwvjQWKU1OWWQDr
+TnQ/XHaBesKzbTZBeELIlxOO7YCFK/rLeQNnfRGwjORs9ERbAjMyckBaDNZr0WzU0chtFIP7A1K5
+L3p21B2SO4SBdWrCNWHLoKE59iLFkztON4AFMDMmKO2qb4sB1rcM7+H5bHLKxNPSd/8gxRi3wD0z
+Bdbd6NpH+wSsg6XyHjD83S7og0cTsIYLWIdCB49u9CNgwWyQOsxJAKPNUqf+KJj/cpLeG6Vy26gD
+fQbiE6aa0wTdkyysGwwC0bKcCYDeZTAQXkUxPOz6boRBaqq/kcC8VDODqJP9UWB7o+SSLUEza4dY
+AKsZAFjPKGJ8bQt9QOHm3YwmTHT6HNPn4mUKWPUMAWs8w031axQ4v5ZNTgTdF2C0Cc3ejKHBMEMq
+839Qx/m8R/0wsE5POB7Hpr5neB6R+/VVcHm3aQAm7mU0i4QTIm/2uE4MrEssfvtLNnnGU/z2T+Ba
+cHa7i0u4Faw1W8H94MxAfTYH3sESiMNOsPhXfpazQRFY1ngR7MQ81cAah513Chlvpn9FwfFHFbM6
+M5B5vxZZZt9AZeJljW8NCKxywvE/Qsdf43je46Bt1ikGwUVwzO3o85/2CVjyTGAXXFXRf6O0BPHd
+hZbAwjltVyfUQUxSLET35xFUxg0p9eE54AksY71vPKyD7wcuCG8LLxdgDQqkZDkDmdhyIFp+d+6b
+yO2IYl+iw+MVEq5WWCU6mQ1PSzF1fhMKcGNgfTuhLOymvduzfeaiyQW5Dtcx8xwx2YU7LDCwjlDE
+DT/H9mT+i0F7pCWwPsV6U1Pi5E1gZa+HvvSjGKD/h8G1HKhwXW3kBIV1/HY2yGIIL1NgDSKkZDmA
+TU4QjF6jWI8C6adJkNqBXBC8+oBoCzkpdTtDL6Iq4khyJ/uZBlhrNeW8mU3OcxLXcFAMhH4Mg1wM
+sKMS2ujqGDfzJOSK7Ig5nwzmh+CcImfqqkDAYqw3RUWOH/03U68VpgNWCYUBhJU2SxP436KYMLiQ
+9b6QrEsgFvG8NdA+T0kupEjYfQz6yG8T2mEG682xG55FHzXw0gFr0CGF5UGF2/MMsgT2Z+o37p+P
+KRO7A+uZOhFyHnRO+djrNcDapoljLWe9yaAq+Rg6Trxeo1uHaTFT53bNYb0rCCzWlPNJNvm9ujUB
+gYVfb5JdxJs0saA4YOWQZbmdxS9DhFMgzpTurfy6jZi0+KCFWxw9uNqojI8ntAV2C49nwygAr6sA
+SBhYY7ADdHEIL/0aBYhUT7LHmHopEJWcznpXQxCD+yPQkXNgweEZHzFjd6gGWNG09QL0VD0XWXW6
+dw4LyEoUbvC1McceznpXWrgoxlWOrCzVYoRFNnk2T+iVAYG1AFnKslVzogOwGOtNEXmM9c66XYLa
+XZQhL1J4N+tNIlY9cD6K2kfcv7NiHhjPQXuq5Ep0TZuY/RsMJBmXU1jvqzGqGa/Pst4lPj6gKfen
+TL2ulEiR+D3rXYjvNcXTc6XCXY0G4kpwz1ax3sXlxOB6vaZu9yog+CTA+xywJm5gva/6dBBQD0QD
+NrIyxJT8h8DaaCjaVwykfQICazbrfbk6SiXYxxFYf6mAtZj5uwWgvIJNXmdL/B6vyzWf9S77IsB0
+B5Tx93D/8DGPSy7ofLZnzTX5PtwJ/eU0cEvvUjwU7qXhPXyyD4pXiM5wgeK4k5GJjwcvljkKMOiS
+/aoK10wG1jJFh4xbITQp/6agCKab5GF9RlHW2QpoJWVlnxAw6B7J1xTn+nfN8SYL+H1M4WJFuXX4
+M9W7gnuB1bPTon1eUFhFCy3LiMCYp+E9nPIQeiqrBvy+yO1Ya1j29Sw5KznOfVspuVri7ft/Vjz1
+8fuAJxjWa36MGxX3utB1msDzBcwsa35DjEuEgXWxwz18L+vdZ/B8zfH7sd4JFJXcyPTLUgvr9p6E
+h8QXEu6bbFnFxYYvYuYrlz7F1OtukQyJCBiI4PsvwdJhmoEppq1/yPasV2QiYpaqAgNTTJGLd+C+
+Y1CGeL2iyXYvFyJbR6sArC/BIBUzQ3XmtoPK5eDqbGeTZyt3wFNaBH+PMShHDNifQxmvIijvhDaL
+i6ecA4NxA0PrOFmIsJi+C23xBLhMSe/UidQVsQGFSCC+IuaYvWHwi+TTdaDRDKvIx7vaME4kZnEf
+hrbZhSy7DliIcwzaOLrGLQqLStxH8V7rm2hIk2RNhLXzRhZmG60Z0MmLXP8WBugRHuWJcspsd3qA
+yWzyCFzLkZ7nTVNEHQ+BazvZ8Lri7ts7wZV+D9vzKpFtGW+BuogyFjAKrpOQkJCQkJCQkJCQkJCE
+l/8Df+8XDp+g0JUAAAAASUVORK5CYII=
+IMAGE;
+
+
+ header('Content-type: image/png');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['background']))
+{
+ $data = <<<IMAGE
+R0lGODlhMAEeAeYAAP///8ni6cTf5+72+PD3+c3k6+nz9ufy9ev099Pn7bnZ48bg6LfY4uHv8/r8
+/f3+/v7//7bX4cjh6fj7/Mvj6vz9/rva4+z19/X6+/f7/Pn8/fb6+7jZ4vv9/bra473b5Lzb5LXX
+4b7c5b/c5e31+NTo7tvs8dfq7/H3+bjY4tnq79Hm7c/l69nr8PL4+t7t8sDd5cLe5uPw9Nvr8Mri
+6fP4+tLn7er099Hm7O/2+dDm7OTw9OXx9Nbp7tbp7+Lv8+Du8szj6sXg57bY4d3s8djq7+jz9tzs
+8cPe58fh6M7k68Pf5+by9fz+/sDd5vT5+vT5+97t8bbY4trr8P7+/v7+/+Pw8+Xx9dXo7sHe5vH4
++fP5+sHd5t/u8s/l7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5
+BAAAAAAALAAAAAAwAR4BAAf/gCGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKNEaWm
+p6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPExbBDyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7K
+UuHi4+Tl5ufo6err7O3u7/Dx8vP09fb34wz6+/z9/v8AAwocSLCgwYMIEypcyLChw4cQI0qcSLGi
+xYsYM2osmKKjx48gQ4ocSbKkyZMoU6pcybKly5cwY8qc+ZGDzZs4c+rcybOnz59AgwodSrSo0aNI
+kypdyrSp06dQo0qdSrWq1aAKsmrdyrWr169gw4odS7as2bNo06pdy7at27dw/+PKnUu3rt27ePOS
+9cC3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNr3sz5sIXPoEOLHk26tOnTqFOrXs26
+tevXsGPLnk27tu3buHPr3s27t+/fqkEIH068uPHjyJMrX868ufPn0KNLn069uvXr2LNr3869u/fv
+4MOLb/6hvPnz6NOrX8++vfv38OPLn0+/vv37+PPr38+/v///AAYo4IAEFgifCAgmqOCCDDbo4IMQ
+RijhhBRWaOGFGGao4YYcdujhhyCGKOKIJJZo4okoTjjCiiy26OKLMMYo44w01mjjjTjmqOOOPPbo
+449ABinkkEQWaeSRSCap5P+SNsLg5JNQRinllFRWaeWVWGap5ZZcdunll2CGKeaYZELpxJlopqnm
+mmy26eabcMYp55x01mnnnXjmqeeefPaZJheABirooIQWauihiCaq6KKMNuroo5BGKumklFZqqaBZ
+ZKrpppx26umnoIYq6qiklmrqqaimquqqrLbq6qubxiDrrLTWauutuOaq66689urrr8AGK+ywxBZr
+7LHI0orEssw26+yz0EYr7bTUVmvttdhmq+223Hbr7bfghtvsEuSWa+656Kar7rrstuvuu/DGK++8
+9NZr77345quvuQL06++/AAcs8MAEF2zwwQgnrPDCDDfs8MMQRyzxxBRXbPH/xRhnrPHGHHeMsBAg
+hyzyyCSXbPLJKKes8sost+zyyzDHLPPMNNdss8gL5Kzzzjz37PPPQAct9NBEF2300UgnrfTSTDft
+9NNQRy311FRXbfXVWGdNdBJcd+3112CHLfbYZJdt9tlop6322my37fbbcMctt9cS1G333Xjnrffe
+fPft99+ABy744IQXbvjhiCeu+OKMN+7445BHLvnklFcOeACYZ6755px37vnnoIcu+uikl2766ain
+rvrqrLfu+uuwxy777LTXbvvtuI9Ow+689+7778AHL/zwxBdv/PHIJ6/88sw37/zz0EffOwXUV2/9
+9dhnr/323Hfv/ffghy/+//jkl2/++einr/767Lfv/vvwxy///PR/H8T9+Oev//789+///wAMoAAH
+SMACGvCACEygAhfIwAbmrwAQjKAEJ0jBClrwghjMoAY3yMEOevCDIAyhCEdIwhKa8IQoTKEKV8jC
+FrrwhTDcoBJmSMMa2vCGOMyhDnfIwx768IdADKIQh0jEIhrxiEhMYg1ZwMQmOvGJUIyiFKdIxSpa
+8YpYzKIWt8jFLnrxi2AMoxid6IUymvGMaEyjGtfIxja68Y1wjKMc50jHOtrxjnjMox73eEYd+PGP
+gAykIAdJyEIa8pCITKQiF8nIRjrykZCMpCQnSUlA4uCSmMykJjfJyU568v+ToAylKEdJylKa8pSo
+TKUqV8nKVmZyBbCMpSxnScta2vKWuMylLnfJy1768pfADKYwh0nMYhpTljZIpjKXycxmOvOZ0Iym
+NKdJzWpa85rYzKY2t8nNbnrzm8tMgDjHSc5ymvOc6EynOtfJzna6853wjKc850nPetrznvjMpz73
+yc9++vOfAA2oQNtZgoIa9KAITahCF8rQhjr0oRCNqEQnStGKWvSiGM2oRjd6UCx49KMgDalIR0rS
+kpr0pChNqUpXytKWuvSlMI2pTGdKU5D24KY4zalOd8rTnvr0p0ANqlCHStSiGvWoSE2qUpfK1Kbm
+1AdQjapUp0rVqlr1qlj/zapWt8rVrnr1q2ANq1jHStaymlWqJ0irWtfK1ra69a1wjatc50rXutr1
+rnjNq173yte++vWvay2CYAdL2MIa9rCITaxiF8vYxjr2sZCNrGQnS9nKWvaymCWsCjbL2c569rOg
+Da1oR0va0pr2tKhNrWpXy9rWuva1sI1tZ1tA29ra9ra4za1ud8vb3vr2t8ANrnCHS9ziGve4yE2u
+cm07heY697nQja50p0vd6lr3utjNrna3y93ueve74A2veMf73BmY97zoTa9618ve9rr3vfCNr3zn
+S9/62ve++M2vfvfLX/Sa4L8ADrCAB0zgAhv4wAhOsIIXzOAGO/jBEI6w/4QnTOEKB/gIGM6whjfM
+4Q57+MMgDrGIR0ziEpv4xChOsYpXzOIWu1jDRIixjGdM4xrb+MY4zrGOd8zjHvv4x0AOspCHTOQi
+G/nIM46CkpfM5CY7+clQjrKUp0zlKlv5yljOspa3zOUue/nLYGbyC8ZM5jKb+cxoTrOa18zmNrv5
+zXCOs5znTOc62/nOeM5zmbvA5z77+c+ADrSgB03oQhv60IhOtKIXzehGO/rRkI60pP0MhEpb+tKY
+zrSmN83pTnv606AOtahHTepSm/rUqE61qld96Qa4+tWwjrWsZ03rWtv61rjOta53zete+/rXwA62
+sIdN7GIb+9jITrayl//N7GY7O9c/iLa0p03talv72tjOtra3ze1ue/vb4A63uMdN7nKb+9zTtoK6
+183udrv73fCOt7znTe962/ve+M63vvfN7377+98AZ7cMBk7wghv84AhPuMIXzvCGO/zhEI+4xCdO
+8Ypb/OIYz3jBd8Dxjnv84yAPuchHTvKSm/zkKE+5ylfO8pa7/OUwj7nMPc6Dmtv85jjPuc53zvOe
++/znQA+60IdO9KIb/ehIT7rSl37zKzj96VCPutSnTvWqW/3qWM+61rfO9a57/etgD7vYx052qDPh
+7GhPu9rXzva2u/3tcI+73OdO97rb/e54z7ve9873vqf9AIAPvOAHT/j/whv+8IhPvOIXz/jGO/7x
+kI+85CdP+cpb/vKYz7zmN8/5znv+86BfvBFGT/rSm/70qE+96lfP+ta7/vWwj73sZ0/72tv+9rjP
+fekNwPve+/73wA++8IdP/OIb//jIT77yl8/85jv/+dCPvvSnT/3qW//62M++9rfP/ePf4PvgD7/4
+x0/+8pv//OhPv/rXz/72u//98I+//OdP//qHHwH4z7/+98///vv//wAYgAI4gARYgAZ4gAiYgAq4
+gAzYgA74gBAYgRI4gRRYgRZ4gRg4gBewgRzYgR74gSAYgiI4giRYgiZ4giiYgiq4gizYgi74gjAY
+gzI4gzRYgzZ4gziY/4M6uIMmSAI++INAGIRCOIREWIRGeIRImIRKuIRM2IRO+IRQGIVSOIVUCIQD
+cIVYmIVauIVc2IVe+IVgGIZiOIZkWIZmeIZomIZquIZs2IZu+IZwGIdyOId0WId2eIdimAN6uId8
+2Id++IeAGIiCOIiEWIiGeIiImIiKuIiM2IiO+IiQyIcEMImUWImWeImYmImauImc2Ime+ImgGIqi
+OIqkWIqmeIqomIqquIqs2Iqu+IqwGIuyOIueiAK2eIu4mIu6uIu82Iu++IvAGIzCOIzEWIzGeIzI
+mIzKuIzMiIta8IzQGI3SOI3UWI3WeI3YmI3auI3c2I3e+I3gGI7iOP+O5FiO0egC6JiO6riO7NiO
+7viO8BiP8jiP9FiP9niP+JiP+riP/NiP/qiONRCQAjmQBFmQBnmQCJmQCrmQDNmQDvmQEBmREjmR
+FFmRFnmRA7kFGrmRHNmRHvmRIBmSIjmSJFmSJnmSKJmSKrmSLNmSLvmSMMmRTzCTNFmTNnmTOJmT
+OrmTPNmTPvmTQBmUQjmURFmURnmUSJmUNQkFTNmUTvmUUBmVUjmVVFmVVnmVWJmVWrmVXNmVXvmV
+YBmWYumUGFCWZnmWaJmWarmWbNmWbvmWcBmXcjmXdFmXdnmXeJmXermXfNmXfvmXgBmYgjmYhFmY
+cLkBiJmYirmYjNn/mI75mJAZmZI5mZRZmZZ5mZiZmZq5mZzZmZ75maAZmqI5mqRZmqZ5mqg5mRmw
+mqzZmq75mrAZm7I5m7RZm7Z5m7iZm7q5m7zZm775m8AZnMI5nMRZnMZ5nMiZnMq5nLY5Ac75nNAZ
+ndI5ndRZndZ5ndiZndq5ndzZnd75neAZnuI5nuRZnuZ5nuiZnuq5nuzZnu6ZnRoQn/I5n/RZn/Z5
+n/iZn/q5n/zZn/75nwAaoAI6oARaoAZ6oAiaoAq6oAzaoA76oBAaofzpABRaoRZ6oRiaoRq6oRza
+oR76oSAaoiI6oiRaoiZ6oiiaoiq6oizaoi76ojAaozI6ozT6oR1w/6M4mqM6uqM82qM++qNAGqRC
+OqREWqRGeqRImqRKuqRM2qRO+qRQGqVSOqVUWqVWeqVCWgFauqVc2qVe+qVgGqZiOqZkWqZmeqZo
+mqZquqZs2qZu+qZwGqdyOqd0Wqd2eqd4mqd6WqZN0Kd++qeAGqiCOqiEWqiGeqiImqiKuqiM2qiO
++qiQGqmSOql/+gCWeqmYmqmauqmc2qme+qmgGqqiOqqkWqqmeqqomqqquqqs2qqu+qqwGquyOqu0
+Wqu2GqpUkKu6uqu82qu++qvAGqzCOqzEWqzGeqzImqzKuqzM2qzO+qy7WgXSOq3UWq3Weq3Ymq3a
+uq3c2q3e+q3gGv+u4jqu5Fqu5nqu6EqtELCu7Nqu7vqu8Bqv8jqv9Fqv9nqv+Jqv+rqv/Nqv/vqv
+ABuwAjuwBFuwBnuwCJuwCruw9goADvuwEBuxEjuxFFuxFnuxGJuxGruxHNuxHvuxIBuyIjuyJFuy
+JnuyKJuyKruyLNuyLvuyMBuzMjuzNFuzNnuzOJuzOruzPNuzPvuzQBu0Qju0RFu0Rnu0SJu0Sru0
+TNu0Tvu0UBu1Uju1VFu1Vnu1WJu1Wru1XNu1Xvu1YBu2Yju2ZFu2Znu2aJu2aru2bNu2bvu2cBu3
+cju3dFu3dnu3eJu3eru3fNu3fvu3gBu4gju4hFu4hnu4iJu4irv/uIzbuI77uJAbuZI7uZRbuZZ7
+uZibuZq7uZzbuZ77uaAbuqI7uqRbuqZ7uqibuqq7uqzbuq77urAbu7I7u7Rbu7Z7u7ibu7q7u7zb
+u777u8AbvMI7vMRbvMZ7vMibvMq7vMzbvM77vNAbvdI7vdRbvdZ7vdibvdq7vdzbvd77veAbvuI7
+vuRbvuZ7vuibvuq7vuzbvu77vvAbv/I7v/Rbv/Z7v/ibv/q7v/zbv/77vwAcwAI8wARcwAZ8wAic
+wAq8wAzcwA78wBAcwRI8wRRcwRZ8wRicwRq8wRzcwR78wSAcwiI8wiRcwiZ8wiicwiq8wizcwi78
+wjAcwzI8wzRcFcM2fMM4nMM6vMM83MM+/MNArLmBAAA7
+IMAGE;
+
+ header('Content-type: image/gif');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['loader']))
+{
+ $data = <<<IMAGE
+R0lGODlhEAALAPQAAP///wBmzNro9tDi9Ory+gZpzQBmzC6B1YKz5WCf3rrV8CJ60kqS2oq452Sh
+377X8SZ80wRozE6U2+bv+djn9vT4/DiH19zp9/L2+7bS76DF68re8+70+gAAAAAAAAAAACH/C05F
+VFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCwAAACwAAAAA
+EAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJ
+CwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJ
+CwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHT
+uBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V5
+5zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme
+1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAA
+ABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2
+y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2
+isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0
+DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7AAAAAAAAAAAA
+IMAGE;
+ header('Content-type: image/gif');
+ echo base64_decode($data);
+ exit;
+}
+elseif (isset($_GET['ssl_check']))
+{
+ header('Content-type: text/plain; charset=utf-8');
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://email.us-east-1.amazonaws.com');
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($ch, CURLOPT_NOSIGNAL, true);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'aws-sdk-php/compat-www');
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($ch, CURLOPT_VERBOSE, true);
+
+ curl_exec($ch);
+ echo (curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT) === 0) ? 'false' : 'true';
+ curl_close($ch);
+
+ exit;
+}
+
+// Include the compatibility test logic
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sdk_compatibility.inc.php';
+
+header('Content-type: text/html; charset=UTF-8');
+
+?><!DOCTYPE html>
+
+<html lang="en">
+<head>
+<title>AWS SDK for PHP: Environment Compatibility Test</title>
+<meta name="ROBOTS" content="NOINDEX, NOFOLLOW, NOARCHIVE" />
+
+<script type="text/javascript" charset="utf-8">
+/*!
+ * Reqwest! A x-browser general purpose XHR connection manager
+ * copyright Dustin Diaz 2011
+ * https://github.com/ded/reqwest
+ * license MIT
+ */
+!function(window){function serial(a){var b=a.name;if(a.disabled||!b)return"";b=enc(b);switch(a.tagName.toLowerCase()){case"input":switch(a.type){case"reset":case"button":case"image":case"file":return"";case"checkbox":case"radio":return a.checked?b+"="+(a.value?enc(a.value):!0)+"&":"";default:return b+"="+(a.value?enc(a.value):"")+"&"}break;case"textarea":return b+"="+enc(a.value)+"&";case"select":return b+"="+enc(a.options[a.selectedIndex].value)+"&"}return""}function enc(a){return encodeURIComponent(a)}function reqwest(a,b){return new Reqwest(a,b)}function init(o,fn){function error(a){o.error&&o.error(a),complete(a)}function success(resp){o.timeout&&clearTimeout(self.timeout)&&(self.timeout=null);var r=resp.responseText;if(r)switch(type){case"json":resp=window.JSON?window.JSON.parse(r):eval("("+r+")");break;case"js":resp=eval(r);break;case"html":resp=r}fn(resp),o.success&&o.success(resp),complete(resp)}function complete(a){o.complete&&o.complete(a)}this.url=typeof o=="string"?o:o.url,this.timeout=null;var type=o.type||setType(this.url),self=this;fn=fn||function(){},o.timeout&&(this.timeout=setTimeout(function(){self.abort(),error()},o.timeout)),this.request=getRequest(o,success,error)}function setType(a){return/\.json$/.test(a)?"json":/\.jsonp$/.test(a)?"jsonp":/\.js$/.test(a)?"js":/\.html?$/.test(a)?"html":/\.xml$/.test(a)?"xml":"js"}function Reqwest(a,b){this.o=a,this.fn=b,init.apply(this,arguments)}function getRequest(a,b,c){if(a.type!="jsonp"){var f=xhr();f.open(a.method||"GET",typeof a=="string"?a:a.url,!0),setHeaders(f,a),f.onreadystatechange=readyState(f,b,c),a.before&&a.before(f),f.send(a.data||null);return f}var d=doc.createElement("script");window[getCallbackName(a)]=generalCallback,d.type="text/javascript",d.src=a.url,d.async=!0;var e=function(){a.success&&a.success(lastValue),lastValue=undefined,head.removeChild(d)};d.onload=e,d.onreadystatechange=function(){/^loaded|complete$/.test(d.readyState)&&e()},head.appendChild(d)}function generalCallback(a){lastValue=a}function getCallbackName(a){var b=a.jsonpCallback||"callback";if(a.url.slice(-(b.length+2))==b+"=?"){var c="reqwest_"+uniqid++;a.url=a.url.substr(0,a.url.length-1)+c;return c}var d=new RegExp(b+"=([\\w]+)");return a.url.match(d)[1]}function setHeaders(a,b){var c=b.headers||{};c.Accept=c.Accept||"text/javascript, text/html, application/xml, text/xml, */*",b.crossOrigin||(c["X-Requested-With"]=c["X-Requested-With"]||"XMLHttpRequest");if(b.data){c["Content-type"]=c["Content-type"]||"application/x-www-form-urlencoded";for(var d in c)c.hasOwnProperty(d)&&a.setRequestHeader(d,c[d],!1)}}function readyState(a,b,c){return function(){a&&a.readyState==4&&(twoHundo.test(a.status)?b(a):c(a))}}var v=window.v;!v&&typeof require!="undefined"&&(v=require("valentine"));var twoHundo=/^20\d$/,doc=document,byTag="getElementsByTagName",head=doc[byTag]("head")[0],xhr="XMLHttpRequest"in window?function(){return new XMLHttpRequest}:function(){return new ActiveXObject("Microsoft.XMLHTTP")},uniqid=0,lastValue;Reqwest.prototype={abort:function(){this.request.abort()},retry:function(){init.call(this,this.o,this.fn)}},reqwest.serialize=function(a){var b=a[byTag]("input"),c=a[byTag]("select"),d=a[byTag]("textarea");return(v(b).chain().toArray().map(serial).value().join("")+v(c).chain().toArray().map(serial).value().join("")+v(d).chain().toArray().map(serial).value().join("")).replace(/&$/,"")},reqwest.serializeArray=function(a){for(var b=this.serialize(a).split("&"),c=0,d=b.length,e=[],f;c<d;c++)b[c]&&(f=b[c].split("="))&&e.push({name:f[0],value:f[1]});return e};var old=window.reqwest;reqwest.noConflict=function(){window.reqwest=old;return this},window.reqwest=reqwest}(this)
+</script>
+
+<style type="text/css">
+body {
+ font:14px/1.4em "Helvetica Neue", Helvetica, "Lucida Grande", Roboto, "Droid Sans", Ubuntu, Verdana, Arial, Clean, Sans, sans-serif;
+ letter-spacing:0px;
+ color:#333;
+ margin:0;
+ padding:0;
+ background:#fff url(<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?background) repeat-x top left;
+}
+
+div#site {
+ width:650px;
+ margin:20px auto 0 auto;
+}
+
+a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+}
+
+a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+}
+
+p {
+ margin:0;
+ padding:5px 0;
+}
+
+em {
+ font-style:normal;
+ background-color:#ffc;
+}
+
+ul, ol {
+ margin:10px 0 10px 20px;
+ padding:0 0 0 15px;
+}
+
+ul li, ol li {
+ margin:0 0 4px 0;
+ padding:0 0 0 3px;
+}
+
+h2 {
+ font-size:18px;
+ padding:0;
+ margin:0 0 10px 0;
+}
+
+h3 {
+ font-size:16px;
+ padding:0;
+ margin:20px 0 5px 0;
+}
+
+h4 {
+ font-size:14px;
+ padding:0;
+ margin:15px 0 5px 0;
+}
+
+pre, code {
+ font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, "Andale Mono", monospace;
+ background-color: #F0F0F0;
+ border-radius: 3px 3px 3px 3px;
+ padding: 0 3px;
+ font-size: 1em;
+}
+
+em strong {
+ text-transform: uppercase;
+}
+
+table.chart {
+ border-collapse:collapse;
+}
+
+table.chart th {
+ background-color:#eee;
+ padding:2px 3px;
+ border:1px solid #fff;
+}
+
+table.chart td {
+ text-align:center;
+ padding:2px 3px;
+ border:1px solid #eee;
+}
+
+table.chart tr.enabled td {
+ /* Leave this alone */
+}
+
+table.chart tr.disabled td,
+table.chart tr.disabled td a {
+ color:#999;
+ font-style:italic;
+}
+
+table.chart tr.disabled td a {
+ text-decoration:underline;
+}
+
+div.chunk {
+ margin:0;
+ padding:10px;
+ border-bottom:1px solid #ccc;
+}
+
+div.important {
+ background-color:#ffc;
+}
+
+div.ok {
+ background-color:#cfc;
+}
+
+div.error {
+ background-color:#fcc;
+}
+
+div.important h3 {
+ margin: 7px 0 5px 0;
+}
+
+.footnote,
+.footnote a {
+ font:12px/1.4em "Helvetica Neue", Helvetica, "Lucida Grande", Verdana, Arial, Clean, Sans, sans-serif;
+ color:#aaa;
+}
+
+.footnote em {
+ background-color:transparent;
+ font-style:italic;
+}
+</style>
+
+</head>
+
+<body>
+
+<div id="site">
+ <div id="content">
+
+ <div class="chunk">
+ <h2 style="text-align:center;"><img src="<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?logopng" alt="SDK Compatibility Test" title="SDK Compatibility Test" /></h2>
+
+ <h3>Minimum Requirements</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Should Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($php_ok) ? 'enabled' : 'disabled'; ?>">
+ <td>PHP</td>
+ <td>5.2 or newer</td>
+ <td><?php echo phpversion(); ?></td>
+ </tr>
+ <tr class="<?php echo ($curl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/curl">cURL</a></td>
+ <td>7.15.0 or newer, with SSL</td>
+ <td><?php echo ($curl_ok) ? ($curl_version['version'] . ' (' . $curl_version['ssl_version'] . ')') : ($curl_version['version'] . (in_array('https', $curl_version['protocols'], true) ? ' (with ' . $curl_version['ssl_version'] . ')' : ' (without SSL)')); ?></td>
+ </tr>
+ <tr class="<?php echo ($simplexml_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/simplexml">SimpleXML</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($simplexml_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($dom_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/dom">DOM</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($dom_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($spl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/spl">SPL</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($spl_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($json_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/json">JSON</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($json_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pcre_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pcre">PCRE</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pcre_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($file_ok) ? 'enabled' : 'disabled'; ?>">
+ <td>File System <a href="http://php.net/file_get_contents">Read</a>/<a href="http://php.net/file_put_contents">Write</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($file_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Optional Extensions</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($openssl_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/openssl">OpenSSL</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($openssl_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($zlib_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/zlib">Zlib</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($zlib_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($apc_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/apc">APC</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($apc_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($xcache_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://xcache.lighttpd.net">XCache</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($xcache_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($memcache_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/memcache">Memcache</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($memcache_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($memcached_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/memcached">Memcached</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($memcached_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pdo_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pdo">PDO</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pdo_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($pdo_sqlite_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/pdo-sqlite">PDO-SQLite</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($pdo_sqlite_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($sqlite2_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/sqlite">SQLite 2</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($sqlite2_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ <tr class="<?php echo ($sqlite3_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/sqlite3">SQLite 3</a></td>
+ <td>Enabled</td>
+ <td><?php echo ($sqlite3_ok) ? 'Enabled' : 'Disabled'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Settings for php.ini</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo (!$ini_open_basedir) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/open_basedir">open_basedir</a></td>
+ <td>off</td>
+ <td><?php echo ($ini_open_basedir) ? 'on' : 'off'; ?></td>
+ </tr>
+ <tr class="<?php echo (!$ini_safe_mode) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/safe_mode">safe_mode</a></td>
+ <td>off</td>
+ <td><?php echo ($ini_safe_mode) ? 'on' : 'off'; ?></td>
+ </tr>
+ <tr class="<?php echo ($ini_zend_enable_gc) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="http://php.net/zend.enable_gc">zend.enable_gc</a></td>
+ <td>on</td>
+ <td><?php echo ($ini_zend_enable_gc) ? 'on' : 'off'; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Other</h3>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Test</th>
+ <th>Would Like To Be</th>
+ <th>What You Have</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="<?php echo ($int64_ok) ? 'enabled' : 'disabled'; ?>">
+ <td><a href="https://aws.amazon.com/amis/4158">Architecture</a></td>
+ <td>64-bit</td>
+ <td><?php echo ($int64_ok) ? '64-bit' : '32-bit'; ?><?php if (is_windows()): ?>
+ (<a href="#win64">why?</a>)
+ <?php endif; ?></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <br>
+ </div>
+
+ <?php if ($compatiblity == REQUIREMENTS_ALL_MET): ?>
+ <div class="chunk important ok">
+ <h3>Bottom Line: Yes, you can!</h3>
+ <p>Your PHP environment is ready to go, and can take advantage of all possible features!</p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>You can download the latest version of the <a href="http://aws.amazon.com/sdkforphp"><strong>AWS SDK for PHP</strong></a> and install it by <a href="http://aws.amazon.com/articles/4261">following the instructions</a>. Also, check out our library of <a href="http://aws.amazon.com/articles/4262">screencasts and tutorials</a>.</p>
+ <p>Take the time to read <a href="http://aws.amazon.com/articles/4261">"Getting Started"</a> to make sure you're prepared to use the AWS SDK for PHP. No seriously, read it.</p>
+ </div>
+ <?php elseif ($compatiblity == REQUIREMENTS_MIN_MET): ?>
+ <div class="chunk important ok">
+ <h3>Bottom Line: Yes, you can!</h3>
+ <p>Your PHP environment is ready to go! <i>There are a couple of minor features that you won't be able to take advantage of, but nothing that's a show-stopper.</i></p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>You can download the latest version of the <a href="http://aws.amazon.com/sdkforphp"><strong>AWS SDK for PHP</strong></a> and install it by <a href="http://aws.amazon.com/articles/4261">following the instructions</a>. Also, check out our library of <a href="http://aws.amazon.com/articles/4262">screencasts and tutorials</a>.</p>
+ <p>Take the time to read <a href="http://aws.amazon.com/articles/4261">"Getting Started"</a> to make sure you're prepared to use the AWS SDK for PHP. No seriously, read it.</p>
+ </div>
+ <?php else: ?>
+ <div class="chunk important error">
+ <h3>Bottom Line: We're sorry&hellip;</h3>
+ <p>Your PHP environment does not support the minimum requirements for the <strong>AWS SDK for PHP</strong>.</p>
+ </div>
+ <div class="chunk">
+ <h3>What's Next?</h3>
+ <p>If you're using a shared hosting plan, it may be a good idea to contact your web host and ask them to install a more recent version of PHP and relevant extensions.</p>
+ <p>If you have control over your PHP environment, we recommended that you upgrade your PHP environment. Check out the "Set Up Your Environment" section of the <a href="http://aws.amazon.com/articles/4261">Getting Started Guide</a> for more information.</p>
+ </div>
+ <?php endif; ?>
+
+ <?php if ($compatiblity >= REQUIREMENTS_MIN_MET): ?>
+ <div class="chunk">
+ <h3>Recommended settings for config.inc.php</h3>
+ <p>Based on your particular server configuration, the following settings are recommended.</p>
+ <br>
+ <table cellpadding="0" cellspacing="0" border="0" width="100%" class="chart">
+ <thead>
+ <tr>
+ <th>Configuration Setting</th>
+ <th>Recommended Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>default_cache_config</code></td>
+ <?php if ($apc_ok): ?>
+ <td><code>apc</code></td>
+ <?php elseif ($xcache_ok): ?>
+ <td><code>xcache</code></td>
+ <?php elseif ($file_ok): ?>
+ <td>Any valid, server-writable file system path</td>
+ <?php endif; ?>
+ </tr>
+ <tr>
+ <td><code>certificate_authority</code></td>
+ <?php if (is_windows()): ?>
+ <td id="ssl_check"><code>true</code></td>
+ <?php else: ?>
+ <td id="ssl_check"><img src="<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?loader" alt="Loading..."></td>
+ <?php endif; ?>
+ </tr>
+ </tbody>
+ </table>
+ <br>
+ </div>
+ <?php endif; ?>
+
+ <div class="chunk">
+ <h3>Give me the details!</h3>
+ <?php if ($compatiblity >= REQUIREMENTS_MIN_MET): ?>
+ <ol>
+ <li><em>Your environment meets the minimum requirements for using the <strong>AWS SDK for PHP</strong>!</em></li>
+
+ <?php if (version_compare(PHP_VERSION, '5.3.0') < 0): ?>
+ <li>You're still running <strong>PHP <?php echo PHP_VERSION; ?></strong>. The PHP 5.2 family is no longer supported by the PHP team, and future versions of the AWS SDK for PHP will <i>require</i> PHP 5.3 or newer.</li>
+ <?php endif; ?>
+
+ <?php if ($openssl_ok): ?>
+ <li>The <a href="http://php.net/openssl">OpenSSL</a> extension is installed. This will allow you to use <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> and decrypt Microsoft&reg; Windows&reg; instance passwords.</li>
+ <?php endif; ?>
+
+ <?php if ($zlib_ok): ?>
+ <li>The <a href="http://php.net/zlib">Zlib</a> extension is installed. The SDK will request gzipped data whenever possible.</li>
+ <?php endif; ?>
+
+ <?php if (!$int64_ok): ?>
+ <li>You're running on a <strong>32-bit</strong> system. This means that PHP does not correctly handle files larger than 2GB (this is a <a href="http://www.google.com/search?q=php+2gb+32-bit">well-known PHP issue</a>). For more information, please see: <a href="http://docs.php.net/manual/en/function.filesize.php#refsect1-function.filesize-returnvalues">PHP filesize: Return values</a>.</li>
+ <?php if (is_windows()): ?>
+ <li id="win64"><em>Note that PHP on Microsoft® Windows® <a href="http://j.mp/php64win">does not support 64-bit integers at all</a>, even if both the hardware and PHP are 64-bit.</em></li>
+ <?php endif; ?>
+ <?php endif; ?>
+
+ <?php if ($ini_open_basedir || $ini_safe_mode): ?>
+ <li>You have <a href="http://php.net/open_basedir">open_basedir</a> or <a href="http://php.net/safe_mode">safe_mode</a> enabled in your <code>php.ini</code> file. Sometimes PHP behaves strangely when these settings are enabled. Disable them if you can.</li>
+ <?php endif; ?>
+
+ <?php if (!$ini_zend_enable_gc): ?>
+ <li>The PHP garbage collector (available in PHP 5.3+) is not enabled in your <code>php.ini</code> file. Enabling <a href="http://php.net/zend.enable_gc">zend.enable_gc</a> will provide better memory management in the PHP core.</li>
+ <?php endif; ?>
+
+ <?php
+ $storage_types = array();
+ if ($file_ok) { $storage_types[] = '<a href="http://php.net/file_put_contents">The file system</a>'; }
+ if ($apc_ok) { $storage_types[] = '<a href="http://php.net/apc">APC</a>'; }
+ if ($xcache_ok) { $storage_types[] = '<a href="http://xcache.lighttpd.net">XCache</a>'; }
+ if ($sqlite_ok && $sqlite3_ok) { $storage_types[] = '<a href="http://php.net/sqlite3">SQLite 3</a>'; }
+ elseif ($sqlite_ok && $sqlite2_ok) { $storage_types[] = '<a href="http://php.net/sqlite">SQLite 2</a>'; }
+ if ($memcached_ok) { $storage_types[] = '<a href="http://php.net/memcached">Memcached</a>'; }
+ elseif ($memcache_ok) { $storage_types[] = '<a href="http://php.net/memcache">Memcache</a>'; }
+ ?>
+ <li>Storage types available for response caching: <?php echo implode(', ', $storage_types); ?></li>
+ </ol>
+
+ <?php if (!$openssl_ok && !$zlib_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/openssl">OpenSSL</a> extension, which means that you won't be able to take advantage of <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> or decrypt Microsoft&reg; Windows&reg; instance passwords. You're also missing the <a href="http://php.net/zlib">Zlib</a> extension, which means that the SDK will be unable to request gzipped data from Amazon and you won't be able to take advantage of compression with the <i>response caching</i> feature.</p>
+ <?php elseif (!$zlib_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/zlib">Zlib</a> extension, which means that the SDK will be unable to request gzipped data from Amazon and you won't be able to take advantage of compression with the <i>response caching</i> feature.</p>
+ <?php elseif (!$openssl_ok): ?>
+ <p class="footnote"><strong>NOTE:</strong> You're missing the <a href="http://php.net/openssl">OpenSSL</a> extension, which means that you won't be able to take advantage of <a href="http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html">CloudFront Private URLs</a> or decrypt Microsoft&reg; Windows&reg; instance passwords.</p>
+ <?php endif; ?>
+
+ <?php else: ?>
+ <ol>
+ <?php if (!$php_ok): ?>
+ <li><strong>PHP:</strong> You are running an unsupported version of PHP.</li>
+ <?php endif; ?>
+
+ <?php if (!$curl_ok): ?>
+ <li><strong>cURL:</strong> The <a href="http://php.net/curl">cURL</a> extension is not available. Without cURL, the SDK cannot connect to &mdash; or authenticate with &mdash; Amazon's services.</li>
+ <?php endif; ?>
+
+ <?php if (!$simplexml_ok): ?>
+ <li><strong>SimpleXML:</strong> The <a href="http://php.net/simplexml">SimpleXML</a> extension is not available. Without SimpleXML, the SDK cannot parse the XML responses from Amazon's services.</li>
+ <?php endif; ?>
+
+ <?php if (!$dom_ok): ?>
+ <li><strong>DOM:</strong> The <a href="http://php.net/dom">DOM</a> extension is not available. Without DOM, the SDK cannot transliterate JSON responses from Amazon's services into the common SimpleXML-based pattern used throughout the SDK.</li>
+ <?php endif; ?>
+
+ <?php if (!$spl_ok): ?>
+ <li><strong>SPL:</strong> <a href="http://php.net/spl">Standard PHP Library</a> support is not available. Without SPL support, the SDK cannot autoload the required PHP classes.</li>
+ <?php endif; ?>
+
+ <?php if (!$json_ok): ?>
+ <li><strong>JSON:</strong> <a href="http://php.net/json">JSON</a> support is not available. AWS leverages JSON heavily in many of its services.</li>
+ <?php endif; ?>
+
+ <?php if (!$pcre_ok): ?>
+ <li><strong>PCRE:</strong> Your PHP installation doesn't support Perl-Compatible Regular Expressions (PCRE). Without PCRE, the SDK cannot do any filtering via regular expressions.</li>
+ <?php endif; ?>
+
+ <?php if (!$file_ok): ?>
+ <li><strong>File System Read/Write:</strong> The <a href="http://php.net/file_get_contents">file_get_contents()</a> and/or <a href="http://php.net/file_put_contents">file_put_contents()</a> functions have been disabled. Without them, the SDK cannot read from, or write to, the file system.</li>
+ <?php endif; ?>
+ </ol>
+ <?php endif; ?>
+ </div>
+
+ <div class="chunk">
+ <p class="footnote"><strong>NOTE</strong>: Passing this test does not guarantee that the AWS SDK for PHP will run on your web server &mdash; it only ensures that the requirements have been addressed.</p>
+ </div>
+ </div>
+
+</div>
+
+<?php if (!is_windows()): ?>
+<script type="text/javascript" charset="utf-8">
+reqwest('<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?ssl_check', function(resp) {
+ $sslCheck = document.getElementById('ssl_check');
+ $sslCheck.innerHTML = '';
+ $sslCheck.innerHTML = '<code>' + resp + '</code>';
+});
+</script>
+<?php endif; ?>
+
+</body>
+</html>
diff --git a/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php
new file mode 100755
index 00000000000..a6632d89787
--- /dev/null
+++ b/3rdparty/aws-sdk/_compatibility_test/sdk_compatibility_test_cli.php
@@ -0,0 +1,186 @@
+#! /usr/bin/env php
+<?php
+
+//Prevent script from being called via browser
+if (PHP_SAPI !== 'cli')
+{
+ die('ERROR: You may only run the compatibility test from the command line.');
+}
+
+// Include the compatibility test logic
+require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sdk_compatibility.inc.php';
+
+// CLI display
+function success($s = 'Yes')
+{
+ return is_windows() ? $s : "\033[1;37m\033[42m " . $s . " \033[0m";
+}
+
+function info($s = 'Info')
+{
+ return is_windows() ? $s : "\033[1;37m\033[44m " . $s . " \033[0m";
+}
+
+function failure($s = 'No ')
+{
+ return is_windows() ? $s : "\033[1;37m\033[41m " . $s . " \033[0m";
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+echo PHP_EOL;
+
+echo info('AWS SDK for PHP') . PHP_EOL;
+echo 'PHP Environment Compatibility Test (CLI)' . PHP_EOL;
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+echo 'PHP 5.2 or newer............ ' . ($php_ok ? (success() . ' ' . phpversion()) : failure()) . PHP_EOL;
+echo '64-bit architecture......... ' . ($int64_ok ? success() : failure()) . (is_windows() ? ' (see note below)' : '') . PHP_EOL;
+echo 'cURL with SSL............... ' . ($curl_ok ? (success() . ' ' . $curl_version['version'] . ' (' . $curl_version['ssl_version'] . ')') : failure($curl_version['version'] . (in_array('https', $curl_version['protocols'], true) ? ' (with ' . $curl_version['ssl_version'] . ')' : ' (without SSL)'))) . PHP_EOL;
+echo 'Standard PHP Library........ ' . ($spl_ok ? success() : failure()) . PHP_EOL;
+echo 'SimpleXML................... ' . ($simplexml_ok ? success() : failure()) . PHP_EOL;
+echo 'DOM......................... ' . ($dom_ok ? success() : failure()) . PHP_EOL;
+echo 'JSON........................ ' . ($json_ok ? success() : failure()) . PHP_EOL;
+echo 'PCRE........................ ' . ($pcre_ok ? success() : failure()) . PHP_EOL;
+echo 'File system read/write...... ' . ($file_ok ? success() : failure()) . PHP_EOL;
+echo 'OpenSSL extension........... ' . ($openssl_ok ? success() : failure()) . PHP_EOL;
+echo 'Zlib........................ ' . ($zlib_ok ? success() : failure()) . PHP_EOL;
+echo 'APC......................... ' . ($apc_ok ? success() : failure()) . PHP_EOL;
+echo 'XCache...................... ' . ($xcache_ok ? success() : failure()) . PHP_EOL;
+echo 'Memcache.................... ' . ($memcache_ok ? success() : failure()) . PHP_EOL;
+echo 'Memcached................... ' . ($memcached_ok ? success() : failure()) . PHP_EOL;
+echo 'PDO......................... ' . ($pdo_ok ? success() : failure()) . PHP_EOL;
+echo 'SQLite 2.................... ' . ($sqlite2_ok ? success() : failure()) . PHP_EOL;
+echo 'SQLite 3.................... ' . ($sqlite3_ok ? success() : failure()) . PHP_EOL;
+echo 'PDO-SQLite driver........... ' . ($pdo_sqlite_ok ? success() : failure()) . PHP_EOL;
+echo 'open_basedir disabled....... ' . (!$ini_open_basedir ? success() : failure()) . PHP_EOL;
+echo 'safe_mode disabled.......... ' . (!$ini_safe_mode ? success() : failure()) . PHP_EOL;
+echo 'Garbage Collector enabled... ' . ($ini_zend_enable_gc ? success() : failure()) . PHP_EOL;
+
+// Test SSL cert
+if (!is_windows())
+{
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://email.us-east-1.amazonaws.com');
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($ch, CURLOPT_NOSIGNAL, true);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'aws-sdk-php/compat-cli');
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($ch, CURLOPT_VERBOSE, false);
+ curl_exec($ch);
+ $ssl_result = !(curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT) === 0);
+ curl_close($ch);
+
+ echo 'Valid SSL certificate....... ' . ($ssl_result ? failure() : success()) . PHP_EOL;
+}
+else
+{
+ $ssl_result = false;
+ echo 'Valid SSL certificate....... ' . failure() . ' (will use the bundled certificate instead)' . PHP_EOL;
+}
+
+echo PHP_EOL;
+
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+if ($compatiblity >= REQUIREMENTS_MIN_MET)
+{
+ echo success('Your environment meets the minimum requirements for using the AWS SDK for PHP!') . PHP_EOL . PHP_EOL;
+ if (version_compare(PHP_VERSION, '5.3.0') < 0) { echo '* You\'re still running PHP ' . PHP_VERSION . '. The PHP 5.2 family is no longer supported' . PHP_EOL . ' by the PHP team, and future versions of the AWS SDK for PHP will *require*' . PHP_EOL . ' PHP 5.3 or newer.' . PHP_EOL . PHP_EOL; }
+ if ($openssl_ok) { echo '* The OpenSSL extension is installed. This will allow you to use CloudFront' . PHP_EOL . ' Private URLs and decrypt Windows instance passwords.' . PHP_EOL . PHP_EOL; }
+ if ($zlib_ok) { echo '* The Zlib extension is installed. The SDK will request gzipped data' . PHP_EOL . ' whenever possible.' . PHP_EOL . PHP_EOL; }
+ if (!$int64_ok) { echo '* You\'re running on a 32-bit system. This means that PHP does not correctly' . PHP_EOL . ' handle files larger than 2GB (this is a well-known PHP issue).' . PHP_EOL . PHP_EOL; }
+ if (!$int64_ok && is_windows()) { echo '* Note that PHP on Microsoft(R) Windows(R) does not support 64-bit integers' . PHP_EOL . ' at all, even if both the hardware and PHP are 64-bit. http://j.mp/php64win' . PHP_EOL . PHP_EOL; }
+
+ if ($ini_open_basedir || $ini_safe_mode) { echo '* You have open_basedir or safe_mode enabled in your php.ini file. Sometimes' . PHP_EOL . ' PHP behaves strangely when these settings are enabled. Disable them if you can.' . PHP_EOL . PHP_EOL; }
+ if (!$ini_zend_enable_gc) { echo '* The PHP garbage collector (available in PHP 5.3+) is not enabled in your' . PHP_EOL . ' php.ini file. Enabling zend.enable_gc will provide better memory management' . PHP_EOL . ' in the PHP core.' . PHP_EOL . PHP_EOL; }
+
+ $storage_types = array();
+ if ($file_ok) { $storage_types[] = 'The file system'; }
+ if ($apc_ok) { $storage_types[] = 'APC'; }
+ if ($xcache_ok) { $storage_types[] = 'XCache'; }
+ if ($sqlite_ok && $sqlite3_ok) { $storage_types[] = 'SQLite 3'; }
+ elseif ($sqlite_ok && $sqlite2_ok) { $storage_types[] = 'SQLite 2'; }
+ if ($memcached_ok) { $storage_types[] = 'Memcached'; }
+ elseif ($memcache_ok) { $storage_types[] = 'Memcache'; }
+ echo '* Storage types available for response caching:' . PHP_EOL . ' ' . implode(', ', $storage_types) . PHP_EOL . PHP_EOL;
+
+ if (!$openssl_ok) { echo '* You\'re missing the OpenSSL extension, which means that you won\'t be able' . PHP_EOL . ' to take advantage of CloudFront Private URLs or Windows password decryption.' . PHP_EOL . PHP_EOL; }
+ if (!$zlib_ok) { echo '* You\'re missing the Zlib extension, which means that the SDK will be unable' . PHP_EOL . ' to request gzipped data from Amazon and you won\'t be able to take advantage' . PHP_EOL . ' of compression with the response caching feature.' . PHP_EOL . PHP_EOL; }
+}
+else
+{
+ if (!$php_ok) { echo '* ' . failure('PHP:') . ' You are running an unsupported version of PHP.' . PHP_EOL . PHP_EOL; }
+ if (!$curl_ok) { echo '* ' . failure('cURL:') . ' The cURL extension is not available. Without cURL, the SDK cannot' . PHP_EOL . ' connect to -- or authenticate with -- Amazon\'s services.' . PHP_EOL . PHP_EOL; }
+ if (!$simplexml_ok) { echo '* ' . failure('SimpleXML:') . ': The SimpleXML extension is not available. Without SimpleXML,' . PHP_EOL . ' the SDK cannot parse the XML responses from Amazon\'s services.' . PHP_EOL . PHP_EOL; }
+ if (!$dom_ok) { echo '* ' . failure('DOM:') . ': The DOM extension is not available. Without DOM, the SDK' . PHP_EOL . ' Without DOM, the SDK cannot transliterate JSON responses from Amazon\'s' . PHP_EOL . ' services into the common SimpleXML-based pattern used throughout the SDK.' . PHP_EOL . PHP_EOL; }
+ if (!$spl_ok) { echo '* ' . failure('SPL:') . ' Standard PHP Library support is not available. Without SPL support,' . PHP_EOL . ' the SDK cannot autoload the required PHP classes.' . PHP_EOL . PHP_EOL; }
+ if (!$json_ok) { echo '* ' . failure('JSON:') . ' JSON support is not available. AWS leverages JSON heavily in many' . PHP_EOL . ' of its services.' . PHP_EOL . PHP_EOL; }
+ if (!$pcre_ok) { echo '* ' . failure('PCRE:') . ' Your PHP installation doesn\'t support Perl-Compatible Regular' . PHP_EOL . ' Expressions (PCRE). Without PCRE, the SDK cannot do any filtering via' . PHP_EOL . ' regular expressions.' . PHP_EOL . PHP_EOL; }
+ if (!$file_ok) { echo '* ' . failure('File System Read/Write:') . ' The file_get_contents() and/or file_put_contents()' . PHP_EOL . ' functions have been disabled. Without them, the SDK cannot read from,' . PHP_EOL . ' or write to, the file system.' . PHP_EOL . PHP_EOL; }
+}
+
+echo '----------------------------------------' . PHP_EOL;
+echo PHP_EOL;
+
+if ($compatiblity === REQUIREMENTS_ALL_MET)
+{
+ echo success('Bottom Line: Yes, you can!') . PHP_EOL;
+ echo PHP_EOL;
+ echo 'Your PHP environment is ready to go, and can take advantage of all possible features!' . PHP_EOL;
+
+ echo PHP_EOL;
+ echo info('Recommended settings for config.inc.php') . PHP_EOL;
+ echo PHP_EOL;
+
+ echo "CFCredentials::set(array(" . PHP_EOL;
+ echo " '@default' => array(" . PHP_EOL;
+ echo " 'key' => 'aws-key'," . PHP_EOL;
+ echo " 'secret' => 'aws-secret'," . PHP_EOL;
+ echo " 'default_cache_config' => ";
+ if ($apc_ok) echo success('\'apc\'');
+ elseif ($xcache_ok) echo success('\'xcache\'');
+ elseif ($file_ok) echo success('\'/path/to/cache/folder\'');
+ echo "," . PHP_EOL;
+ echo " 'certificate_authority' => " . success($ssl_result ? 'true' : 'false') . PHP_EOL;
+ echo " )" . PHP_EOL;
+ echo "));" . PHP_EOL;
+}
+elseif ($compatiblity === REQUIREMENTS_MIN_MET)
+{
+ echo success('Bottom Line: Yes, you can!') . PHP_EOL;
+ echo PHP_EOL;
+ echo 'Your PHP environment is ready to go! There are a couple of minor features that' . PHP_EOL . 'you won\'t be able to take advantage of, but nothing that\'s a show-stopper.' . PHP_EOL;
+
+ echo PHP_EOL;
+ echo info('Recommended settings for config.inc.php') . PHP_EOL;
+ echo PHP_EOL;
+
+ echo "CFCredentials::set(array(" . PHP_EOL;
+ echo " '@default' => array(" . PHP_EOL;
+ echo " 'key' => 'aws-key'," . PHP_EOL;
+ echo " 'secret' => 'aws-secret'," . PHP_EOL;
+ echo " 'default_cache_config' => ";
+ if ($apc_ok) echo success('\'apc\'');
+ elseif ($xcache_ok) echo success('\'xcache\'');
+ elseif ($file_ok) echo success('\'/path/to/cache/folder\'');
+ echo "," . PHP_EOL;
+ echo " 'certificate_authority' => " . ($ssl_result ? 'false' : 'true') . PHP_EOL;
+ echo " )" . PHP_EOL;
+ echo "));" . PHP_EOL;
+}
+else
+{
+ echo failure('Bottom Line: We\'re sorry...') . PHP_EOL;
+ echo 'Your PHP environment does not support the minimum requirements for the ' . PHP_EOL . 'AWS SDK for PHP.' . PHP_EOL;
+}
+
+echo PHP_EOL;
diff --git a/3rdparty/aws-sdk/_docs/CHANGELOG.md b/3rdparty/aws-sdk/_docs/CHANGELOG.md
new file mode 100644
index 00000000000..52db66f4f6f
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/CHANGELOG.md
@@ -0,0 +1,1405 @@
+# Changelog: 1.5.6.2 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 29th, 2012.
+
+## Services
+### AmazonDynamoDB
+- **Fixed:** STS credentials were not always being cached correctly.
+
+----
+
+# Changelog: 1.5.6.1 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 24th, 2012.
+
+## Services
+### AmazonDynamoDB
+- **Fixed:** STS credentials were not always being cached correctly.
+
+----
+
+# Changelog: 1.5.6 "Gershwin"
+Code name for Apple's never-released successor to the never-released Copeland. <http://en.wikipedia.org/wiki/Gershwin_operating_system>
+
+Launched Tuesday, May 15th, 2012.
+
+## Services
+### AmazonSES
+- **New:** Support for domain verification has been added to the SDK, which enables customers to verify an entire email domain.
+- **New:** Requests to this service are now signed with Signature V4.
+
+----
+
+# Changelog: 1.5.5 "Fishhead"
+Code name for the Apple II File Mangement Utility. <http://applemuseum.bott.org/sections/codenames.html>
+
+Launched Wednesday, May 9, 2012.
+
+## Services
+### AmazonCloudFormation
+* **New:** Requests to this service are now signed with Signature V4.
+
+### AmazonCloudFront
+* **New:** Updated the supported API version to `2012-03-15`.
+
+### AmazonDynamoDB
+* **New:** Support for the US West (Northern California), US West (Oregon), Asia Pacific "Southeast" (Signapore) endpoints have been added.
+
+### AmazonElasticBeanstalk
+* **New:** Support for the new Asia Pacific "Northeast" (Japan) endpoint has been added.
+
+### AmazonStorageGateway
+* **New:** Support for the AWS Storage Gateway service has been added to the SDK.
+
+---
+
+# Changelog: 1.5.4 "Enterprise"
+Code name for Mac OS X Server 1.0 (Rhapsody CR1). <http://en.wikipedia.org/wiki/Rhapsody_(operating_system)>
+
+Launched Thursday, April 19, 2012.
+
+## Bug fixes and enhancements
+* [PHP SDK Bug - Memory leak](https://forums.aws.amazon.com/thread.jspa?threadID=72310)
+* [Does update_object work in 1.5.3?](https://forums.aws.amazon.com/thread.jspa?threadID=89297)
+* [The value of CURLOPT_SSL_VERIFYHOST](https://forums.aws.amazon.com/thread.jspa?threadID=86186)
+* [PHP SDK BUG: s3.class.php Line 2396 on 1.5.2](https://forums.aws.amazon.com/thread.jspa?threadID=86779)
+* [first create_bucket(), then get_bucket_list()](https://forums.aws.amazon.com/thread.jspa?messageID=318885)
+* [Issue with AmazonS3::get_object_list() max-keys](https://forums.aws.amazon.com/thread.jspa?threadID=85878)
+* [Correct the "Bottom line" minimum requirements check](https://github.com/amazonwebservices/aws-sdk-for-php/pull/23)
+* [S3 PHP SDK: copy_object() fails to update the header](http://stackoverflow.com/questions/7677837/s3-php-sdk-copy-object-fails-to-update-the-header)
+* [Adds the following utility methods to simplexml.class.php](https://github.com/amazonwebservices/aws-sdk-for-php/pull/22)
+* [Adding the ability to name a 'rule' for Object Expiration (suggested tweak)](https://forums.aws.amazon.com/thread.jspa?messageID=328023)
+
+## Runtime
+* **New:** Support for Signature Version 4 has been added to the SDK. Signature Version 4 is now the default authentication method for AWS Identity and Access Management, AWS Security Token Service and Amazon CloudSearch.
+
+## Services
+### AmazonCloudFront
+* **New:** Support for a Minimum TTL of zero has been added to the SDK.
+
+### AmazonCloudSearch
+* **New:** Support for Amazon CloudSearch has been added to the SDK. This includes only the Configuration API.
+
+### AmazonDynamoDB
+* **New:** Support for BatchWriteItem API has been added to the SDK.
+* **New:** Support for the European (Ireland) endpoint has been added.
+* **New:** Support for the Asia Pacific "Northeast" (Tokyo) endpoint has been added.
+* **New:** Amazon DynamoDB Session Handler has been added to the SDK.
+* **New:** A simplified interface for adding attributes has been added to the SDK.
+
+### AmazonEC2
+* **New:** The new "m1.medium" instance type is now supported.
+* **New:** Amazon EBS support for Volume Status and Volume Attributes have been added to the SDK.
+* **New:** Amazon EBS support for Conversion Tasks has been added to the SDK.
+* **New:** Amazon EC2 support for the Report Instance Status feature has been added to the SDK.
+* **New:** Amazon VPC support for Network Interfaces has been added to the SDK.
+* **Fixed:** Various parameter fixes have been applied.
+
+### AmazonIAM
+* **New:** Support for Password Policies and the ability to change passwords has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for pre-signed URLs using temporary credentials has been added to the SDK.
+* **New:** Support for setting a custom name to Lifecycle (i.e., Object Expiration) rules has been added to the SDK.
+* **New:** Support for pre-signed URLs with https has been added to the SDK.
+* **Fixed:** Resolved an issue where setting a custom XML parsing class was not being respected.
+* **Fixed:** Resolved an issue where the `get_object_list()` method would return an incorrect number of entries.
+* **Fixed:** Resolved an issue where `update_object()` was attempting to COPY instead of REPLACE.
+* **Fixed:** Resolved an issue stemming from using path-style URLs, `create_bucket()` + `list_bucket()` and the EU-West region.
+* **Fixed:** Resolved an issue where XML responses were not being parsed consistently.
+* **Fixed:** Resolved an issue where Private Streaming URLs contained a double-encoded signature.
+* **Fixed:** The `Expect: 100-continue` HTTP header is now only sent during `create_object()` and `upload_part()` requests.
+
+## Utilities
+### CFRuntime
+* **Fixed:** Resolved an issue where `CURLOPT_SSL_VERIFYHOST` was not set strictly enough.
+* **Fixed:** The `Expect: 100-continue` HTTP header is no longer set on every request.
+
+### CFSimpleXML
+* **New:** Support for `matches()`, `starts_with()` and `ends_with()` methods have been added to the SDK. (Thanks [Wil Moore III](https://github.com/wilmoore)!)
+
+## Compatibility Test
+* **New:** SDK Compatibility Test pages are marked up as to not be indexed by search engines. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** Duplicate code between the CLI and web versions of the SDK has been refactored. (Thanks [Jimmy Berry](https://github.com/boombatower)!)
+
+---
+
+# Changelog: 1.5.3 "Darwin"
+UNIX foundation upon which Mac OS X, Apple TV, and iOS are based. <http://en.wikipedia.org/wiki/Darwin_operating_system>
+
+Launched Wednesday, Tuesday, February 21, 2012.
+
+## Bug fixes and enhancements
+* [Fixing Issue with set_distribution_config](https://github.com/amazonwebservices/aws-sdk-for-php/pull/20)
+
+## Services
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the `set_distribution_config()` method could fail to satisfy an API constraint when using a custom origin server. (Thanks [zoxa](https://github.com/zoxa)!)
+
+### AmazonSWF
+* **New:** Support for the new Amazon Simple Workflow Service has been added to the SDK.
+
+----
+
+# Changelog: 1.5.2 "Copland"
+Code name for Apple's never-released successor to System 7. <http://en.wikipedia.org/wiki/Copland_(operating_system)>
+
+Launched Wednesday, Febraury 1, 2012.
+
+## Bug fixes and enhancements
+* [SSL Cert on PHP SDK 1.5.0.1 ](https://forums.aws.amazon.com/thread.jspa?threadID=84947)
+* [Stream Wrapper need a buffer !](https://forums.aws.amazon.com/thread.jspa?threadID=85436)
+* [Fixing Issue with set_distribution_config](https://github.com/amazonwebservices/aws-sdk-for-php/pull/20)
+* [[Bug] SDK Autoloader Interferes with PHPExcel Autoloader](https://forums.aws.amazon.com/thread.jspa?threadID=85239)
+* [get_object query does not always return the same content type](https://forums.aws.amazon.com/thread.jspa?threadID=84148)
+* [AWSSDKforPHP/authentication/swift_transport_esmtp_signature_handler.class.p ](https://forums.aws.amazon.com/thread.jspa?threadID=85087)
+
+## Runtime
+* **New:** Updated the CA Root Certificates file to version 1.81.
+* **Fixed:** Resolved an issue in the autoloader where the matching logic was too aggressive in certain cases, causing subsequent autoloaders to never trigger.
+
+## Services
+### AmazonAS
+* **New:** Support for Auto Scaling Resource Tagging has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Resolved an issue where `delete_all_objects()` and `delete_all_object_versions()` was being limited to 1000 items.
+* **Fixed:** Resolved an issue where `delete_bucket()` would fail to delete a bucket with the "force" option enabled if the bucket contained more than 1000 items.
+* **Fixed:** Resolved an issue where JSON documents stored in Amazon S3 would be parsed into a native PHP object when retrieved.
+
+## Utilities
+### S3StreamWrapper
+* **New:** Support for multiple stream wrappers (e.g., one per region) has been added to the SDK.
+* **Fixed:** Writes to Amazon S3 are now buffered, resolving issues with pushing more than 8k of data at a time.
+
+### CFJSON
+* **Fixed:** The JSON-to-XML conversion code is now substantially more robust and better handles encoded characters.
+
+### CacheCore
+* **Changed:** Formerly, attempting to cache to a file system location that didn't exist or was not writable by the PHP process would fail silently. This behavior has been changed to throw a `CacheFile_Exception`.
+
+----
+
+# Changelog: 1.5.1 "Blue"
+Code name for Macintosh System 7. <http://en.wikipedia.org/wiki/System_7>
+
+Launched Wednesday, January 18, 2012.
+
+## Bug fixes and enhancements
+* [Documentation patch](https://github.com/amazonwebservices/aws-sdk-for-php/pull/13)
+* [Removed duplicate comment line.](https://github.com/amazonwebservices/aws-sdk-for-php/pull/17)
+* [CFRuntime credentials handling issue](https://forums.aws.amazon.com/thread.jspa?messageID=310388)
+* [PHP 5.2 bug in AWS SDK for PHP 1.5.x](https://forums.aws.amazon.com/thread.jspa?messageID=311543)
+* [[Bug] Custom Curl Opts Lost During Retry](https://forums.aws.amazon.com/thread.jspa?threadID=84835)
+* [json_last_error doesn't exist before php v 5.3.0](https://github.com/amazonwebservices/aws-sdk-for-php/pull/12)
+* [XML still being parsed when use_cache_flow is false](https://github.com/amazonwebservices/aws-sdk-for-php/pull/15)
+* [Bug ssl_verification option not respected for AmazonS3 ](https://forums.aws.amazon.com/thread.jspa?threadID=83710)
+* [[Bug] Compatibility test for Garbage Collector enabled should use ini_get](https://forums.aws.amazon.com/thread.jspa?threadID=84156)
+
+## Runtime
+* **Fixed:** Corrected an issue where calling `AmazonS3->get_object()` would continue to parse the content if caching was being leveraged. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** The autoloader now returns `false` for any class it doesn't match, allowing subsequent autoloaders to catch the class name. (Thanks [Eric Caron](http://www.ericcaron.com)!)
+* **Fixed:** An issue that caused CloudWatch to fail to decompress gzipped data correctly has been resolved.
+* **Fixed:** Resolved an issue with passing explicit credentials without requiring a config file or a `CFCredentials` declaration.
+* **Fixed:** Resolved an issue which causes custom cURL options to be unset from the payload when retrying.
+
+## Services
+### AmazonAS
+* **New:** Support for Amazon SNS notifications and Tagging have been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Resolved an issue with disabling SSL verification.
+* **Fixed:** Resolved an issue where `AmazonCloudFront` were throwing warnings in `E_STRICT` mode.
+
+### AmazonCloudWatch
+* **Fixed:** Resolved an issue with decompressing gzipped data.
+
+### AmazonDynamoDB
+* **New:** Support for Amazon DynamoDB has been added to the SDK.
+* **New:** Amazon DynamoDB requires a default cache configuration to be set in the credential set, otherwise it will not function properly.
+
+### AmazonS3
+* **Fixed:** Resolved an issue with disabling SSL verification.
+* **Fixed:** Resolved multiple documentation issues. (Thanks [Aizat Faiz](http://aizatto.com) and [Jason Ardell](http://ardell.posterous.com/)!)
+* **Fixed:** Resolved an issue where `AmazonS3` were throwing warnings in `E_STRICT` mode.
+
+### AmazonSNS
+* **New:** Support for Short Messaging Service (SMS) endpoints has been added to the SDK.
+* **New:** Support for Subscription Attributes has been added to the SDK.
+
+## Utilities
+### CFJSON
+* **Fixed:** Support for the handling of JSON nulls in PHP 5.2 has been improved. (Thanks [David Chan](http://www.chandeeland.org)!)
+
+## Compatibility Test
+* **Fixed:** The SDK compatibility test now uses `ini_get()` instead of `get_cfg_var()` and `get_cfg_ini()` for more accurate test results.
+
+
+----
+
+# Changelog: 1.5 "Allegro"
+Code name for Mac OS 8.5. <http://en.wikipedia.org/wiki/Mac_OS_8#Mac_OS_8.5>
+
+Launched Wednesday, December 14, 2011
+
+## Credentials
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The function signature of all service constructors has changed. Instead of passing a key and secret as the first and second parameters, the constructor now accepts a hash (associative array) containing `key` and `secret` keys. Please see the API reference documentation
+
+## Runtime
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The function signature of all service constructors has changed. Instead of passing a key and secret as the first and second parameters, the constructor now accepts a hash (associative array) containing `key` and `secret` keys. If you are explicitly passing a key and secret to the constructor, you will need to change your code. If you are simply inheriting your default credentials from a config file, you don't need to make any changes beyond upgrading your config file to the new 1.5 format. Please see the API reference documentation for more information.
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The method by which the `config.inc.php` file maintains its list of credentials has been re-factored and updated to support managing multiple sets of credentials in a single location (e.g., development, staging, production).
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The `init()` method has been renamed to `factory()` to better reflect what it actually does.
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - The `adjust_offset()` method has been removed. Instead, please ensure that the machine's time is set correctly using an [NTP server](https://secure.wikimedia.org/wikipedia/en/wiki/Network_Time_Protocol).
+* !! BACKWARDS-INCOMPATIBLE CHANGE !! - In version 1.4 we enabled a mode where -- for services that supported it -- a set of temporary credentials were fetched and cached before the first request. This functionality has been reverted. The use of short-term credentials must be explicitly enabled by instantiating the `AmazonSTS` class and passing those credentials into the service constructor.
+* **New:** Improved the user directory lookup for the config file.
+* **Changed:** Made `set_region()` an alias of `set_hostname()`.
+
+## Services
+### AmazonAS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonCloudFormation
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for cost estimation of CloudFormation templates has been added to the SDK.
+
+### AmazonCloudWatch
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonEC2
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for 24x7 Reserved Instances has been added to the SDK. For more information, please see [New Amazon EC2 Reserved Instance Options Now Available](https://aws.amazon.com/about-aws/whats-new/2011/12/01/New-Amazon-EC2-Reserved-Instances-Options-Now-Available/).
+* **New:** Support for VPC Spot Instances has been added to the SDK. For more information, please see [Announcing Amazon EC2 Spot Integration with Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/10/11/announcing-amazon-ec2-spot-integration-with-amazon-vpc/).
+* **New:** Support for VPC Everywhere has been added to the SDK. For more information, please see [Amazon VPC Generally Available in Multiple AZs in All Regions](https://aws.amazon.com/about-aws/whats-new/2011/08/03/Announcing-VPC-GA/).
+* **New:** Instance Type-related constants have been added to the SDK: `INSTANCE_MICRO`, `INSTANCE_SMALL`, `INSTANCE_LARGE`, `INSTANCE_XLARGE`, `INSTANCE_HIGH_MEM_XLARGE`, `INSTANCE_HIGH_MEM_2XLARGE`, `INSTANCE_HIGH_MEM_4XLARGE`, `INSTANCE_HIGH_CPU_MEDIUM`, `INSTANCE_HIGH_CPU_XLARGE`, `INSTANCE_CLUSTER_4XLARGE`, `INSTANCE_CLUSTER_8XLARGE`, `INSTANCE_CLUSTER_GPU_XLARGE`.
+
+### AmazonElastiCache
+* **New:** Support for US-West 1 (California), EU-West (Ireland), Asia Pacific Southeast (Singapore), and Asia Pacific Northeast (Tokyo) regions has been added to the SDK. For more information, please see [Amazon ElastiCache is now available in four additional AWS Regions and as a CloudFormation template](https://aws.amazon.com/about-aws/whats-new/2011/12/05/amazon-elasticache-new-regions/).
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`
+
+### AmazonElasticBeanstalk
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonELB
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for ELBs running in VPC has been added to the SDK. For more information, please see [Announcing Elastic Load Balancing in Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/11/21/announcing-elastic-load-balancing-in-amazon-vpc/).
+
+### AmazonEMR
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for EMR AMI Versioning, new Hadoop and Pig versions, and EMR running in VPC has been added to the SDK. For more information, please see [Amazon Elastic MapReduce Announces Support for New Hadoop and Pig Versions, AMI Versioning, and Amazon VPC](https://aws.amazon.com/about-aws/whats-new/2011/12/11/amazon-elastic-mapreduce-ami-versioning-vpc/).
+
+### AmazonIAM
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonImportExport
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonRDS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonS3
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+* **New:** Support for an S3 Stream Wrapper has been added to the SDK. This enables users to read/write to Amazon S3 as though it were the local file system.
+**Fixed:** The `get_object()` method no longer attempts to parse XML/JSON content.
+**Fixed:** Simplified S3 region logic. Now uses fully-qualified domain names across the board.
+
+### AmazonSES
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+### AmazonSDB
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSNS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSQS
+* **New:** Support for the South American (São Paulo) region has been added to the SDK.
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`, `REGION_CALIFORNIA`, `REGION_OREGON`, `REGION_IRELAND`, `REGION_SINGAPORE`, `REGION_TOKYO`, `REGION_SAO_PAULO`
+
+### AmazonSTS
+* **New:** Plain english aliases have been added to the SDK: `REGION_VIRGINA`
+
+
+----
+
+# Changelog: 1.4.8 "Zanarkand"
+<http://finalfantasy.wikia.com/wiki/Zanarkand>
+
+Launched Wednesday, December 7, 2011
+
+## Services
+### AmazonCloudFront
+* **Fixed:** Merged in a pull request contributed by Ben Lumley: <https://github.com/amazonwebservices/aws-sdk-for-php/pull/11>
+
+### AmazonEC2
+* **Fixed:** Resolved an issue where `set_region()` was not setting the correct endpoint for the region.
+
+### AmazonS3
+* **New:** Support for S3-side multi-object delete has been added to the SDK as the `delete_objects()` method. The implementations of `delete_all_objects()` and `delete_all_object_versions()` have been updated to use this new functionality.
+* **Changed:** XML and JSON responses from `get_object()` are no longer parsed. The raw XML and JSON string content is now returned.
+
+
+----
+
+# Changelog: 1.4.7 "Yuna"
+<http://finalfantasy.wikia.com/wiki/Yuna>
+
+Launched Wednesday, November 9, 2011
+
+## Service Classes
+### AmazonAS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonCloudFormation
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonCloudWatch
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonEC2
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonELB
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonEMR
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonIAM
+* **New:** Support for the US GovCloud region has been added to the SDK.
+
+### AmazonRDS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+* **Fixed:** Resolved an issue where certain bits of metadata were not maintained during a copy operation. <https://forums.aws.amazon.com/thread.jspa?threadID=77630>
+* **Fixed:** Resolved an issue where an unsuccessful lookup of an existing content-type would throw a warning. <https://forums.aws.amazon.com/thread.jspa?threadID=78121>
+* **Fixed:** Resolved an issue where an exception would be thrown when a filesize lookup was attempted on an object that didn't exist. <https://forums.aws.amazon.com/thread.jspa?threadID=78197>
+
+### AmazonSDB
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonSNS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+### AmazonSQS
+* **New:** Support for the US-West 2 (Oregon) region has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.6 "Xezat"
+<http://finalfantasy.wikia.com/wiki/Xezat>
+
+Launched Thursday, November 3, 2011
+
+## Service Classes
+### AmazonIAM
+* **New:** Support for a virtual MFA device. A virtual MFA device uses a software application that can generate six-digit authentication codes that are Open AuTHentication Time-based One-Time Password (OATHTOTP)-compatible. The software application can run on any mobile hardware device, including a smartphone.
+
+
+----
+
+# Changelog: 1.4.5 "Weiss"
+<http://finalfantasy.wikia.com/wiki/Weiss>
+
+Launched Friday, October 21, 2011
+
+## Service Classes
+### AmazonSQS
+* **New:** Support for delayed queues and batch operations has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.4 "Vaan"
+<http://finalfantasy.wikia.com/wiki/Vaan>
+
+Launched Tuesday, October 12, 2011
+
+## Runtime
+* **Fixed:** Resolved an issue where a segmentation fault is triggererd when there are multiple autoloaders in the stack and one of them doesn't return a value.
+
+## Service Classes
+### AmazonS3
+* **New:** Support for server-side encryption has been added to the SDK.
+
+
+----
+
+# Changelog: 1.4.3 "Ultros"
+<http://finalfantasy.wikia.com/wiki/Ultros>
+
+Launched Friday, September 30, 2011
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for new features in CloudFormation have been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Setting the default cache configuration no longer causes authentication errors in `AmazonS3`.
+
+
+----
+
+# Changelog: 1.4.2.1 "Tiamat, Part II"
+<http://finalfantasy.wikia.com/wiki/Tiamat>
+
+Launched Wednesday, September 7, 2011
+
+## Utility Classes
+### RequestCore
+* **Fixed:** RequestCore has updated the `cacert.pem` file from Mozilla. This update revokes trust from the DigiNotar and Staat der Nederlanden root certificates.
+
+
+----
+
+# Changelog: 1.4.2 "Tiamat"
+<http://finalfantasy.wikia.com/wiki/Tiamat>
+
+Launched Thursday, September 1, 2011
+
+## Service Classes
+### AmazonEC2
+* **Fixed:** Requests made to Amazon EC2 now use the correct API version (2011-07-15).
+
+### AmazonELB
+* **New:** A pre-defined set of ciphers may now be used for SSL termination at the Elastic Load Balancer.
+* **New:** Application servers can now accept secure communication from the corresponding Elastic Load Balancer.
+* **New:** In cases where HTTPS is required for all traffic entering the back-end server, Elastic Load Balancing can now perform health checks using HTTPS.
+* **New:** White list of public keys can now be associated with back-end servers. Elastic Load Balancing authenticates back-end servers with the public keys in the white list and communicates only with back-end servers that pass this authentication check.
+
+## Utility Classes
+### RequestCore
+* **Fixed:** RequestCore has updated the `cacert.pem` file from Mozilla. This update revokes trust from the DigiNotar root certificate.
+
+
+----
+
+# Changelog: 1.4.1 "Sephiroth"
+<http://finalfantasy.wikia.com/wiki/Sephiroth>
+
+Launched Tuesday, August 23, 2011
+
+## Service Classes
+### AmazonElastiCache
+* **New:** Support for Amazon ElastiCache has been added to the SDK.
+
+### AmazonEMR
+* **New:** Support for Hadoop Bootstrap Actions has been added to the SDK.
+* **New:** Support for Amazon Elastic MapReduce on Spot Instances has been added to the SDK.
+* **New:** Support for Termination Protection has been added to the SDK.
+* **Changed:** For the <code>add_instance_groups()</code> method, the <code>$instance_groups</code> and <code>$job_flow_id</code> parameters have been reversed.
+
+## Utility Classes
+### CFHadoopBootstrap
+* **New:** The `CFHadoopBootstrap` class has been added to the SDK. Simplifies the process of working with Hadoop system and daemon configurations in Amazon EMR.
+* **New:** This class extends from the `CFHadoopBase` class.
+
+
+----
+
+# Changelog: 1.4 "Rikku"
+<http://finalfantasy.wikia.com/wiki/Rikku>
+
+Launched Wednesday, August 3, 2011
+
+## Bug fixes and enhancements
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSNS
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSQS
+* **New:** Support for Session-Based Authentication (SBA) leveraging Amazon Secure Token Service (STS) has been added to the SDK.
+
+### AmazonSTS
+* **New:** Support for the Amazon Secure Token Service (STS) has been added to the SDK.
+
+## Utility Classes
+### CFRuntime
+* **New:** The following anonymous datapoints are now collected in aggregate so that we can make more informed decisions about future SDK features: `memory_limit`, `date.timezone`, `open_basedir`, `safe_mode`, `zend.enable_gc`.
+
+## Compatibility Test
+* **New:** Support for verifying the installed SSL certificate has been added to the compatibility test.
+* **New:** Support for verifying the status of `open_basedir` and `safe_mode` has been added to the compatibility test.
+* **New:** Support for verifying the status of the PHP 5.3 garbage collector has been added to the compatibility test.
+* **New:** The compatibility test now recommends optimal values for the `AWS_CERTIFICATE_AUTHORITY` and `AWS_DEFAULT_CACHE_CONFIG` configuration options based on the system's configuration.
+
+
+----
+
+# Changelog: 1.3.7 "Quistis"
+<http://finalfantasy.wikia.com/wiki/Quistis_Trepe>
+
+Launched Monday, July 25, 2011
+
+## Bug fixes and enhancements
+* Addressed minor bug fixes reported via the feedback form in the API Reference.
+
+## Service Classes
+### AmazonAS
+* **Changed:** Introduced backwards-incompatible changes to the <code>put_scheduled_update_group_action()</code> method.
+
+
+----
+
+# Changelog: 1.3.6 "Penelo"
+<http://finalfantasy.wikia.com/wiki/Penelo>
+
+Launched Tuesday, July 12, 2011
+
+## Bug fixes and enhancements
+* [[Bug Report] rawurlencode error when using SES and curlopts](https://forums.aws.amazon.com/thread.jspa?threadID=68484)
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for the `list_stacks()` method has been added to the SDK.
+
+### AmazonElasticBeanstalk
+* **New:** Support for the `swap_environment_cnames()` method has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Additional information about maximum open connections has been added to the `create_mpu_object()` method.
+
+## Compatibility Test
+* **New:** Now tests whether the system is 64- or 32-bit.
+
+
+----
+
+# Changelog: 1.3.5 "Occuria"
+<http://finalfantasy.wikia.com/wiki/Occuria>
+
+Launched Tuesday, June 21, 2011
+
+## Service Classes
+### AmazonS3
+* **New:** Support for S3 copy part has been added to the SDK.
+
+
+----
+
+# Changelog: 1.3.4 "Nero"
+<http://finalfantasy.wikia.com/wiki/Nero>
+
+Launched Tuesday, June 7, 2011
+
+## Bug fixes and enhancements
+* [Bug in PHP SDK](https://forums.aws.amazon.com/thread.jspa?threadID=67502)
+* [cURL error: SSL certificate problem (60) with aws-sdk-for-php 1.3.3](https://forums.aws.amazon.com/thread.jspa?threadID=68349)
+
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for Local Availability Zone Pricing has been added to the SDK.
+
+### AmazonELB
+* **New:** Elastic Load Balancing provides a special Amazon EC2 security group that you can use to ensure that a back-end Amazon EC2 instance receives traffic only from its load balancer.
+
+### AmazonRDS
+* **New:** Support for Oracle databases has been added to the SDK.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+* **New:** Added support for associative arrays to `each()`, `map()` and `filter()`.
+
+### CFRequest
+* **New:** Now supports the `AWS_CERTIFICATE_AUTHORITY` configuration option.
+
+
+----
+
+# Changelog: 1.3.3 "Moogle"
+<http://finalfantasy.wikia.com/wiki/Moogle>
+
+Launched Tuesday, May 10, 2011
+
+## Bug fixes and enhancements
+* [Bug in AmazonCloudFront::get_private_object_url](https://forums.aws.amazon.com/thread.jspa?threadID=64004)
+* [SDK 1.3.2 - Call to undefined function json_last_error()](https://forums.aws.amazon.com/thread.jspa?threadID=64767)
+* [CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir](https://forums.aws.amazon.com/thread.jspa?threadID=61333)
+
+
+## Service Classes
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the expires value for `get_private_object_url()` only accepted a string instead of a string or integer.
+
+### AmazonCloudWatch
+* **New:** Support for CloudWatch custom user metrics has been added to the SDK.
+
+
+## Extensions
+### S3BrowserUpload
+* **New:** Added the `S3BrowserUpload` class to the SDK. This class assists in generating the correct HTML/XHTML markup for uploading files to S3 via an HTML <form> element.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the `init()` method which simplifies the process of instantiating and chaining a class.
+
+### CFHadoopBase
+* **New:** The `CFHadoopBase` class has been extracted out of `CFHadoopStep` as a shared library.
+
+### CFHadoopStep
+* **New:** The `CFHadoopBase` class has been extracted out of `CFHadoopStep` as a shared library.
+* **New:** This class now extends from the `CFHadoopBase` class.
+
+### CFJSON
+* **Fixed:** Resolved an issue where a PHP 5.3-specific function was being used.
+
+### CFPolicy
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+
+### CFSimpleXML
+* **New:** Added the init() method which simplifies the process of instantiating and chaining a class.
+
+### RequestCore
+* **Fixed:** Improvements to running in PHP environments with open_basedir enabled.
+* **Fixed:** RequestCore now uses an up-to-date `cacert.pem` file from Mozilla instead of the Certificate Authority that libcurl or libopenssl was compiled with, which should resolve certain issues with making SSL connections to AWS services.
+
+
+----
+
+# Changelog: 1.3.2 "Luna"
+<http://finalfantasy.wikia.com/wiki/Luna_Wolf>
+
+Launched Tuesday, April 5, 2011
+
+## New Features & Highlights (Summary)
+* Support for Dedicated Instances within a Virtual Private Cloud on single-tenant hardware has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AmazonCloudWatch get_metric_statistics returns gzipped body](https://forums.aws.amazon.com/thread.jspa?threadID=62625)
+
+
+## Service Classes
+### AmazonCloudWatch
+* **Fixed:** Worked around an issue where when CloudWatch sends back `Content-Encoding: gzip`, it really means `deflate`. When CloudWatch sends back `Content-Encoding: deflate`, it really means the data isn't encoded at all.
+
+### AmazonEC2
+* **New:** Support for Dedicated Instances within a Virtual Private Cloud on single-tenant hardware has been added to the SDK.
+
+
+----
+
+# Changelog: 1.3.1 "Kraken"
+<http://finalfantasy.wikia.com/wiki/Kraken>
+
+Launched Friday, March 25, 2011
+
+## New Features & Highlights (Summary)
+* Fixed issues with Signature v3 authentication (SES).
+* Added gzip decoding.
+* Added support for converting data to more alternate formats.
+* Bug fixes and enhancements:
+ * [Cannot send email](https://forums.aws.amazon.com/thread.jspa?threadID=62833)
+ * [AmazonCloudWatch get_metric_statistics returns gzipped body](https://forums.aws.amazon.com/thread.jspa?threadID=62625)
+
+
+## Utility Classes
+### CFArray
+* **New:** The `to_json()` and `to_yaml()` methoda have been added to the class.
+
+### CFGzipDecode
+* **New:** Handles a variety of primary and edge cases around gzip/deflate decoding in PHP.
+
+### CFRuntime
+* **New:** Gzip decoding has been added to the SDK.
+* **Fixed:** The previous release contained a regression in the Signature v3 support that affected AmazonSES. This has been resolved.
+* **Fixed:** Completed support for Signature v3 over HTTP connections.
+
+### CFSimpleXML
+* **New:** The `to_stdClass()` and `to_yaml()` methoda have been added to the class.
+
+
+----
+
+# Changelog: 1.3 "Jecht"
+<http://finalfantasy.wikia.com/wiki/Jecht>
+
+Launched Tuesday, March 15, 2011
+
+## New Features & Highlights (Summary)
+* Support for VPC Internet Access has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AmazonEC2::register_image issue](https://forums.aws.amazon.com/thread.jspa?threadID=52499)
+ * [Automatic Parseing of XML objects](https://forums.aws.amazon.com/thread.jspa?threadID=61882)
+
+## Service Classes
+### AmazonEC2
+* **New:** Support for VPC Internet Access has been added to the SDK.
+* **Fixed:** The `$image_location` parameter in the `register_image()` method is no longer required. This is a backwards-incompatible change.
+
+### AmazonS3
+* **Fixed:** Resolved an issue in `get_object()` where using the `lastmodified` and `etag` parameters required both to be set before taking effect. They can now be set independently from each other.
+
+
+## Utility classes
+### CFArray
+* **Changed:** The `reduce()` method has been renamed to `filter()`. `reduce()` is now simply an alias for `filter()`.
+
+### CFJSON
+* **New:** Simplifies the task of normalizing XML and JSON responses as `CFSimpleXML` objects.
+
+### CFRuntime
+* **New:** Preliminary support for Signature v3 over HTTP has been added to the SDK. This is useful for debugging Signature v3 issues over non-HTTPS connections.
+* **Changed:** Classes that use the shared authentication method (i.e., NOT `AmazonS3` or `AmazonCloudFront`) will automatically convert JSON service responses into a `CFSimpleXML` object.
+* **Changed:** Formerly, the SDK would attempt to sniff the content to determine the type. Now, the SDK will check the HTTP response headers for `text/xml`, `application/xml` or `application/json` to determine whether or not to parse the content. If the HTTP response headers are not available, the SDK will still attempt content sniffing.
+
+### CFSimpleXML
+* **New:** The `to_json()` method has been added to the class.
+
+### CFUtilities
+* **New:** The `is_json()` method has been added to the class.
+
+
+----
+
+# Changelog: 1.2.6 "Ifrit"
+<http://finalfantasy.wikia.com/wiki/Ifrit>
+
+Launched Wednesday, March 2, 2011
+
+## New Features & Highlights (Summary)
+* **New:** Support for the new Asia Pacific "Northeast" (Japan) endpoint has been added for all relevant services.
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK. Includes a runnable sample.
+* **Fixed:** Improvements to avoid triggering warnings when PHP is in Safe Mode.
+
+
+## Service Classes
+### AmazonAS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonCloudFormation
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonCloudWatch
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonEC2
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonELB
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonRDS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonS3
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+* **New:** Added support for `ap-northeast-1` as a location constraint when creating a new bucket.
+
+### AmazonSDB
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonSNS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+### AmazonSQS
+* **New:** Added a new _class_ constant: `REGION_APAC_NE1`.
+
+## Utility classes
+### CFRuntime
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK.
+* **New:** Future-proofed for future regional endpoints.
+
+### RequestCore
+* **New:** Support for registering callback functions for read/write streams has been added to the SDK.
+* **Fixed:** Improvements to avoid triggering warnings when PHP is in Safe Mode.
+
+## Samples
+* **New:** A sample demonstrating how to add a command-line progress bar for S3 transfers has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.5 "Heidegger"
+<http://finalfantasy.wikia.com/wiki/Heidegger>
+
+Launched Thursday, February 24, 2011
+
+## New Features & Highlights (Summary)
+* Support for AWS CloudFormation has been added to the SDK.
+* Bug fixes and enhancements:
+ * [PHP API change_content_type() broken](https://forums.aws.amazon.com/thread.jspa?threadID=59532)
+ * [Bug setting OriginAccessIdentity for a Cloudfront distribution config](https://forums.aws.amazon.com/thread.jspa?threadID=60989)
+
+## Service Classes
+### AmazonCloudFormation
+* **New:** Support for AWS CloudFormation has been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Issues around `update_xml_config()` have been resolved.
+
+### AmazonS3
+* **Fixed:** Issues around `change_content_type()` have been resolved.
+
+
+----
+
+# Changelog: 1.2.4 "Goltanna"
+<http://finalfantasy.wikia.com/wiki/Druksmald_Goltanna>
+
+Launched Wednesday, February 16, 2011
+
+## New Features & Highlights (Summary)
+* Support for IAM account aliases and server certificates has been added to the SDK.
+* Support for Amazon S3 Website Configuration has been added to the SDK.
+* Documentation updates for Amazon RDS and AWS Import/Export.
+* Updated all documentation blocks to adhere to the PHPDoc format. This enables a greater number of tools to take advantage of the SDK documentation.
+* Rolled out a major update to the SDK API Reference.
+
+## Service Classes
+### AmazonIAM
+* **New:** Support for IAM account aliases and server certificates has been added to the SDK.
+
+### AmazonImportExport
+* **New:** Documentation has been updated to note the new US West region support.
+
+### AmazonRDS
+* **New:** Documentation has been updated to note the new support for MySQL 5.5.
+
+### AmazonS3
+* **New:** Support for Amazon S3 Website Configuration has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.3 "Fayth"
+<http://finalfantasy.wikia.com/wiki/Fayth>
+
+Launched Tuesday, January 25, 2010
+
+## New Features & Highlights (Summary)
+* Support for Amazon Simple Email Service has been added to the SDK.
+
+## Service Classes
+### AmazonSES
+* **New:** Support for Amazon Simple Email Service has been added to the SDK.
+
+
+----
+
+# Changelog: 1.2.2 "Esper"
+<http://finalfantasy.wikia.com/wiki/Esper>
+
+Launched Tuesday, January 18, 2011
+
+## New Features & Highlights (Summary)
+* Support for Amazon Elastic Beanstalk has been added to the SDK.
+* Bug fixes and enhancements:
+ * [AWS PHP S3 Library is not working out of the box](https://forums.aws.amazon.com/thread.jspa?threadID=55174)
+ * [Problem with create_mpu_object() and streaming_read_callback() in S3](https://forums.aws.amazon.com/thread.jspa?threadID=54541)
+ * [Integrated Uranium235's GitHub contributions](https://github.com/Uranium235/aws-sdk-for-php/compare/Streaming)
+
+## Service Classes
+### AmazonElasticBeanstalk
+* **New:** Support for AWS Elastic Beanstalk has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Major improvements to transferring data over streams.
+
+## Utility classes
+###RequestCore
+* **New:** Upgraded to version 1.4.
+* **Fixed:** Major improvements to transferring data over streams.
+
+
+----
+
+# Changelog: 1.2.1 "Dio"
+<http://finalfantasy.wikia.com/wiki/Dio>
+
+Launched Friday, January 14, 2011
+
+
+## New Features & Highlights (Summary)
+* Support for S3 Response Headers has been added to the SDK.
+* Bug fixes and enhancements:
+ * [copy_object failed between regions](https://forums.aws.amazon.com/thread.jspa?threadID=56893)
+ * [Possible S3 bug with multiple buckets?](https://forums.aws.amazon.com/thread.jspa?threadID=56561)
+
+## Service Classes
+### AmazonS3
+* **New:** Support for S3 Response Headers has been added to the SDK.
+* **New:** Documentation for Amazon S3 has been updated to include large object support details.
+* **New:** The `abort_multipart_uploads_by_date()` method has been added to the SDK, which aborts multipart uploads that were initiated before a specific date.
+* **Fixed:** Resolved an issue where the resource prefix wasn't being reset correctly.
+
+## Utility classes
+### CFArray
+* **New:** Instantiating the class without passing an array will use an empty array instead.
+* **New:** Added the `compress()` method which removes null values from the array.
+* **New:** Added the `reindex()` method which reindexes all array elements starting at zero.
+
+## Compatibility Test
+* **New:** The command-line compatibility test now color-codes the responses.
+
+
+----
+
+# Changelog: 1.2 "Cloud"
+<http://finalfantasy.wikia.com/wiki/Cloud_Strife>
+
+Launched Friday, December 3, 2010
+
+
+## New Features & Highlights (Summary)
+* Support for Amazon AutoScaling, Amazon Elastic MapReduce, and Amazon Import/Export Service has been added to the SDK.
+* Support for metric alarms has been added to Amazon CloudWatch.
+* Support for batch deletion has been added to Amazon SimpleDB.
+* Bug fixes and enhancements:
+ * [EU Region DNS problem](https://forums.aws.amazon.com/thread.jspa?threadID=53028)
+ * [[SimpleDB] Conditional PUT](https://forums.aws.amazon.com/thread.jspa?threadID=55884)
+ * [Suggestions for the PHP SDK](https://forums.aws.amazon.com/thread.jspa?threadID=55210)
+ * [Updating a distribution config](https://forums.aws.amazon.com/thread.jspa?threadID=54888)
+ * [Problem with curlopt parameter in S3](https://forums.aws.amazon.com/thread.jspa?threadID=54532)
+ * [AmazonS3::get_object_list() doesn't consider max-keys option](https://forums.aws.amazon.com/thread.jspa?threadID=55169)
+
+## Base/Runtime class
+* **New:** Added support for an alternate approach to instantiating classes which allows for method chaining (PHP 5.3+).
+* **Changed:** Moved `CHANGELOG.md`, `CONTRIBUTORS.md`, `LICENSE.md` and `NOTICE.md` into a new `_docs` folder.
+* **Changed:** Renamed the `samples` directory to `_samples`.
+* **Changed:** Changed the permissions for the SDK files from `0755` to `0644`.
+* **Fixed:** Resolved an issue where attempting to merge cURL options would fail.
+
+## Service Classes
+### AmazonAS
+* **New:** Support for the Amazon AutoScaling Service has been added to the SDK.
+
+### AmazonCloudFront
+* **Fixed:** Resolved an issue where the incorrect formatting of an XML element prevented the ability to update the list of trusted signers.
+
+### AmazonCloudWatch
+* **New:** Support for the Amazon CloudWatch `2010-08-01` service release expands Amazon's cloud monitoring offerings with custom alarms.
+* **Changed:** The changes made to the `get_metric_statistics()` method are backwards-incompatible with the previous release. The `Namespace` and `Period` parameters are now required and the parameter order has changed.
+
+### AmazonEMR
+* **New:** Support for the Amazon Elastic MapReduce Service has been added to the SDK.
+
+### AmazonImportExport
+* **New:** Support for the Amazon Import/Export Service has been added to the SDK.
+
+### AmazonS3
+* **Fixed:** Resolved an issue in the `create_bucket()` method that caused the regional endpoint to be reset to US-Standard.
+* **Fixed:** Resolved an issue in the `get_object_list()` method where the `max-keys` parameter was ignored.
+
+### AmazonSDB
+* **New:** Support for `BatchDeleteAttributes` has been added to the SDK.
+* **Fixed:** Resolved an issue where the `Expected` condition was not respected by `put_attributes()` or `delete_attributes()`.
+
+
+## Utility classes
+### CFComplexType
+* **New:** You can now assign a `member` parameter to prefix all list identifiers.
+* **Changed:** The `option_group()` method is now `public` instead of `private`.
+* **Changed:** Rewrote the `to_query_string()` method to avoid the use of PHP's `http_build_query()` function because it uses `urlencode()` internally instead of `rawurlencode()`.
+
+### CFHadoopStep
+* **New:** Simplifies the process of working with Hadoop steps in Amazon EMR.
+
+### CFManifest
+* **New:** Simplifies the process of constructing YAML manifest documents for Amazon Import/Export Service.
+
+### CFStepConfig
+* **New:** Simplifies the process of working with step configuration in Amazon EMR.
+
+
+## Third-party Libraries
+### CacheCore
+* **Changed:** The `generate_timestamp()` method is now `protected` instead of `private`.
+
+
+----
+
+# Changelog: 1.1 "Barret"
+<http://finalfantasy.wikia.com/wiki/Barret_Wallace>
+
+Launched Wednesday, November 10, 2010
+
+
+## New Features & Highlights (Summary)
+* Support for Amazon ELB, Amazon RDS and Amazon VPC has been added to the SDK.
+* Support for the Amazon S3 multipart upload feature has been added to the SDK. This feature enables developers upload large objects in a series of requests for improved upload reliability.
+* Support for the Amazon CloudFront custom origin (2010-11-01 release) feature has been added to the SDK. This feature enables developers to use custom domains as sources for Amazon CloudFront distributions.
+* The `AmazonS3` class now supports reading from and writing to open file resources in addition to the already-supported file system paths.
+* You can now seek to a specific byte-position within a file or file resource and begin streaming from that point when uploading or downloading objects.
+* The methods `get_bucket_filesize()`, `get_object_list()`, `delete_all_objects()` and `delete_all_object_versions()` are no longer limited to 1000 entries and will work correctly for all entries.
+* Requests that have errors at the cURL level now throw exceptions containing the error message and error code returned by cURL.
+* Bug fixes and enhancements:
+ * [Bug in Samples](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52748)
+ * [EU Region DNS problem](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53028)
+ * [AmazonS3 get_bucket_object_count](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52976)
+ * [S3: get_object_list() fatal error](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53418)
+ * [S3 get_object_metadata() problems](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=54244)
+ * [Bug in authenticate in sdk.class.php](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53117)
+ * [How to use Prefix with "get_object_list"?](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52987)
+ * [SignatureDoesNotMatch with utf-8 in SimpleDB](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52798)
+ * [Suggestion for the PHP SDK concerning streaming](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52787)
+ * [get_bucket_filesize only returns filesize for first 1000 objects](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=53786)
+
+
+## Base/Runtime class
+* **Changed:** Port numbers other than 80 and 443 are now part of the signature.
+* **Changed:** When putting UTF-8 characters via HTTP `POST`, a `SignatureDoesNotMatch` error would be returned. This was resolved by specifying the character set in the `Content-Type` header.
+
+
+## Service Classes
+### AmazonCloudFront
+* **New:** Support for the Amazon CloudFront non-S3 origin feature (2010-11-01 release) has been added to the SDK. This feature enables developers to use non-S3 domains as sources for Amazon CloudFront distributions.
+
+### AmazonEC2
+* **New:** Support for Amazon Virtual Private Cloud has been added to the SDK.
+
+### AmazonELB
+* **New:** Support for Amazon Elastic Load Balancing Service has been added to the SDK.
+
+### AmazonIAM
+* **Fixed:** Removed `set_region()` as IAM only supports a single endpoint.
+
+### AmazonRDS
+* **New:** Support for Amazon Relational Database Service has been added to the SDK.
+
+### AmazonS3
+* **New:** Support for the Amazon S3 multipart upload feature has been added to the SDK. This feature enables developers upload large objects in a series of requests for improved upload reliability.
+* **New:** The `fileUpload` and `fileDownload` options now support reading from and writing to open file resources in addition to the already-supported file system paths.
+* **Fixed:** In Amazon S3, requests directly to the eu-west endpoint must use the path-style URI. The set_region() method now takes this into account.
+* **Fixed:** As of version 1.0.1, CFSimpleXML extends SimpleXMLIterator instead of SimpleXMLElement. This prevented the `__call()` magic method from firing when `get_object_list()` was used.
+* **Fixed:** The `preauth` option for the `get_object_list()` method has been removed from the documentation as it is not supported.
+* **Fixed:** The methods `get_bucket_filesize()`, `get_object_list()`, `delete_all_objects()` and `delete_all_object_versions()` are no longer limited to 1000 entries and will work correctly for all entries.
+* **Fixed:** Using `delete_bucket()` to force-delete a bucket now works correctly for buckets with more than 1000 versions.
+* **Fixed:** The response from the `get_object_metadata()` method now includes all supported HTTP headers, including metadata stored in `x-amz-meta-` headers.
+* **Fixed:** Previously, if the `get_object_metadata()` method was called on a non-existant object, metadata for the alphabetically-next object would be returned.
+
+### AmazonSQS
+* **New:** The `get_queue_arn()` method has been added to the `AmazonSQS` class, which converts a queue URI to a queue ARN.
+
+
+## Utility classes
+### CFSimpleXML
+* **New:** Added `to_string()` and `to_array()` methods.
+
+
+## Third-party Libraries
+### RequestCore
+* **New:** Upgraded to version 1.3.
+* **New:** Added `set_seek_position()` for seeking to a byte-position in a file or file resource before starting an upload.
+* **New:** Added support for reading from and writing to open file resources.
+* **Fixed:** Improved the reporting for cURL errors.
+
+
+## Compatibility Test
+* **Fixed:** Fixed the links to the Getting Started Guide.
+
+
+----
+
+# Changelog: 1.0.1 "Aeris"
+<http://finalfantasy.wikia.com/wiki/Aerith_Gainsborough>
+
+Launched Tuesday, October 12, 2010
+
+
+## New Features & Highlights (Summary)
+* Improved support for running XPath queries against the service response bodies.
+* Added support for request retries and exponential backoff.
+* Added support for HTTP request/response header logging.
+* Bug fixes and enhancements:
+ * [Bug in Samples](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52748)
+ * [Can't set ACL on object using the SDK](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52305)
+ * [Range requests for S3 - status codes 200, 206](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52738)
+ * [S3 change_storage_redundancy() function clears public-read ACL](http://developer.amazonwebservices.com/connect/thread.jspa?threadID=52652)
+
+
+## Base/Runtime class
+* **New:** Added support for request retries and exponential backoff for all `500` and `503` HTTP status codes.
+* **New:** Added the `enable_debug_mode()` method to enable HTTP request/response header logging to `STDERR`.
+
+
+## Service Classes
+### AmazonS3
+* **Fixed:** Lots of tweaks to the documentation.
+* **Fixed:** The `change_content_type()`, `change_storage_redundancy()`, `set_object_acl()`, and `update_object()` methods now respect the existing content-type, storage redundancy, and ACL settings when updating.
+* **New:** Added the `get_object_metadata()` method has been added as a singular interface for obtaining all available metadata for an object.
+
+
+## Utility Classes
+### CFArray
+* **New:** Added the `each()` method which accepts a callback function to execute for each entry in the array. Works similarly to [jQuery's each()](http://api.jquery.com/each).
+* **New:** Added the `map()` method which accepts a callback function to execute for each entry in the array. Works similarly to [jQuery's map()](http://api.jquery.com/map).
+* **New:** Added the `reduce()` method which accepts a callback function to execute for each entry in the array. Works similarly to [DomCrawler reduce()](http://github.com/symfony/symfony/blob/master/src/Symfony/Component/DomCrawler/Crawler.php) from the [Symfony 2](http://symfony-reloaded.org) Preview Release.
+* **New:** Added the `first()` and `last()` methods to return the first and last nodes in the array, respectively.
+
+### CFInfo
+* **New:** Retrieves information about the current installation of the AWS SDK for PHP.
+
+### CFSimpleXML
+* **New:** Added the `query()` method, which allows for XPath queries while the results are wrapped in a `CFArray` response.
+* **New:** Added the `parent()` method, which allows for traversing back up the document tree.
+* **New:** Added the `stringify()` method, which typecasts the value as a string.
+* **New:** Added the `is()` and `contains()` methods, which allow for testing whether the XML value is or contains a given value, respectively.
+* **Changed:** Now extends the `SimpleXMLIterator` class, which in-turn extends the `SimpleXMLElement` class. This adds new iterator methods to the `CFSimpleXML` class.
+
+
+## Third-party Libraries
+### CacheCore
+* **New:** Upgraded to version 1.2.
+* **New:** Added a static `init` method that allows for chainable cache initialization (5.3+).
+
+### RequestCore
+* **New:** Added `206` as a successful status code (i.e., Range GET).
+
+
+## Compatibility Test
+* **Fixed:** Some of the links in the compatibility test were missing. These have been fixed.
+
+
+----
+
+# Changelog: AWS SDK for PHP 1.0
+
+Launched Tuesday, September 28, 2010
+
+This is a complete list of changes since we forked from the CloudFusion 2.5.x trunk build.
+
+
+## New Features & Highlights (Summary)
+* The new file to include is `sdk.class.php` rather than `cloudfusion.class.php`.
+* Because of the increased reliance on [JSON](http://json.org) across AWS services, the minimum supported version is now PHP 5.2 ([Released in November 2006](http://www.php.net/ChangeLog-5.php#5.2.0); Justified by these [WordPress usage statistics](http://wpdevel.wordpress.com/2010/07/09/suggest-topics-for-the-july-15-2010-dev/comment-page-1/#comment-8542) and the fact that [PHP 5.2 has been end-of-life'd](http://www.php.net/archive/2010.php#id2010-07-22-1) in favor of 5.3).
+* Up-to-date service support for [EC2](http://aws.amazon.com/ec2), [S3](http://aws.amazon.com/s3), [SQS](http://aws.amazon.com/sqs), [SimpleDB](http://aws.amazon.com/simpledb), [CloudWatch](http://aws.amazon.com/cloudwatch), and [CloudFront](http://aws.amazon.com/cloudfront).
+* Added service support for [SNS](http://aws.amazon.com/sns).
+* Limited testing for third-party API-compatible services such as [Eucalyptus](http://open.eucalyptus.com), [Walrus](http://open.eucalyptus.com) and [Google Storage](http://sandbox.google.com/storage).
+* Improved the consistency of setting complex data types across services. (Required some backwards-incompatible changes.)
+* Added new APIs and syntactic sugar for SimpleXML responses, batch requests and response caching.
+* Moved away from _global_ constants in favor of _class_ constants.
+* Minor, but notable improvements to the monkey patching support.
+* Added a complete list of bug fix and patch contributors. Give credit where credit is due. ;)
+
+**Note: ALL backwards-incompatible changes are noted below. Please review the changes if you are upgrading.** We're making a small number of backwards-incompatible changes in order to improve the consistency across services. We're making these changes _now_ so that we can ensure that future versions will always be backwards-compatible with the next major version change.
+
+
+## File structure
+The package file structure has been refined in a few ways:
+
+* All service-specific classes are inside the `/services/` directory.
+* All utility-specific classes are inside the `/utilities/` directory.
+* All third-party classes are inside the `/lib/` directory.
+
+
+## Base/Runtime class
+* **Fixed:** Resolved issues: [#206](http://code.google.com/p/tarzan-aws/issues/detail?id=206).
+* **New:** The following global constants have been added: `CFRUNTIME_NAME`, `CFRUNTIME_VERSION`, `CFRUNTIME_BUILD`, `CFRUNTIME_URL`, and `CFRUNTIME_USERAGENT`
+* **New:** Now supports camelCase versions of the snake_case method names. (e.g. `getObjectList()` will get translated to `get_object_list()` behind the scenes.)
+* **New:** Added `set_resource_prefix()` and `allow_hostname_override()` (in addition to `set_hostname()`) to support third-party, API-compatible services.
+* **New:** Added new caching APIs: `cache()` and `delete_cache()`, which work differently from the methods they replace. See docs for more information.
+* **New:** Added new batch request APIs, `batch()` and `CFBatchRequest` which are intended to replace the old `returnCurlHandle` optional parameter.
+* **New:** Will look for the `config.inc.php` file first in the same directory (`./config.inc.php`), and then fallback to `~/.aws/sdk/config.inc.php`.
+* **Changed:** Renamed the `CloudFusion` base class to `CFRuntime`.
+* **Changed:** `CloudFusion_Exception` has been renamed as `CFRuntime_Exception`.
+* **Changed:** Renamed the `CloudFusion::$enable_ssl` property to `CFRuntime::$use_ssl`.
+* **Changed:** Renamed the `CloudFusion::$set_proxy` property to `CFRuntime::$proxy`.
+* **Changed:** `CFRuntime::disable_ssl()` no longer takes any parameters. Once SSL is off, it is always off for that class instance.
+* **Changed:** All date-related constants are now class constants of the `CFUtilities` class (e.g. `CFUtilities::DATE_FORMAT_ISO8601`).
+ * Use `CFUtilities::konst()` if you're extending classes and need to do something such as `$this->util::DATE_FORMAT_ISO8601` but keep getting the `T_PAAMAYIM_NEKUDOTAYIMM` error.
+* **Changed:** All `x-cloudfusion-` and `x-tarzan-` HTTP headers are now `x-aws-`.
+* **Changed:** `CloudFusion::autoloader()` is now in its own separate class: `CFLoader::autoloader()`. This prevents it from being incorrectly inherited by extending classes.
+* **Changed:** `RequestCore`, `ResponseCore` and `SimpleXMLElement` are now extended by `CFRequest`, `CFResponse` and `CFSimpleXML`, respectively. These new classes are now used by default.
+* **Changed:** Changes to monkey patching:
+ * You must now extend `CFRequest` instead of `RequestCore`, and then pass that class name to `set_request_class()`.
+ * You must now extend `CFResponse` instead of `ResponseCore`, and then pass that class name to `set_response_class()`.
+ * You can now monkey patch `CFSimpleXML` (extended from `SimpleXMLElement`) with `set_parser_class()`.
+ * You can now monkey patch `CFBatchRequest` with `set_batch_class()`.
+ * No changes for monkey patching `CFUtilities` with `set_utilities_class()`.
+* **Removed:** Removed ALL existing _global_ constants and replaced them with _class_ constants.
+* **Removed:** Removed `cache_response()` and `delete_cache_response()`.
+
+
+## Service classes
+
+### AmazonCloudFront
+* **Fixed:** Resolved issues: [#124](http://code.google.com/p/tarzan-aws/issues/detail?id=124), [#225](http://code.google.com/p/tarzan-aws/issues/detail?id=225), [#229](http://code.google.com/p/tarzan-aws/issues/detail?id=229), [#232](http://code.google.com/p/tarzan-aws/issues/detail?id=232), [#239](http://code.google.com/p/tarzan-aws/issues/detail?id=239).
+* **Fixed:** Fixed an issue where `AmazonCloudFront` sent a `RequestCore` user agent in requests.
+* **New:** Class is now up-to-date with the [2010-07-15](http://docs.amazonwebservices.com/AmazonCloudFront/2010-07-15/APIReference/) API release.
+* **New:** Added _class_ constants for deployment states: `STATE_INPROGRESS` and `STATE_DEPLOYED`.
+* **New:** Now supports streaming distributions.
+* **New:** Now supports HTTPS (as well as HTTPS-only) access.
+* **New:** Now supports Origin Access Identities. Added `create_oai()`, `list_oais()`, `get_oai()`, `delete_oai()`, `generate_oai_xml()` and `update_oai_xml()`.
+* **New:** Now supports private (signed) URLs. Added `get_private_object_url()`.
+* **New:** Now supports default root objects.
+* **New:** Now supports invalidation.
+* **New:** Added `get_distribution_list()`, `get_streaming_distribution_list()` and `get_oai_list()` which return simplified arrays of identifiers.
+* **Changed:** Replaced all of the remaining `CDN_*` constants with _class_ constants.
+
+### AmazonCloudWatch
+* **New:** Added new _class_ constants: `DEFAULT_URL`, `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, and `REGION_APAC_SE1`.
+* **New:** Now supports the _Northern California_, _European_ and _Asia-Pacific_ regions.
+* **New:** The _global_ `CW_DEFAULT_URL` constant has been replaced by `AmazonCloudFront::DEFAULT_URL`.
+
+### AmazonEC2
+* **Fixed:** Resolved issues: [#124](http://code.google.com/p/tarzan-aws/issues/detail?id=124), [#131](http://code.google.com/p/tarzan-aws/issues/detail?id=131), [#138](http://code.google.com/p/tarzan-aws/issues/detail?id=138), [#139](http://code.google.com/p/tarzan-aws/issues/detail?id=139), [#154](http://code.google.com/p/tarzan-aws/issues/detail?id=154), [#173](http://code.google.com/p/tarzan-aws/issues/detail?id=173), [#200](http://code.google.com/p/tarzan-aws/issues/detail?id=200), [#233](http://code.google.com/p/tarzan-aws/issues/detail?id=233).
+* **New:** Class is now up-to-date with the [2010-06-15](http://docs.amazonwebservices.com/AWSEC2/2010-06-15/APIReference/) API release.
+* **New:** Now supports [Paid AMIs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=865&categoryID=87).
+* **New:** Now supports [Multiple instance types](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=992&categoryID=87).
+* **New:** Now supports [Elastic IPs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1344&categoryID=87).
+* **New:** Now supports [Availability Zones](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1344&categoryID=87).
+* **New:** Now supports [Elastic Block Store](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1665&categoryID=87).
+* **New:** Now supports [Windows instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1765&categoryID=87).
+* **New:** Now supports the [European region](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1926&categoryID=87).
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports [Reserved instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2213&categoryID=87).
+* **New:** Now supports [Shared snapshots](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2843&categoryID=87).
+* **New:** Now supports [EBS AMIs](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3105&categoryID=87).
+* **New:** Now supports [Spot instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3215&categoryID=87).
+* **New:** Now supports [Cluster Compute Instances](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3965&categoryID=87).
+* **New:** Now supports [Placement Groups](http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3965&categoryID=87).
+* **New:** Added new _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, `REGION_APAC_SE1`.
+* **New:** Added new _class_ constants for run-state codes: `STATE_PENDING`, `STATE_RUNNING`, `STATE_SHUTTING_DOWN`, `STATE_TERMINATED`, `STATE_STOPPING`, `STATE_STOPPED`.
+* **New:** Added support for decrypting the Administrator password for Microsoft Windows instances.
+* **New:** Instead of needing to pass `Parameter.0`, `Parameter.1`, ...`Parameter.n` individually to certain methods, you can now reliably pass a string for a single value or an indexed array for a list of values.
+* **New:** Limited tested has been done with the Eucalyptus EC2-clone.
+* **Changed:** The `$account_id` parameter has been removed from the constructor.
+* **Changed:** The _global_ `EC2_LOCATION_US` and `EC2_LOCATION_EU` constants have been replaced.
+* **Changed:** The `set_locale()` method has been renamed to `set_region()`. It accepts any of the region constants.
+
+### AmazonIAM
+* **New:** Up-to-date with the [2010-03-31](http://docs.amazonwebservices.com/sns/2010-03-31/api/) API release.
+
+### AmazonS3
+* **Fixed:** Resolved issues: [#31](http://code.google.com/p/tarzan-aws/issues/detail?id=31), [#72](http://code.google.com/p/tarzan-aws/issues/detail?id=72), [#123](http://code.google.com/p/tarzan-aws/issues/detail?id=123), [#156](http://code.google.com/p/tarzan-aws/issues/detail?id=156), [#199](http://code.google.com/p/tarzan-aws/issues/detail?id=199), [#201](http://code.google.com/p/tarzan-aws/issues/detail?id=201), [#203](http://code.google.com/p/tarzan-aws/issues/detail?id=203), [#207](http://code.google.com/p/tarzan-aws/issues/detail?id=207), [#208](http://code.google.com/p/tarzan-aws/issues/detail?id=208), [#209](http://code.google.com/p/tarzan-aws/issues/detail?id=209), [#210](http://code.google.com/p/tarzan-aws/issues/detail?id=210), [#212](http://code.google.com/p/tarzan-aws/issues/detail?id=212), [#216](http://code.google.com/p/tarzan-aws/issues/detail?id=216), [#217](http://code.google.com/p/tarzan-aws/issues/detail?id=217), [#226](http://code.google.com/p/tarzan-aws/issues/detail?id=226), [#228](http://code.google.com/p/tarzan-aws/issues/detail?id=228), [#234](http://code.google.com/p/tarzan-aws/issues/detail?id=234), [#235](http://code.google.com/p/tarzan-aws/issues/detail?id=235).
+* **Fixed:** Fixed an issue where `AmazonS3` sent a `RequestCore` user agent in requests.
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports the new _EU (Ireland)_ REST endpoint.
+* **New:** Now supports MFA Delete.
+* **New:** Now supports Conditional Copy.
+* **New:** Now supports Reduced Redundancy Storage (RRS). Added `change_storage_redundancy()`.
+* **New:** Now supports Object Versioning. Added `enable_versioning()`, `disable_versioning`, `get_versioning_status()`, and `list_bucket_object_versions()`.
+* **New:** Now supports Bucket Policies. Added `set_bucket_policy()`, `get_bucket_policy()`, and `delete_bucket_policy()`.
+* **New:** Now supports Bucket Notifications. Added `create_bucket_notification()`, `get_bucket_notifications()`, and `delete_bucket_notification()`.
+* **New:** Added _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, `REGION_APAC_SE1`.
+* **New:** Added _class_ constants for storage types: `STORAGE_STANDARD` and `STORAGE_REDUCED`.
+* **New:** Enhanced `create_object()` with the ability to upload a file from the file system.
+* **New:** Enhanced `get_object()` with the ability to download a file to the file system.
+* **New:** Enhanced `get_bucket_list()` and `get_object_list()` with performance improvements.
+* **New:** Enhanced all GET operations with the ability to generate pre-authenticated URLs. This is the same feature as `get_object_url()` has had, applied to all GET operations.
+* **New:** Limited testing with Walrus, the Eucalyptus S3-clone.
+* **New:** Limited testing with Google Storage.
+* **Changed:** Replaced all of the remaining `S3_*` constants with _class_ constants: `self::ACL_*`, `self::GRANT_*`, `self::USERS_*`, and `self::PCRE_ALL`.
+* **Changed:** Changed the function signature for `create_object()`. The filename is now passed as the second parameter, while the remaining options are now passed as the third parameter. This behavior now matches all of the other object-related methods.
+* **Changed:** Changed the function signature for `head_object()`, `delete_object()`, and `get_object_acl()`. The methods now accept optional parameters as the third parameter instead of simply `returnCurlHandle`.
+* **Changed:** Changed the function signature for `get_object_url()` and `get_torrent_url()`. Instead of passing a number of seconds until the URL expires, you now pass a string that `strtotime()` understands (including `60 seconds`).
+* **Changed:** Changed the function signature for `get_object_url()`. Instead of passing a boolean value for `$torrent`, the last parameter is now an `$opt` variable which allows you to set `torrent` and `method` parameters.
+* **Changed:** Changed how `returnCurlHandle` is used. Instead of passing `true` as the last parameter to most methods, you now need to explicitly set `array('returnCurlHandle' => true)`. This behavior is consistent with the implementation in other classes.
+* **Changed:** Optional parameter names changed in `list_objects()`: `maxKeys` is now `max-keys`.
+* **Changed:** `get_bucket_locale()` is now called `get_bucket_region()`, and returns the response body as a _string_ for easier comparison with class constants.
+* **Changed:** `get_bucket_size()` is now called `get_bucket_object_count()`. Everything else about it is identical.
+* **Changed:** `head_bucket()` is now called `get_bucket_headers()`. Everything else about it is identical.
+* **Changed:** `head_object()` is now called `get_object_headers()`. Everything else about it is identical.
+* **Changed:** `create_bucket()` has two backward-incompatible changes:
+ * Method now **requires** the region (formerly _locale_) to be set.
+ * Method takes an `$acl` parameter so that the ACL can be set directly when creating a new bucket.
+* **Changed:** Bucket names are now validated. Creating a new bucket now requires the more stringent DNS-valid guidelines, while the process of reading existing buckets follows the looser path-style guidelines. This change also means that the reading of path-style bucket names is now supported, when previously they weren’t.
+* **Removed:** Removed `store_remote_file()` because its intended usage repeatedly confused users, and had potential for misuse. If you were using it to upload from the local file system, you should be using `create_object` instead.
+* **Removed:** Removed `copy_bucket()`, `replace_bucket()`, `duplicate_object()`, `move_object()`, and `rename_object()` because only a small number of users used them, and they weren't very robust anyway.
+* **Removed:** Removed `get_bucket()` because it was just an alias for `list_objects()` anyway. Use the latter from now on -- it's identical.
+
+### AmazonSDB
+* **Fixed:** Resolved issues: [#205](http://code.google.com/p/tarzan-aws/issues/detail?id=205).
+* **New:** Class is now up-to-date with the [2009-04-15](http://docs.amazonwebservices.com/AmazonSimpleDB/2009-04-15/DeveloperGuide/) API release.
+* **Changed:** Changed the function signatures for `get_attributes()` and `delete_attributes()` to improve consistency.
+
+### AmazonSNS
+* **New:** Up-to-date with the [2010-03-31](http://docs.amazonwebservices.com/sns/2010-03-31/api/) API release.
+
+### AmazonSQS
+* **Fixed:** Resolved issues: [#137](http://code.google.com/p/tarzan-aws/issues/detail?id=137), [#213](http://code.google.com/p/tarzan-aws/issues/detail?id=213), [#219](http://code.google.com/p/tarzan-aws/issues/detail?id=219), [#220](http://code.google.com/p/tarzan-aws/issues/detail?id=220), [#221](http://code.google.com/p/tarzan-aws/issues/detail?id=221), [#222](http://code.google.com/p/tarzan-aws/issues/detail?id=222).
+* **Fixed:** In CloudFusion 2.5, neither `add_permission()` nor `remove_permission()` were functional. They are now working.
+* **New:** Now supports the _Northern California_ and _Asia-Pacific_ regions.
+* **New:** Now supports the new _US-East (N. Virginia)_ endpoint.
+* **New:** Now supports the new _EU (Ireland)_ endpoint.
+* **New:** Added new _class_ constants for regions: `REGION_US_E1`, `REGION_US_W1`, `REGION_EU_W1`, and `REGION_APAC_SE1`.
+* **Changed:** Because we now support multiple region endpoints, queue names alone are no longer sufficient for referencing your queues. As such, you must now use a full-queue URL instead of just the queue name.
+* **Changed:** The _global_ `SQS_LOCATION_US` and `SQS_LOCATION_EU` constants have been replaced.
+* **Changed:** Renamed `set_locale()` as `set_region()`. It accepts any of the region constants.
+* **Changed:** Changed the function signature for `list_queues()`. See the updated API reference.
+* **Changed:** Changed the function signature for `set_queue_attributes()`. See the updated API reference.
+* **Changed:** Changed how `returnCurlHandle` is used. Instead of passing `true` as the last parameter to most methods, you now need to explicitly set `array('returnCurlHandle' => true)`. This behavior is consistent with the implementation in other classes.
+* **Changed:** Function signature changed in `get_queue_attributes()`. The `$attribute_name` parameter is now passed as a value in the `$opt` parameter.
+
+### AmazonSQSQueue
+* **Removed:** `AmazonSQSQueue` was a simple wrapper around the AmazonSDB class. It generally failed as an object-centric approach to working with SQS, and as such, has been eliminated. Use the `AmazonSQS` class instead.
+
+
+## Utility Classes
+### CFArray
+* **New:** Extends `ArrayObject`.
+* **New:** Simplified typecasting of SimpleXML nodes to native types (e.g. integers, strings).
+
+### CFBatchRequest
+* **New:** Provides a higher-level API for executing batch requests.
+
+### CFComplexType
+* **New:** Used internally by several classes to handle various complex data-types (e.g. single or multiple values, `Key.x.Subkey.y.Value` combinations).
+* **New:** Introduces a way to convert between JSON, YAML, and the PHP equivalent of Lists and Maps (nested associative arrays).
+
+### CFRequest
+* **New:** Sets some project-specific settings and passes them to the lower-level RequestCore.
+
+### CFResponse
+* **New:** No additional changes from the base `ResponseCore` class.
+
+### CFPolicy
+* **New:** Used for constructing Base64-encoded, JSON policy documents to be passed around to other methods.
+
+### CFSimpleXML
+* **New:** Extends `SimpleXMLElement`.
+* **New:** Simplified node retrieval. All SimpleXML-based objects (e.g. `$response->body`) now have magic methods that allow you to quickly retrieve nodes with the same name
+ * e.g. `$response->body->Name()` will return an array of all SimpleXML nodes that match the `//Name` XPath expression.
+
+### CFUtilities
+* **Fixed:** `to_query_string()` now explicitly passes a `&` character to `http_build_query()` to avoid configuration issues with MAMP/WAMP/XAMP installations.
+* **Fixed:** `convert_response_to_array()` has been fixed to correctly return an all-array response under both PHP 5.2 and 5.3. Previously, PHP 5.3 returned a mix of `array`s and `stdClass` objects.
+* **New:** Added `konst()` to retrieve the value of a class constant, while avoiding the `T_PAAMAYIM_NEKUDOTAYIM` error. Misspelled because `const` is a reserved word.
+* **New:** Added `is_base64()` to determine whether or not a string is Base64-encoded data.
+* **New:** Added `decode_uhex()` to decode `\uXXXX` entities back into their unicode equivalents.
+* **Changed:** Changed `size_readable()`. Now supports units up to exabytes.
+* **Changed:** Moved the `DATE_FORMAT_*` _global_ constants into this class as _class_ constants.
+* **Removed:** Removed `json_encode_php51()` now that the minimum required version is PHP 5.2 (which includes the JSON extension by default).
+* **Removed:** Removed `hex_to_base64()`.
+
+
+## Third-party Libraries
+### CacheCore
+* **New:** Upgraded to version 1.1.1.
+* **New:** Now supports both the [memcache](http://php.net/memcache) extension, but also the newer, faster [memcached](http://php.net/memcached) extension. Prefers `memcached` if both are installed.
+* **Deprecated:** Support for MySQL and PostgreSQL as storage mechanisms has been **deprecated**. Since they're using PDO, they'll continue to function (as we're maintaining SQLite support via PDO), but we recommend migrating to using APC, XCache, Memcache or SQLite if you'd like to continue using response caching.
+* New BSD licensed
+* <http://github.com/skyzyx/cachecore>
+
+### RequestCore
+* **New:** Upgraded to version 1.2.
+* **New:** Now supports streaming up and down.
+* **New:** Now supports "rolling" requests for better scalability.
+* New BSD licensed
+* <http://github.com/skyzyx/requestcore>
diff --git a/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md b/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md
new file mode 100644
index 00000000000..3523bf6723c
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/CONTRIBUTORS.md
@@ -0,0 +1,64 @@
+# Contributors
+
+## AWS SDK for PHP Contributors
+
+Contributions were provided under the Apache 2.0 License, as appropriate.
+
+The following people have provided ideas, support and bug fixes:
+
+* [arech8](http://developer.amazonwebservices.com/connect/profile.jspa?userID=154435) (bug fixes)
+* [Aizat Faiz](http://aizatto.com) (bug fixes)
+* [Ben Lumley](http://github.com/benlumley) (bug fixes)
+* [David Chan](http://www.chandeeland.org) (bug fixes)
+* [Eric Caron](http://www.ericcaron.com) (bug fixes)
+* [Jason Ardell](http://ardell.posterous.com/) (bug fixes)
+* [Jeremy Archuleta](http://code.google.com/u/jeremy.archuleta/) (bug fixes)
+* [Jimmy Berry](http://blog.boombatower.com/) (bug fixes, patches)
+* [Paul Voegler](mailto:voegler@gmx.de) (bug fixes, bug reports, patches)
+* [Peter Bowen](http://github.com/pzb) (feedback, bug reports)
+* [zoxa](https://github.com/zoxa) (bug fixes)
+
+
+## CloudFusion/CacheCore/RequestCore Contributors
+
+Contributions were provided under the New BSD License, as appropriate.
+
+The following people have provided ideas, support and bug fixes:
+
+* [Aaron Collegeman](http://blog.aaroncollegeman.com) (bug fixes)
+* [Alex Schenkel](http://code.google.com/u/alex.schenkel/) (bug fixes)
+* [Andrzej Bednarczyk](http://kreo-consulting.com) (bug fixes)
+* [bprater](http://code.google.com/u/bprater/) (bug fixes)
+* [castoware](http://code.google.com/u/castoware/) (bug fixes)
+* [Chris Chen](http://github.com/chrischen) (bug fixes, patches, support)
+* [Chris Mytton](http://hecticjeff.net) (bug fixes)
+* [evgen.dm](http://code.google.com/u/evgen.dm/) (bug fixes)
+* [gafitescu](http://code.google.com/u/gafitescu/) (bug fixes)
+* [Gary Richardson](http://code.google.com/u/gary.richardson/) (bug fixes)
+* [Gil Hildebrand](http://squidoo.com) (bug fixes)
+* [Guilherme Blanco](http://blog.bisna.com) (bug fixes)
+* [hammjazz](http://code.google.com/u/hammjazz/) (bug fixes)
+* [HelloBunty](http://code.google.com/u/HelloBunty/) (bug fixes)
+* [inputrequired](http://code.google.com/u/inputrequired/) (bug fixes)
+* [Ivo Beckers](http://infopractica.nl) (bug fixes)
+* [Jason Litka](http://jasonlitka.com) (bug fixes, patches)
+* [Jeremy Archuleta](http://code.google.com/u/jeremy.archuleta/) (bug fixes)
+* [John Beales](http://johnbeales.com) (bug fixes)
+* [John Parker](http://code.google.com/u/john3parker/) (bug fixes)
+* [Jon Cianciullo](http://code.google.com/u/jon.cianciullo/) (bug fixes)
+* [kris0476](http://code.google.com/u/kris0476/) (bug fixes)
+* [Matt Terenzio](http://jour.nali.st/blog) (bug fixes, patches)
+* [Mike Jetter](http://mbjetter.com) (bug fixes)
+* [Morten Blinksbjerg Nielsen](http://mbn.dk) (bug fixes)
+* [nathell](http://code.google.com/u/nathell/) (bug fixes)
+* [nickgsuperstar](http://code.google.com/u/nickgsuperstar/) (bug fixes)
+* [ofpichon](http://code.google.com/u/ofpichon/) (bug fixes)
+* [Otavio Ferreira](http://otaviofff.me) (bug fixes)
+* [Paul Voegler](mailto:voegler@gmx.de) (bug fixes, bug reports, patches)
+* [Steve Brozosky](http://code.google.com/u/@UBZWSlJVBxhHXAN1/) (bug fixes)
+* [Steve Chu](http://stevechu.org) (bug fixes)
+* [tommusic](http://code.google.com/u/tommusic/) (bug fixes)
+* [Tyler Hall](http://clickontyler.com) (bug fixes)
+* [webcentrica.co.uk](http://code.google.com/u/@VhBQQldUBBBEXAF1/) (bug fixes)
+* [worden341](http://github.com/worden341) (bug fixes)
+* [yakkyjunk](http://code.google.com/u/yakkyjunk/) (bug fixes)
diff --git a/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html b/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html
new file mode 100644
index 00000000000..8b1545db50a
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/DYNAMODBSESSIONHANDLER.html
@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>README</title>
+ <style type="text/css" media="screen">
+ body {
+ font: 18px/1.5em 'Book Antiqua', 'Palatino Linotype', Palatino, 'Minion Pro', Cambria, Georgia, serif;
+ padding: 50px 10%;
+ max-width: 1000px;
+ margin: 0 auto;
+ color: #080000;
+ background-color: #fbfbf9;
+ }
+ code {
+ font: 13px/1.4em Monaco, monospace;
+ background-color: #f3f3f3;
+ color: #444;
+ padding: 1px 2px;
+
+ border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ }
+ pre {
+ border: 1px solid #ddd;
+ border-left: 6px solid #c0c0c0;
+ background-color: #f3f3f3;
+ color: #444;
+ font: 13px/1.4em Monaco, monospace;
+ overflow: auto;
+
+ margin: 1em 0 1.5em 0;
+ padding: 1em;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+
+ -webkit-border-top-right-radius: 5px;
+ -webkit-border-bottom-right-radius: 5px;
+ -moz-border-radius-topright: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+ }
+ pre code {
+ font-family: inherit;
+ font-size: inherit;
+ background-color: inherit;
+ color: inherit;
+ padding: 0;
+
+ border-radius: none;
+ -webkit-border-radius: none;
+ -moz-border-radius: none;
+ }
+ a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ }
+ a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+ }
+ a.active {
+ font-weight: bold;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ padding: 0.8em 0 0.2em 0;
+ margin: 0;
+ }
+ h1 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 2em;
+ line-height: 1.3em;
+ border-bottom: 3px solid #cdcdcc;
+ }
+ h2 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 1.5em;
+ line-height: 1.3em;
+ border-bottom: 1px solid #cdcdcc;
+ }
+ li {
+ margin: 0;
+ padding: 0;
+ }
+ em, i {
+ font-style: italic;
+ }
+ strong, b {
+ font-weight: bold;
+ color: #000;
+ }
+ p {
+ margin: 0;
+ padding: 0.5em 0;
+ }
+ ul.columns {
+ -moz-column-count: 3;
+ -moz-column-gap: 20px;
+ -webkit-column-count: 3;
+ -webkit-column-gap: 20px;
+ column-count: 3;
+ column-gap: 20px;
+ }
+ dl dt {
+ font: 13px/1.4em Monaco, monospace;
+ font-weight: bold;
+ }
+ dl dd {
+ margin-bottom: 0.5em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>DynamoDB Session Handler</h1>
+ <p>The <strong>DynamoDB Session Handler</strong> is a custom session handler for PHP that allows Amazon DynamoDB to be used as a session store while still using PHP&rsquo;s native session functions.</p>
+
+ <h2>What issues does this address?</h2>
+ <p>The native PHP session handler stores sessions on the local file system. This is unreliable in distributed web applications, because the user may be routed to servers that do not contain the session data. To solve this problem, PHP developers have implemented custom solutions for storing user session data using databases, shared file systems, Memcache servers, tamper-proof cookies, etc., by taking advantage of the interface provided by PHP via the <code>session_set_save_handler()</code> function. Unfortunately, most of these solutions require a lot of configuration or prior knowledge about the storage mechanism in order to setup. Some of them also require the provisioning or management of additional servers.</p>
+
+ <h2>Proposed solution</h2>
+ <p>The DynamoDB Session Handler uses Amazon DynamoDB as a session store, which alleviates many of the problems with existing solutions. There are no additional servers to manage, and there is very little configuration required. The Amazon DynamoDB is also fundamentally designed for low latency (the data is even stored on <abbr title="Solid State Drive">SSD</abbr>s), so the performance impact is much smaller when compared to other databases. Since the Session Handler is designed to be a drop in replacement for the default PHP session handler, it also implements session locking in a familiar way.</p>
+
+ <h2>How do I use it?</h2>
+ <p>The first step is to instantiate the Amazon DynamoDB client and register the session handler.</p>
+ <pre>require_once 'AWSSDKforPHP/sdk.class.php';
+
+// Instantiate the Amazon DynamoDB client.
+// REMEMBER: You need to set 'default_cache_config' in your config.inc.php.
+$dynamodb = new AmazonDynamoDB();
+
+// Register the DynamoDB Session Handler.
+$handler = $dynamodb->register_session_handler(array(
+ 'table_name' => 'my-sessions-table'
+));</pre>
+ <p>Before you can use the session handler, you need to create a table to store the sessions in. This can be done through the <a href="https://console.aws.amazon.com/dynamodb/home">AWS Console for Amazon DynamoDB</a>, or using the session handler class (which you must configure with the table name like in the example above).</p>
+ <pre>// Create a table for session storage with default settings.
+$handler->create_sessions_table();</pre>
+ <p>If you create the table via the AWS Console, you need to make sure the primary key is a string. By default the DynamoDB Session Handler looks for a key named "id", so if you name the key something else, you will need to specify that when you configure the session handler (see the <a href="#configuration">Configuration section</a> below).</p>
+ <p>Once the session handler is registered with a valid table, you can write to (and read from) the session using the standard <code>$_SESSION</code> superglobal.</p>
+ <pre>// Start the session. This will acquire a lock if session locking is enabled.
+session_start();
+
+// Alter the session data.
+$_SESSION['username'] = 'jeremy';
+$_SESSION['role'] = 'admin';
+
+// Close and write to the session.
+// REMEMBER: You should close the session ASAP to release the session lock.
+session_write_close();</pre>
+
+ <h3>Removing expired sessions</h3>
+ <p>The session handler ties into PHP's native session garbage collection functionality, so expired sessions will be deleted periodically and automatically based on how you configure PHP to do the garbage collection. See the PHP manual for the following PHP INI settings: <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-probability">session.gc_probability</a>, <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-divisor">session.gc_divisor</a>, and <a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime">session.gc_maxlifetime</a>. You may also manually call the <code>DynamoDBSessionHandler::garbage_collect()</code> to clean up the expired sessions.</p>
+
+ <h2 id="configuration">Configuring the DynamoDB Session Handler</h2>
+ <p>You may configure the behavior of the session handler using a the following settings:</p>
+ <dl>
+ <dt>table_name</dt>
+ <dd>The name of the DynamoDB table in which to store sessions.</dd>
+
+ <dt>hash_key</dt>
+ <dd>The name of the primary hash key in the DynamoDB sessions table.</dd>
+
+ <dt>session_lifetime</dt>
+ <dd>The lifetime of an inactive session before it should be garbage collected. If <code>0</code> is used, then the actual lifetime value that will be used is <code>ini_get('session.gc_maxlifetime')</code>.</dd>
+
+ <dt>consistent_reads</dt>
+ <dd>Whether or not the session handler should do consistent reads from DynamoDB.</dd>
+
+ <dt>session_locking</dt>
+ <dd>Whether or not the session handler should do session locking (see the <a href="#session_locking">Session locking section</a> for more information).</dd>
+
+ <dt>max_lock_wait_time</dt>
+ <dd>Maximum time, in seconds, that the session handler should take to acquire a lock before giving up. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+
+ <dt>min_lock_retry_utime</dt>
+ <dd>Minimum time, in microseconds, that the session handler should wait to retry acquiring a lock. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+
+ <dt>max_lock_retry_utime</dt>
+ <dd>Maximum time, in microseconds, that the session handler should wait to retry acquiring a lock. Only used if <code>session_locking</code> is <code>true</code>.</dd>
+ </dl>
+
+ <p>To configure the Session Handle, you must pass the configuration data into the constructor. (<strong>Note</strong>: The values used below are actually the default settings.)</p>
+ <pre>$dynamodb = new AmazonDynamoDB();
+$handler = $dynamodb->register_session_handler(array(
+ 'table_name' => 'sessions',
+ 'hash_key' => 'id',
+ 'session_lifetime' => 0,
+ 'consistent_reads' => true,
+ 'session_locking' => true,
+ 'max_lock_wait_time' => 15,
+ 'min_lock_retry_utime' => 5000,
+ 'max_lock_retry_utime' => 50000,
+));</pre>
+
+ <h2 id="session_locking">Session locking</h2>
+ <p>The default session handler for PHP locks sessions using a pessimistic locking algorithm. If a request (process) opens a session for reading using the <code>session_start()</code> function, it first acquires a lock. The lock is closed when that request writes back to the session, either when the request is complete, or via the <code>session_write_close()</code> function. Since the DynamoDB Session Handler is meant to be a drop in replacement for the default session handler, it also implements the same locking scheme. However, this can be slow, undesirable, and costly when multiple, simultaneous requests from the same user occur, particularly with ajax requests or HTML iframes. In some cases, you may not want or need the session to be locked. After evaluating whether or not your application actually requires session locking, you may turn off locking when you configure the session handler by setting <code>session_locking</code> to <code>false</code>.</p>
+
+ <h2 id="pricing">Pricing</h2>
+ <p>Aside from nominal data storage and data transfer fees, the costs associated with using Amazon DynamoDB are calculated based on provisioned throughput capacity and item size (see the <a href="http://aws.amazon.com/dynamodb/#pricing">Amazon DynamoDB pricing</a> details). Throughput is measured in units of Read Capacity and Write Capacity. Ultimately, the throughput and costs required for your sessions table is going to be based on your website traffic, but the following is a list of the capacity units required for each session-related operation:</p>
+ <ul>
+ <li><strong>Reading</strong> via <code>session_start()</code>
+ <p>With locking enabled: 1 unit of Write Capacity + 1 unit of Write Capacity for each time it must retry acquiring the lock</p>
+ <p>With locking disabed: 1 unit of Read Capacity (or 0.5 units of Read Capacity if <i>consistent reads</i> are disabled)</p>
+ </li>
+ <li><strong>Writing</strong> via <code>session_write_close()</code>
+ <p>1 unit of Write Capacity</p>
+ </li>
+ <li><strong>Deleting</strong> via <code>session_destroy()</code>
+ <p>1 unit of Write Capacity</p>
+ </li>
+ <li><strong>Garbage Collecting</strong> via <code>DyanamoDBSessionHandler::garbage_collect()</code>
+ <p>0.5 units of Read Capacity per KB of data in the sessions table + 1 unit of Write Capacity per expired item</p>
+ </li>
+ </ul>
+
+ <h2 id="more_information">More information</h2>
+ <p>For more information on the Amazon DynamoDB service please visit the <a href="http://aws.amazon.com/dynamodb">Amazon DynamoDB homepage</a>.</p>
+
+ </body>
+</html>
diff --git a/3rdparty/aws-sdk/_docs/KNOWNISSUES.md b/3rdparty/aws-sdk/_docs/KNOWNISSUES.md
new file mode 100644
index 00000000000..9773c3932b8
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/KNOWNISSUES.md
@@ -0,0 +1,65 @@
+# Known Issues
+
+## 2GB limit for 32-bit stacks; all Windows stacks.
+
+Because PHP's integer type is signed and many platforms use 32-bit integers, the AWS SDK for PHP does not correctly
+handle files larger than 2GB on a 32-bit stack (where "stack" includes CPU, OS, web server, and PHP binary). This is a
+[well-known PHP issue]. In the case of Microsoft® Windows®, there are no official builds of PHP that support 64-bit
+integers.
+
+The recommended solution is to use a 64-bit Linux stack, such as the [64-bit Amazon Linux AMI] with the latest version of
+PHP installed.
+
+For more information, please see: [PHP filesize: Return values]. A workaround is suggested in
+`AmazonS3::create_mpu_object()` [with files bigger than 2GB].
+
+ [well-known PHP issue]: http://www.google.com/search?q=php+2gb+32-bit
+ [64-bit Amazon Linux AMI]: http://aws.amazon.com/amazon-linux-ami/
+ [PHP filesize: Return values]: http://docs.php.net/manual/en/function.filesize.php#refsect1-function.filesize-returnvalues
+ [with files bigger than 2GB]: https://forums.aws.amazon.com/thread.jspa?messageID=215487#215487
+
+
+## Amazon S3 Buckets containing periods
+
+Amazon S3's SSL certificate covers domains that match `*.s3.amazonaws.com`. When buckets (e.g., `my-bucket`) are accessed
+using DNS-style addressing (e.g., `my-bucket.s3.amazonaws.com`), those SSL/HTTPS connections are covered by the certificate.
+
+However, when a bucket name contains one or more periods (e.g., `s3.my-domain.com`) and is accessed using DNS-style
+addressing (e.g., `s3.my-domain.com.s3.amazonaws.com`), that SSL/HTTPS connection will fail because the certificate
+doesn't match.
+
+The most secure workaround is to change the bucket name to one that does not contain periods. Less secure workarounds
+are to use `disable_ssl()` or `disable_ssl_verification()`. Because of the security implications, calling either of
+these methods will throw a warning. You can avoid the warning by adjusting your `error_reporting()` settings.
+
+
+## Expiring request signatures
+
+When leveraging `AmazonS3::create_mpu_object()`, it's possible that later parts of the multipart upload will fail if
+the upload takes more than 15 minutes.
+
+
+## Too many open file connections
+
+When leveraging `AmazonS3::create_mpu_object()`, it's possible that the SDK will attempt to open too many file resources
+at once. Because the file connection limit is not available to the PHP environment, the SDK is unable to automatically
+adjust the number of connections it attempts to open.
+
+A workaround is to increase the part size so that fewer file connections are opened.
+
+
+## Exceptionally large batch requests
+
+When leveraging the batch request feature to execute multiple requests in parallel, it's possible that the SDK will
+throw a fatal exception if a particular batch pool is exceptionally large and a service gets overloaded with requests.
+
+This seems to be most common when attempting to send a large number of emails with the SES service.
+
+
+## Long-running processes using SSL leak memory
+
+When making requests with the SDK over SSL during long-running processes, there will be a gradual memory leak that can
+eventually cause a crash. The leak occurs within the PHP bindings for cURL when attempting to verify the peer during an
+SSL handshake. See <https://bugs.php.net/61030> for details about the bug.
+
+A workaround is to disable SSL for requests executed in long-running processes.
diff --git a/3rdparty/aws-sdk/_docs/LICENSE.md b/3rdparty/aws-sdk/_docs/LICENSE.md
new file mode 100644
index 00000000000..853ab3bae8e
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/LICENSE.md
@@ -0,0 +1,151 @@
+# Apache License
+Version 2.0, January 2004
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+
+## 1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1
+through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the
+License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled
+by, or are under common control with that entity. For the purposes of this definition, "control" means
+(i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract
+or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software
+source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form,
+including but not limited to compiled object code, generated documentation, and conversions to other media
+types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License,
+as indicated by a copyright notice that is included in or attached to the work (an example is provided in the
+Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from)
+the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent,
+as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not
+include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work
+and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any
+modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to
+Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to
+submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of
+electronic, verbal, or written communication sent to the Licensor or its representatives, including but not
+limited to communication on electronic mailing lists, source code control systems, and issue tracking systems
+that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but
+excluding communication that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been
+received by Licensor and subsequently incorporated within the Work.
+
+
+## 2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare
+Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+
+## 3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual,
+worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent
+license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such
+license applies only to those patent claims licensable by such Contributor that are necessarily infringed by
+their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such
+Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim
+or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work
+constitutes direct or contributory patent infringement, then any patent licenses granted to You under this
+License for that Work shall terminate as of the date such litigation is filed.
+
+
+## 4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without
+modifications, and in Source or Object form, provided that You meet the following conditions:
+
+ 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+ 2. You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+ 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent,
+ trademark, and attribution notices from the Source form of the Work, excluding those notices that do
+ not pertain to any part of the Derivative Works; and
+
+ 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that
+ You distribute must include a readable copy of the attribution notices contained within such NOTICE
+ file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed as part of the Derivative Works; within
+ the Source form or documentation, if provided along with the Derivative Works; or, within a display
+ generated by the Derivative Works, if and wherever such third-party notices normally appear. The
+ contents of the NOTICE file are for informational purposes only and do not modify the License. You may
+ add Your own attribution notices within Derivative Works that You distribute, alongside or as an
+ addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be
+ construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license
+terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative
+Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the
+conditions stated in this License.
+
+
+## 5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by
+You to the Licensor shall be under the terms and conditions of this License, without any additional terms or
+conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate
+license agreement you may have executed with Licensor regarding such Contributions.
+
+
+## 6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of
+the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+
+## 7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor
+provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the
+appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+
+## 8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless
+required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any
+Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential
+damages of any character arising as a result of this License or out of the use or inability to use the Work
+(including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has been advised of the possibility
+of such damages.
+
+
+## 9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for,
+acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this
+License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole
+responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold
+each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason
+of your accepting any such warranty or additional liability.
+
+
+END OF TERMS AND CONDITIONS
diff --git a/3rdparty/aws-sdk/_docs/NOTICE.md b/3rdparty/aws-sdk/_docs/NOTICE.md
new file mode 100644
index 00000000000..780c2e4c9d5
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/NOTICE.md
@@ -0,0 +1,444 @@
+# AWS SDK for PHP
+
+Based on [CloudFusion](http://getcloudfusion.com). Includes other third-party software.
+
+See below for complete copyright and licensing notices.
+
+
+## AWS SDK for PHP
+
+<http://aws.amazon.com/php>
+
+Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License").
+You may not use this file except in compliance with the License.
+A copy of the License is located at
+
+<http://aws.amazon.com/apache2.0>
+
+or in the "license" file accompanying this file. This file is distributed
+on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+express or implied. See the License for the specific language governing
+permissions and limitations under the License.
+
+
+## CloudFusion
+
+<http://getcloudfusion.com>
+
+* Copyright 2005-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+* Copyright 2007-2010 "CONTRIBUTORS" (see [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list)
+
+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 organization 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 HOLDER 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.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## CacheCore
+
+<http://github.com/skyzyx/cachecore>
+
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+
+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 organization 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 HOLDER 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.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## RequestCore
+
+<http://github.com/skyzyx/requestcore>
+
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2007-2010 [Foleeo Inc.](http://warpshare.com)
+
+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 organization 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 HOLDER 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.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## SimplePie
+
+<http://simplepie.org>
+
+* Copyright 2004-2010 [Ryan Parman](http://ryanparman.com)
+* Copyright 2005-2010 [Geoffrey Sneddon](http://gsnedders.com)
+* Copyright 2008-2011 [Ryan McCue](http://ryanmccue.info)
+
+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 organization 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 HOLDER 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.
+
+<http://opensource.org/licenses/bsd-license.php>
+
+
+## Reqwest
+
+<https://github.com/ded/reqwest>
+
+* Copyright 2011 [Dustin Diaz](http://dustindiaz.com)
+
+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.
+
+<http://www.opensource.org/licenses/mit-license.php>
+
+
+## Human readable file sizes
+
+<http://aidanlister.com/2004/04/human-readable-file-sizes/>
+
+* Copyright 2004-2010 [Aidan Lister](http://aidanlister.com)
+* Copyright 2007-2010 [Ryan Parman](http://ryanparman.com)
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED 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 PHP
+DEVELOPMENT TEAM OR ITS 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.
+
+<http://www.php.net/license/3_01.txt>
+
+
+## Snippets from PHP.net documentation
+
+* `CFUtilities::is_base64()` - Copyright 2008 "debug" <http://us.php.net/manual/en/function.base64-decode.php#81425>
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. 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.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED 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 PHP
+DEVELOPMENT TEAM OR ITS 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.
+
+<http://www.php.net/license/3_01.txt>
+
+
+## phunction PHP framework
+
+<http://sourceforge.net/projects/phunction/>
+
+* Copyright 2010 [Alix Axel](mailto:alix-axel@users.sf.net)
+
+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.
+
+<http://www.opensource.org/licenses/mit-license.php>
+
+
+## Symfony YAML Component
+
+<http://components.symfony-project.org/yaml/>
+
+Copyright 2008-2009 [Fabien Potencier](http://fabien.potencier.org)
+
+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.
+
+<http://opensource.org/licenses/mit-license.php>
+
+
+## PEAR Console_ProgressBar
+
+<http://pear.php.net/package/Console_ProgressBar/>
+
+Copyright 2003-2007 [Stefan Walk](http://pear.php.net/user/et)
+
+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.
+
+<http://opensource.org/licenses/mit-license.php>
+
+
+## Mozilla Certificate Authority
+
+* <http://curl.haxx.se/ca/cacert.pem>
+* <https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=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 Netscape security libraries.
+
+The Initial Developer of the Original Code is Netscape Communications
+Corporation. Portions created by the Initial Developer are Copyright
+(C) 1994-2000 the Initial Developer. All Rights Reserved.
+
+<http://www.mozilla.org/MPL/>
+
+
+## array-to-domdocument
+
+<https://code.google.com/p/array-to-domdocument/>
+
+* Copyright 2010-2011 [Omer Hassan](https://code.google.com/u/113495690012051782542/)
+* Portions copyright 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+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.
+
+<http://opensource.org/licenses/mit-license.php>
diff --git a/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html b/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html
new file mode 100644
index 00000000000..5d91068aa23
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/STREAMWRAPPER_README.html
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title>README</title>
+ <style type="text/css" media="screen">
+ body {
+ font: 18px/1.5em 'Book Antiqua', 'Palatino Linotype', Palatino, 'Minion Pro', Cambria, Georgia, serif;
+ padding: 50px 10%;
+ max-width: 1000px;
+ margin: 0 auto;
+ color: #080000;
+ background-color: #fbfbf9;
+ }
+ code {
+ font: 13px/1.4em Monaco, monospace;
+ background-color: #f3f3f3;
+ color: #444;
+ padding: 1px 2px;
+
+ border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ }
+ pre {
+ border: 1px solid #ddd;
+ border-left: 6px solid #c0c0c0;
+ background-color: #f3f3f3;
+ color: #444;
+ font: 13px/1.4em Monaco, monospace;
+ overflow: auto;
+
+ margin: 1em 0 1.5em 0;
+ padding: 1em;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+
+ -webkit-border-top-right-radius: 5px;
+ -webkit-border-bottom-right-radius: 5px;
+ -moz-border-radius-topright: 5px;
+ -moz-border-radius-bottomright: 5px;
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+ }
+ pre code {
+ font-family: inherit;
+ font-size: inherit;
+ background-color: inherit;
+ color: inherit;
+ padding: 0;
+
+ border-radius: none;
+ -webkit-border-radius: none;
+ -moz-border-radius: none;
+ }
+ a {
+ color: #326EA1;
+ text-decoration: underline;
+ padding: 1px 2px;
+ -webkit-transition: background-color 0.15s;
+ -webkit-transition: color 0.15s;
+ -moz-transition: background-color 0.15s;
+ -moz-transition: color 0.15s;
+ transition: background-color 0.15s;
+ transition: color 0.15s;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ border-radius: 2px;
+ }
+ a:hover, a.hover {
+ color: #fff;
+ background-color: #333;
+ text-decoration: none;
+ padding: 1px 2px;
+ }
+ a.active {
+ font-weight: bold;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ padding: 0.8em 0 0.2em 0;
+ margin: 0;
+ }
+ h1 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 2em;
+ line-height: 1.3em;
+ border-bottom: 3px solid #cdcdcc;
+ }
+ h2 {
+ margin-top: 30px;
+ padding: 15px 0 5px 5px;
+ font-size: 1.5em;
+ line-height: 1.3em;
+ border-bottom: 1px solid #cdcdcc;
+ }
+ li {
+ margin: 0;
+ padding: 0;
+ }
+ em, i {
+ font-style: italic;
+ }
+ strong, b {
+ font-weight: bold;
+ color: #000;
+ }
+ p {
+ margin: 0;
+ padding: 0.5em 0;
+ }
+ ul.columns {
+ -moz-column-count: 3;
+ -moz-column-gap: 20px;
+ -webkit-column-count: 3;
+ -webkit-column-gap: 20px;
+ column-count: 3;
+ column-gap: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>S3 Stream Wrapper</h1>
+ <p>The <strong>S3 Stream Wrapper</strong> is a stream wrapper interface for PHP that provides access to Amazon S3 using PHP&#8217;s standard File System API functions.</p>
+
+ <h2>What issues does this address?</h2>
+ <p>There are a large number of existing applications, code snippets and other bits of PHP that are designed to read and write from the local file system as part of their normal operations. Many of these apps could benefit from moving into the cloud, but doing so would require rewriting a substantial amount of code.</p>
+ <p>What if we could simplify this process so that the updates required to make an existing application cloud-backed would be very minimal?</p>
+
+ <h2>Proposed solution</h2>
+ <p>PHP provides an interface for solving this exact kind of problem, called the <a href="http://php.net/streamwrapper">Stream Wrapper</a> interface. By writing a class that implements this interface and <a href="http://php.net/manual/en/function.stream-wrapper-register.php">registering it as a handler</a> we can reduce both the amount of rewriting that needs to be done for existing applications, as well as substantially lower the learning curve for reading and writing from Amazon S3.</p>
+
+ <h2>How do I use it?</h2>
+ <p>After including the AWS SDK for PHP in your project, use the <code>AmazonS3::register_stream_wrapper()</code> method to register <code>s3://</code> as a <a href="http://php.net/manual/en/wrappers.php">supported stream wrapper</a> for Amazon S3. <em>It's that simple</em>. Amazon S3 file patterns take the following form: <code>s3://bucket/object</code>.</p>
+
+ <pre><code>require_once 'AWSSDKforPHP/sdk.class.php';
+
+$s3 = new AmazonS3();
+$s3->register_stream_wrapper();
+
+$directory = 's3://my-new-bucket';
+$filename = $directory . '/put.txt';
+$contents = '';
+
+if (mkdir($directory))
+{
+ if (file_put_contents($filename, 'This is some sample data.'))
+ {
+ $handle = fopen($filename, 'rb+');
+ $contents = stream_get_contents($handle);
+ fclose($handle);
+ }
+
+ rmdir($directory);
+}
+
+echo $contents;</code></pre>
+
+ <p>You may also pass a different protocol name as a parameter to <code>AmazonS3::register_stream_wrapper()</code> if you want to use something besides <code>s3://</code>. Using this technique you can create more than one stream wrapper with different configurations (e.g. for different regions). To do that you just need to create separate instances of the <code>AmazonS3</code> class, configure them, and then register a stream wrapper for each of them with different protocol names.</p>
+
+ <pre><code>require_once 'AWSSDKforPHP/sdk.class.php';
+
+$s3east = new AmazonS3();
+$s3east->set_region(AmazonS3::REGION_US_E1);
+$s3east->register_stream_wrapper('s3east');
+mkdir('s3east://my-easterly-bucket');
+
+$s3west = new AmazonS3();
+$s3west->set_region(AmazonS3::REGION_US_W1);
+$s3west->register_stream_wrapper('s3west');
+mkdir('s3west://my-westerly-bucket');</code></pre>
+
+ <h2>Tests and usage examples</h2>
+ <p>We are also including tests written in the <a href="http://qa.php.net/phpt_details.php">PHPT</a> format. Not only do these tests show how the software can be used, but any tests submitted back to us should be in this format. These tests will likely fail for you unless you change the bucket names to be globally unique across S3. You can run the tests with <code>pear</code>.</p>
+ <pre><code>cd S3StreamWrapper/tests;
+pear run-tests;</code></pre>
+ <p>If you have <a href="http://phpunit.de">PHPUnit</a> 3.6+ and <a href="http://xdebug.org">Xdebug</a> installed, you can generate a code coverage report as follows:</p>
+ <pre><code>cd S3StreamWrapper/tests && \
+phpunit --colors --coverage-html ./_coverage_report . && \
+open ./_coverage_report/index.html;</code></pre>
+
+ <h2>Notes and Known Issues</h2>
+ <ul>
+ <li><p><code>stream_lock()</code> and <code>stream_cast()</code> are not currently implemented, and likely won't be.</p></li>
+ <li><p>Strangely <code>touch()</code> doesn&#8217;t seem to work. I think this is because of an issue with my implementation of <code>url_stat()</code>, but I can&#8217;t find any information on the magical combination of parameters that will make this work.</p></li>
+ <li><p>Using <code>fopen()</code> will always open in <code>rb+</code> mode. Amazon S3 as a service doesn&#8217;t support anything else.</p></li>
+ <li><p>Because of the way that PHP interacts with the <a href="http://php.net/manual/en/class.streamwrapper.php">StreamWrapper</a> interface, it&#8217;s difficult to optimize for batch requests under the hood. If you need to push or pull data from several objects, you may find that using <a href="http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#m=CFRuntime/batch">batch requests</a> with the <a href="http://docs.amazonwebservices.com/AWSSDKforPHP/latest/#i=AmazonS3">standard interface</a> has better latency.</p></li>
+ <li><p><code>rmdir()</code> does not do a force-delete, so you will need to iterate over the files to delete them one-by-one.</p></li>
+ <li><p><code>realpath()</code>, <code>glob()</code>, <code>chmod()</code>, <code>chown()</code>, <code>chgrp()</code>, <code>tempnam()</code> and a few other functions don&#8217;t support the StreamWrapper interface at the PHP-level because they're designed to work with the (no/low-latency) local file system.</p></li>
+ <li><p>Support for <code>ftruncate()</code> does not exist in any current release of PHP, but is implemented on the PHP trunk for a future release. <a href="http://bugs.php.net/53888">http://bugs.php.net/53888</a>.</p></li>
+ <li><p>Since <a href="http://docs.amazonwebservices.com/AmazonS3/latest/gsg/WorkingWithS3.html#WriteObject">Amazon S3 doesn&#8217;t support appending data</a>, it is best to avoid functions that expect or rely on that functionality (e.g. <a href="http://php.net/fputcsv">fputcsv()</a>).</p></li>
+ </ul>
+
+ <h2>Successfully tested with</h2>
+ <ul class="columns">
+ <li><a href="http://php.net/close_dir">close_dir()</a></li>
+ <li><a href="http://php.net/file_exists">file_exists()</a></li>
+ <li><a href="http://php.net/file_get_contents">file_get_contents()</a></li>
+ <li><a href="http://php.net/file_put_contents">file_put_contents()</a></li>
+ <li><a href="http://php.net/fclose">fclose()</a></li>
+ <li><a href="http://php.net/feof">feof()</a></li>
+ <li><a href="http://php.net/fflush">fflush()</a></li>
+ <li><a href="http://php.net/fgetc">fgetc()</a></li>
+ <li><a href="http://php.net/fgetcsv">fgetcsv()</a></li>
+ <li><a href="http://php.net/fgets">fgets()</a></li>
+ <li><a href="http://php.net/fgetss">fgetss()</a></li>
+ <li><a href="http://php.net/fopen">fopen()</a></li>
+ <li><a href="http://php.net/fpassthru">fpassthru()</a></li>
+ <li><a href="http://php.net/fputs">fputs()</a></li>
+ <li><a href="http://php.net/fread">fread()</a></li>
+ <li><a href="http://php.net/fseek">fseek()</a></li>
+ <li><a href="http://php.net/fstat">fstat()</a></li>
+ <li><a href="http://php.net/ftell">ftell()</a></li>
+ <li><a href="http://php.net/fwrite">fwrite()</a></li>
+ <li><a href="http://php.net/is_dir">is_dir()</a></li>
+ <li><a href="http://php.net/is_file">is_file()</a></li>
+ <li><a href="http://php.net/is_readable">is_readable()</a></li>
+ <li><a href="http://php.net/is_writable">is_writable()</a></li>
+ <li><a href="http://php.net/mkdir">mkdir()</a></li>
+ <li><a href="http://php.net/open_dir">open_dir()</a></li>
+ <li><a href="http://php.net/read_dir">read_dir()</a></li>
+ <li><a href="http://php.net/rewind">rewind()</a></li>
+ <li><a href="http://php.net/rewinddir">rewinddir()</a></li>
+ <li><a href="http://php.net/rmdir">rmdir()</a></li>
+ <li><a href="http://php.net/scandir">scandir()</a></li>
+ <li><a href="http://php.net/stream_get_contents">stream_get_contents()</a></li>
+ <li><a href="http://php.net/unlink">unlink()</a></li>
+ </ul>
+
+ <h2>Known issues with</h2>
+ <ul>
+ <li><a href="http://php.net/chgrp">chgrp()</a></li>
+ <li><a href="http://php.net/chmod">chmod()</a></li>
+ <li><a href="http://php.net/chown">chown()</a></li>
+ <li><a href="http://php.net/fputcsv">fputcsv()</a></li>
+ <li><a href="http://php.net/glob">glob()</a></li>
+ <li><a href="http://php.net/realpath">realpath()</a></li>
+ <li><a href="http://php.net/tempnam">tempnam()</a></li>
+ <li><a href="http://php.net/touch">touch()</a></li>
+ </ul>
+
+ <p>A future version <em>may</em> provide S3-specific implementations of some of these functions (e.g., <code>s3chmod()</code>, <code>s3glob()</code>, <code>s3touch()</code>).</p>
+ </body>
+</html>
diff --git a/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md b/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md
new file mode 100644
index 00000000000..7ad235576b4
--- /dev/null
+++ b/3rdparty/aws-sdk/_docs/WHERE_IS_THE_API_REFERENCE.md
@@ -0,0 +1,2 @@
+You can find the API Reference at:
+http://docs.amazonwebservices.com/AWSSDKforPHP/latest/
diff --git a/3rdparty/aws-sdk/authentication/signable.interface.php b/3rdparty/aws-sdk/authentication/signable.interface.php
new file mode 100644
index 00000000000..5316d16a815
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signable.interface.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// INTERFACE
+
+/**
+ * The interface implemented by all signing classes.
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+interface Signable
+{
+ /**
+ * Constructs a new instance of the implementing class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials);
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate();
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v2query.class.php b/3rdparty/aws-sdk/authentication/signature_v2query.class.php
new file mode 100644
index 00000000000..a91190e1a25
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v2query.class.php
@@ -0,0 +1,163 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v2 (AWS Query).
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV2Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV2Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $query = array();
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $query['Version'] = $this->api_version;
+ }
+
+ $query['Action'] = $this->operation;
+ $query['AWSAccessKeyId'] = $this->key;
+ $query['SignatureMethod'] = 'HmacSHA256';
+ $query['SignatureVersion'] = 2;
+ $query['Timestamp'] = $timestamp;
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+
+ // Create the string that needs to be hashed.
+ $canonical_query_string = $this->util->to_signable_string($query);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Prepare the string to sign
+ $this->string_to_sign = "POST\n$host_header\n$request_uri\n$canonical_query_string";
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $query['Signature'] = base64_encode(hash_hmac('sha256', $this->string_to_sign, $this->secret_key, true));
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->querystring);
+ $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+ }
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v3json.class.php b/3rdparty/aws-sdk/authentication/signature_v3json.class.php
new file mode 100644
index 00000000000..d07f554d1f7
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v3json.class.php
@@ -0,0 +1,235 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v3 (JSON).
+ *
+ * @version 2011.12.08
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV3JSON extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV3JSON> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $nonce = $this->util->generate_guid();
+ $curlopts = array();
+ $signed_headers = array();
+ $return_curl_handle = false;
+ $x_amz_target = null;
+ $query = array('body' => $this->payload);
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $query['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $query['Version'] = $this->api_version;
+ }
+
+ $curlopts = array();
+
+ // Set custom CURLOPT settings
+ if (is_array($this->payload) && isset($this->payload['curlopts']))
+ {
+ $curlopts = $this->payload['curlopts'];
+ unset($this->payload['curlopts']);
+ }
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ $return_curl_handle = isset($query['returnCurlHandle']) ? $query['returnCurlHandle'] : false;
+ unset($query['returnCurlHandle']);
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+
+ // Normalize JSON input
+ if (isset($query['body']) && $query['body'] === '[]')
+ {
+ $query['body'] = '{}';
+ }
+
+ // Create the string that needs to be hashed.
+ $canonical_query_string = $this->util->encode_signature2($query['body']);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ //$request->set_body($this->querystring);
+ //$headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Signing using X-Amz-Target is handled differently.
+ $headers['X-Amz-Target'] = $x_amz_target;
+ $headers['Content-Type'] = 'application/x-amz-json-1.0';
+ $request->set_body($query['body']);
+ $this->querystring = $query['body'];
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ // $headers['X-Amz-Nonce'] = $nonce;
+ $headers['Date'] = $date;
+ $headers['Content-Length'] = strlen($this->querystring);
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Prepare the string to sign (HTTP)
+ $this->string_to_sign = "POST\n$request_uri\n\n";
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ substr(strtolower($header_key), 0, 8) === 'content-' ||
+ strtolower($header_key) === 'date' ||
+ strtolower($header_key) === 'expires' ||
+ strtolower($header_key) === 'host' ||
+ substr(strtolower($header_key), 0, 6) === 'x-amz-'
+ )
+ {
+ $this->string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+ $signed_headers[] = $header_key;
+ }
+ }
+
+ $this->string_to_sign .= "\n";
+
+ if (isset($query['body']) && $query['body'] !== '')
+ {
+ $this->string_to_sign .= $query['body'];
+ }
+
+ // Convert from string-to-sign to bytes-to-sign
+ $bytes_to_sign = hash('sha256', $this->string_to_sign, true);
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha256', $bytes_to_sign, $this->secret_key, true));
+
+ $headers['X-Amzn-Authorization'] = 'AWS3'
+ . ' AWSAccessKeyId=' . $this->key
+ . ',Algorithm=HmacSHA256'
+ . ',SignedHeaders=' . implode(';', $signed_headers)
+ . ',Signature=' . $signature;
+
+ $request->add_header('X-Amzn-Authorization', $headers['X-Amzn-Authorization']);
+ $request->request_headers = $headers;
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v3query.class.php b/3rdparty/aws-sdk/authentication/signature_v3query.class.php
new file mode 100644
index 00000000000..04565f928ed
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v3query.class.php
@@ -0,0 +1,192 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v3 (AWS Query).
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV3Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV3Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, $current_time);
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_ISO8601, $current_time);
+ $nonce = $this->util->generate_guid();
+ $curlopts = array();
+ $signed_headers = array();
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ $query['SecurityToken'] = $this->auth_token;
+ }
+
+ $query['Action'] = $this->operation;
+ $query['Version'] = $this->api_version;
+
+ // Set custom CURLOPT settings
+ if (is_array($this->payload) && isset($this->payload['curlopts']))
+ {
+ $curlopts = $this->payload['curlopts'];
+ unset($this->payload['curlopts']);
+ }
+
+ // Merge in any options that were passed in
+ if (is_array($this->payload))
+ {
+ $query = array_merge($query, $this->payload);
+ }
+
+ $return_curl_handle = isset($query['returnCurlHandle']) ? $query['returnCurlHandle'] : false;
+ unset($query['returnCurlHandle']);
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($query, 'strcmp');
+ $canonical_query_string = $this->util->to_signable_string($query);
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Set the proper request URI.
+ $request_uri = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
+
+ // Generate the querystring from $query
+ $this->querystring = $this->util->to_query_string($query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->querystring);
+ $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $headers['X-Amz-Nonce'] = $nonce;
+ $headers['Date'] = $date;
+ $headers['Content-Length'] = strlen($this->querystring);
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Prepare the string to sign (HTTPS)
+ $this->string_to_sign = $date . $nonce;
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ substr(strtolower($header_key), 0, 8) === 'content-' ||
+ strtolower($header_key) === 'date' ||
+ strtolower($header_key) === 'expires' ||
+ strtolower($header_key) === 'host' ||
+ substr(strtolower($header_key), 0, 6) === 'x-amz-'
+ )
+ {
+ $signed_headers[] = $header_key;
+ }
+ }
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha256', $this->string_to_sign, $this->secret_key, true));
+
+ $headers['X-Amzn-Authorization'] = 'AWS3-HTTPS'
+ . ' AWSAccessKeyId=' . $this->key
+ . ',Algorithm=HmacSHA256'
+ . ',SignedHeaders=' . implode(';', $signed_headers)
+ . ',Signature=' . $signature;
+
+ $request->add_header('X-Amzn-Authorization', $headers['X-Amzn-Authorization']);
+ $request->request_headers = $headers;
+
+ return $request;
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v4json.class.php b/3rdparty/aws-sdk/authentication/signature_v4json.class.php
new file mode 100644
index 00000000000..d3ab07ad8bf
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v4json.class.php
@@ -0,0 +1,353 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v4 (Query).
+ *
+ * @version 2011.01.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV4JSON extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV4Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_SIGV4, $current_time);
+
+ // Initialize
+ $x_amz_target = null;
+
+ $this->headers = array();
+ $this->signed_headers = array();
+ $this->canonical_headers = array();
+ $this->query = array();
+
+ // Prepare JSON structure
+ $decoded = json_decode($this->payload, true);
+ $data = (array) (is_array($decoded) ? $decoded : $this->payload);
+ unset($data['curlopts']);
+ unset($data['returnCurlHandle']);
+ $this->body = json_encode($data);
+ if ($this->body === '' || $this->body === '[]')
+ {
+ $this->body = '{}';
+ }
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $this->headers['X-Amz-Security-Token'] = $this->auth_token;
+ $this->query['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $this->query['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $this->query['Version'] = $this->api_version;
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($this->query, 'strcmp');
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Generate the querystring from $this->query
+ $this->querystring = $this->util->to_query_string($this->query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->body);
+ $this->querystring = $this->body;
+ $this->headers['Content-Type'] = 'application/x-amz-json-1.1';
+ $this->headers['X-Amz-Target'] = $x_amz_target;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $this->headers['X-Amz-Date'] = $timestamp;
+ $this->headers['Content-Length'] = strlen($this->querystring);
+ $this->headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($this->headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($this->headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ $request->add_header($header_key, $header_value);
+ $this->canonical_headers[] = strtolower($header_key) . ':' . $header_value;
+
+ $this->signed_headers[] = strtolower($header_key);
+ }
+
+ $this->headers['Authorization'] = $this->authorization($timestamp);
+ $request->add_header('Authorization', $this->headers['Authorization']);
+ $request->request_headers = $this->headers;
+
+ return $request;
+ }
+
+ /**
+ * Generates the authorization string to use for the request.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The authorization string.
+ */
+ protected function authorization($datetime)
+ {
+ $access_key_id = $this->key;
+
+ $parts = array();
+ $parts[] = "AWS4-HMAC-SHA256 Credential=${access_key_id}/" . $this->credential_string($datetime);
+ $parts[] = 'SignedHeaders=' . implode(';', $this->signed_headers);
+ $parts[] = 'Signature=' . $this->hex16($this->signature($datetime));
+
+ return implode(',', $parts);
+ }
+
+ /**
+ * Calculate the signature.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The signature.
+ */
+ protected function signature($datetime)
+ {
+ $k_date = $this->hmac('AWS4' . $this->secret_key, substr($datetime, 0, 8));
+ $k_region = $this->hmac($k_date, $this->region());
+ $k_service = $this->hmac($k_region, $this->service());
+ $k_credentials = $this->hmac($k_service, 'aws4_request');
+ $signature = $this->hmac($k_credentials, $this->string_to_sign($datetime));
+
+ return $signature;
+ }
+
+ /**
+ * Calculate the string to sign.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The string to sign.
+ */
+ protected function string_to_sign($datetime)
+ {
+ $parts = array();
+ $parts[] = 'AWS4-HMAC-SHA256';
+ $parts[] = $datetime;
+ $parts[] = $this->credential_string($datetime);
+ $parts[] = $this->hex16($this->hash($this->canonical_request()));
+
+ $this->string_to_sign = implode("\n", $parts);
+
+ return $this->string_to_sign;
+ }
+
+ /**
+ * Generates the credential string to use for signing.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The credential string.
+ */
+ protected function credential_string($datetime)
+ {
+ $parts = array();
+ $parts[] = substr($datetime, 0, 8);
+ $parts[] = $this->region();
+ $parts[] = $this->service();
+ $parts[] = 'aws4_request';
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Calculate the canonical request.
+ *
+ * @return string The canonical request.
+ */
+ protected function canonical_request()
+ {
+ $parts = array();
+ $parts[] = 'POST';
+ $parts[] = $this->canonical_uri();
+ $parts[] = ''; // $parts[] = $this->canonical_querystring();
+ $parts[] = implode("\n", $this->canonical_headers) . "\n";
+ $parts[] = implode(';', $this->signed_headers);
+ $parts[] = $this->hex16($this->hash($this->body));
+
+ $this->canonical_request = implode("\n", $parts);
+
+ return $this->canonical_request;
+ }
+
+ /**
+ * The region ID to use in the signature.
+ *
+ * @return return The region ID.
+ */
+ protected function region()
+ {
+ $pieces = explode('.', $this->endpoint);
+
+ // Handle cases with single/no region (i.e. service.region.amazonaws.com vs. service.amazonaws.com)
+ if (count($pieces < 4))
+ {
+ return 'us-east-1';
+ }
+
+ return $pieces[1];
+ }
+
+ /**
+ * The service ID to use in the signature.
+ *
+ * @return return The service ID.
+ */
+ protected function service()
+ {
+ $pieces = explode('.', $this->endpoint);
+ return $pieces[0];
+ }
+
+ /**
+ * The request URI path.
+ *
+ * @return string The request URI path.
+ */
+ protected function canonical_uri()
+ {
+ return '/';
+ }
+
+ /**
+ * The canonical query string.
+ *
+ * @return string The canonical query string.
+ */
+ protected function canonical_querystring()
+ {
+ if (!isset($this->canonical_querystring))
+ {
+ $this->canonical_querystring = $this->util->to_signable_string($this->query);
+ }
+
+ return $this->canonical_querystring;
+ }
+
+ /**
+ * Hex16-pack the data.
+ *
+ * @param string $value (Required) The data to hex16 pack.
+ * @return string The hex16-packed data.
+ */
+ protected function hex16($value)
+ {
+ $result = unpack('H*', $value);
+ return reset($result);
+ }
+
+ /**
+ * Applies HMAC SHA-256 encryption to the string, salted by the key.
+ *
+ * @return string Raw HMAC SHA-256 hashed string.
+ */
+ protected function hmac($key, $string)
+ {
+ return hash_hmac('sha256', $string, $key, true);
+ }
+
+ /**
+ * SHA-256 hashes the string.
+ *
+ * @return string Raw SHA-256 hashed string.
+ */
+ protected function hash($string)
+ {
+ return hash('sha256', $string, true);
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signature_v4query.class.php b/3rdparty/aws-sdk/authentication/signature_v4query.class.php
new file mode 100644
index 00000000000..bd5a3fbf5b5
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signature_v4query.class.php
@@ -0,0 +1,345 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Implements support for Signature v4 (Query).
+ *
+ * @version 2011.01.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class AuthV4Query extends Signer implements Signable
+{
+ /**
+ * Constructs a new instance of the <AuthV4Query> class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ parent::__construct($endpoint, $operation, $payload, $credentials);
+ }
+
+ /**
+ * Generates a cURL handle with all of the required authentication bits set.
+ *
+ * @return resource A cURL handle ready for executing.
+ */
+ public function authenticate()
+ {
+ // Determine signing values
+ $current_time = time();
+ $timestamp = gmdate(CFUtilities::DATE_FORMAT_SIGV4, $current_time);
+
+ // Initialize
+ $x_amz_target = null;
+
+ $this->headers = array();
+ $this->signed_headers = array();
+ $this->canonical_headers = array();
+ $this->query = array('body' => is_array($this->payload) ? $this->payload : array());
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $this->headers['X-Amz-Security-Token'] = $this->auth_token;
+ $this->query['body']['SecurityToken'] = $this->auth_token;
+ }
+
+ // Manage the key-value pairs that are used in the query.
+ if (stripos($this->operation, 'x-amz-target') !== false)
+ {
+ $x_amz_target = trim(str_ireplace('x-amz-target:', '', $this->operation));
+ }
+ else
+ {
+ $this->query['body']['Action'] = $this->operation;
+ }
+
+ // Only add it if it exists.
+ if ($this->api_version)
+ {
+ $this->query['body']['Version'] = $this->api_version;
+ }
+
+ // Do a case-sensitive, natural order sort on the array keys.
+ uksort($this->query['body'], 'strcmp');
+
+ // Remove the default scheme from the domain.
+ $domain = str_replace(array('http://', 'https://'), '', $this->endpoint);
+
+ // Parse our request.
+ $parsed_url = parse_url('http://' . $domain);
+
+ // Set the proper host header.
+ if (isset($parsed_url['port']) && (integer) $parsed_url['port'] !== 80 && (integer) $parsed_url['port'] !== 443)
+ {
+ $host_header = strtolower($parsed_url['host']) . ':' . $parsed_url['port'];
+ }
+ else
+ {
+ $host_header = strtolower($parsed_url['host']);
+ }
+
+ // Generate the querystring from $this->query
+ $this->querystring = $this->util->to_query_string($this->query);
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Compose the request.
+ $request_url = ($this->use_ssl ? 'https://' : 'http://') . $domain;
+ $request_url .= !isset($parsed_url['path']) ? '/' : '';
+
+ // Instantiate the request class
+ $request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
+ $request->set_method('POST');
+ $request->set_body($this->canonical_querystring());
+ $this->querystring = $this->canonical_querystring();
+
+ $this->headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
+ $this->headers['X-Amz-Target'] = $x_amz_target;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Add authentication headers
+ $this->headers['X-Amz-Date'] = $timestamp;
+ $this->headers['Content-Length'] = strlen($this->querystring);
+ $this->headers['Content-MD5'] = $this->util->hex_to_base64(md5($this->querystring));
+ $this->headers['Host'] = $host_header;
+
+ // Sort headers
+ uksort($this->headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($this->headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ $request->add_header($header_key, $header_value);
+ $this->canonical_headers[] = strtolower($header_key) . ':' . $header_value;
+
+ $this->signed_headers[] = strtolower($header_key);
+ }
+
+ $this->headers['Authorization'] = $this->authorization($timestamp);
+
+ $request->add_header('Authorization', $this->headers['Authorization']);
+ $request->request_headers = $this->headers;
+
+ return $request;
+ }
+
+ /**
+ * Generates the authorization string to use for the request.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The authorization string.
+ */
+ protected function authorization($datetime)
+ {
+ $access_key_id = $this->key;
+
+ $parts = array();
+ $parts[] = "AWS4-HMAC-SHA256 Credential=${access_key_id}/" . $this->credential_string($datetime);
+ $parts[] = 'SignedHeaders=' . implode(';', $this->signed_headers);
+ $parts[] = 'Signature=' . $this->hex16($this->signature($datetime));
+
+ return implode(',', $parts);
+ }
+
+ /**
+ * Calculate the signature.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The signature.
+ */
+ protected function signature($datetime)
+ {
+ $k_date = $this->hmac('AWS4' . $this->secret_key, substr($datetime, 0, 8));
+ $k_region = $this->hmac($k_date, $this->region());
+ $k_service = $this->hmac($k_region, $this->service());
+ $k_credentials = $this->hmac($k_service, 'aws4_request');
+ $signature = $this->hmac($k_credentials, $this->string_to_sign($datetime));
+
+ return $signature;
+ }
+
+ /**
+ * Calculate the string to sign.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The string to sign.
+ */
+ protected function string_to_sign($datetime)
+ {
+ $parts = array();
+ $parts[] = 'AWS4-HMAC-SHA256';
+ $parts[] = $datetime;
+ $parts[] = $this->credential_string($datetime);
+ $parts[] = $this->hex16($this->hash($this->canonical_request()));
+
+ $this->string_to_sign = implode("\n", $parts);
+
+ return $this->string_to_sign;
+ }
+
+ /**
+ * Generates the credential string to use for signing.
+ *
+ * @param string $datetime (Required) The current timestamp.
+ * @return string The credential string.
+ */
+ protected function credential_string($datetime)
+ {
+ $parts = array();
+ $parts[] = substr($datetime, 0, 8);
+ $parts[] = $this->region();
+ $parts[] = $this->service();
+ $parts[] = 'aws4_request';
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Calculate the canonical request.
+ *
+ * @return string The canonical request.
+ */
+ protected function canonical_request()
+ {
+ $parts = array();
+ $parts[] = 'POST';
+ $parts[] = $this->canonical_uri();
+ $parts[] = ''; // $parts[] = $this->canonical_querystring();
+ $parts[] = implode("\n", $this->canonical_headers) . "\n";
+ $parts[] = implode(';', $this->signed_headers);
+ $parts[] = $this->hex16($this->hash($this->canonical_querystring()));
+
+ $this->canonical_request = implode("\n", $parts);
+
+ return $this->canonical_request;
+ }
+
+ /**
+ * The region ID to use in the signature.
+ *
+ * @return return The region ID.
+ */
+ protected function region()
+ {
+ $pieces = explode('.', $this->endpoint);
+
+ // Handle cases with single/no region (i.e. service.region.amazonaws.com vs. service.amazonaws.com)
+ if (count($pieces < 4))
+ {
+ return 'us-east-1';
+ }
+
+ return $pieces[1];
+ }
+
+ /**
+ * The service ID to use in the signature.
+ *
+ * @return return The service ID.
+ */
+ protected function service()
+ {
+ $pieces = explode('.', $this->endpoint);
+ return ($pieces[0] === 'email') ? 'ses' : $pieces[0];
+ }
+
+ /**
+ * The request URI path.
+ *
+ * @return string The request URI path.
+ */
+ protected function canonical_uri()
+ {
+ return '/';
+ }
+
+ /**
+ * The canonical query string.
+ *
+ * @return string The canonical query string.
+ */
+ protected function canonical_querystring()
+ {
+ if (!isset($this->canonical_querystring))
+ {
+ $this->canonical_querystring = $this->util->to_signable_string($this->query['body']);
+ }
+
+ return $this->canonical_querystring;
+ }
+
+ /**
+ * Hex16-pack the data.
+ *
+ * @param string $value (Required) The data to hex16 pack.
+ * @return string The hex16-packed data.
+ */
+ protected function hex16($value)
+ {
+ $result = unpack('H*', $value);
+ return reset($result);
+ }
+
+ /**
+ * Applies HMAC SHA-256 encryption to the string, salted by the key.
+ *
+ * @return string Raw HMAC SHA-256 hashed string.
+ */
+ protected function hmac($key, $string)
+ {
+ return hash_hmac('sha256', $string, $key, true);
+ }
+
+ /**
+ * SHA-256 hashes the string.
+ *
+ * @return string Raw SHA-256 hashed string.
+ */
+ protected function hash($string)
+ {
+ return hash('sha256', $string, true);
+ }
+}
diff --git a/3rdparty/aws-sdk/authentication/signer.abstract.php b/3rdparty/aws-sdk/authentication/signer.abstract.php
new file mode 100644
index 00000000000..f6bf7912f7b
--- /dev/null
+++ b/3rdparty/aws-sdk/authentication/signer.abstract.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The abstract class that serves as the base class that signer classes extend.
+ *
+ * @version 2011.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+abstract class Signer
+{
+ /**
+ * The endpoint to direct the request to.
+ */
+ public $endpoint;
+
+ /**
+ * The operation to execute as a result of this request.
+ */
+ public $operation;
+
+ /**
+ * The options to use as part of the payload in the request.
+ */
+ public $payload;
+
+ /**
+ * The credentials to use for signing and making requests.
+ */
+ public $credentials;
+
+
+ /**
+ * Constructs a new instance of the implementing class.
+ *
+ * @param string $endpoint (Required) The endpoint to direct the request to.
+ * @param string $operation (Required) The operation to execute as a result of this request.
+ * @param array $payload (Required) The options to use as part of the payload in the request.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return void
+ */
+ public function __construct($endpoint, $operation, $payload, CFCredential $credentials)
+ {
+ $this->endpoint = $endpoint;
+ $this->operation = $operation;
+ $this->payload = $payload;
+ $this->credentials = $credentials;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/cachecore/LICENSE b/3rdparty/aws-sdk/lib/cachecore/LICENSE
new file mode 100755
index 00000000000..49b38bd620a
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. 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 Ryan Parman, Foleeo Inc. 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 HOLDERS
+AND 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/aws-sdk/lib/cachecore/README b/3rdparty/aws-sdk/lib/cachecore/README
new file mode 100755
index 00000000000..07e00267cbb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/README
@@ -0,0 +1 @@
+A simple caching system for PHP5 that provides a single interface for a variety of storage types.
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/README b/3rdparty/aws-sdk/lib/cachecore/_sql/README
new file mode 100755
index 00000000000..e25d53d1208
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/README
@@ -0,0 +1,5 @@
+The .sql files in this directory contain the code to create the tables for database caching.
+
+If you're not using database caching, you can safely ignore these.
+
+If you ARE using database caching, simply load the correct *.sql file into your database to set up the required tables.
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql
new file mode 100755
index 00000000000..2efee3a732f
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/mysql.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `cache` (
+ `id` char(40) NOT NULL default '',
+ `expires` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ `data` longtext,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql
new file mode 100755
index 00000000000..f2bdd86a528
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/pgsql.sql
@@ -0,0 +1,6 @@
+CREATE TABLE "cache" (
+ expires timestamp without time zone NOT NULL,
+ id character(40) NOT NULL,
+ data text NOT NULL
+)
+WITH (OIDS=TRUE); \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql b/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql
new file mode 100755
index 00000000000..590f45e4ff1
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/_sql/sqlite3.sql
@@ -0,0 +1,2 @@
+CREATE TABLE cache (id TEXT, expires NUMERIC, data BLOB);
+CREATE UNIQUE INDEX idx ON cache(id ASC); \ No newline at end of file
diff --git a/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php b/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php
new file mode 100755
index 00000000000..59f5e88f397
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cacheapc.class.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Container for all APC-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/apc APC
+ */
+class CacheAPC extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return apc_add($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($data = apc_fetch($this->id))
+ {
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return apc_store($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return apc_delete($this->id);
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. APC manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheAPC_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php b/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php
new file mode 100755
index 00000000000..1670d316408
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachecore.class.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Container for all shared caching methods. This is not intended to be instantiated directly, but is
+ * extended by the cache-specific classes.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+class CacheCore
+{
+ /**
+ * A name to uniquely identify the cache object by.
+ */
+ var $name;
+
+ /**
+ * Where to store the cache.
+ */
+ var $location;
+
+ /**
+ * The number of seconds before a cache object is considered stale.
+ */
+ var $expires;
+
+ /**
+ * Used internally to uniquely identify the location + name of the cache object.
+ */
+ var $id;
+
+ /**
+ * Stores the time when the cache object was created.
+ */
+ var $timestamp;
+
+ /**
+ * Stores whether or not the content should be gzipped when stored
+ */
+ var $gzip;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ if (!extension_loaded('zlib'))
+ {
+ $gzip = false;
+ }
+
+ $this->name = $name;
+ $this->location = $location;
+ $this->expires = $expires;
+ $this->gzip = $gzip;
+
+ return $this;
+ }
+
+ /**
+ * Allows for chaining from the constructor. Requires PHP 5.3 or newer.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public static function init($name, $location = null, $expires = 0, $gzip = true)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to use CacheCore::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($name, $location, $expires, $gzip);
+ }
+
+ /**
+ * Set the number of seconds until a cache expires.
+ *
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @return $this
+ */
+ public function expire_in($seconds)
+ {
+ $this->expires = $seconds;
+ return $this;
+ }
+
+ /**
+ * Provides a simple, straightforward cache-logic mechanism. Useful for non-complex response caches.
+ *
+ * @param string|function $callback (Required) The name of the function to fire when we need to fetch new data to cache.
+ * @param array params (Optional) Parameters to pass into the callback function, as an array.
+ * @return array The cached data being requested.
+ */
+ public function response_manager($callback, $params = null)
+ {
+ // Automatically handle $params values.
+ $params = is_array($params) ? $params : array($params);
+
+ if ($data = $this->read())
+ {
+ if ($this->is_expired())
+ {
+ if ($data = call_user_func_array($callback, $params))
+ {
+ $this->update($data);
+ }
+ else
+ {
+ $this->reset();
+ $data = $this->read();
+ }
+ }
+ }
+ else
+ {
+ if ($data = call_user_func_array($callback, $params))
+ {
+ $this->create($data);
+ }
+ }
+
+ return $data;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// CORE DEPENDENCIES
+
+// Include the ICacheCore interface.
+if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'icachecore.interface.php'))
+{
+ include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'icachecore.interface.php';
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheCore_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php b/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php
new file mode 100755
index 00000000000..3df240151fb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachefile.class.php
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Container for all file-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+class CacheFile extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, $location, $expires, $gzip);
+ $this->id = $this->location . '/' . $this->name . '.cache';
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ if (file_exists($this->id))
+ {
+ return false;
+ }
+ elseif (realpath($this->location) && file_exists($this->location) && is_writeable($this->location))
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return (bool) file_put_contents($this->id, $data);
+ }
+ elseif (realpath($this->location) && file_exists($this->location))
+ {
+ throw new CacheFile_Exception('The file system location "' . $this->location . '" is not writable. Check the file system permissions for this directory.');
+ }
+ else
+ {
+ throw new CacheFile_Exception('The file system location "' . $this->location . '" does not exist. Create the directory, or double-check any relative paths that may have been set.');
+ }
+
+ return false;
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if (file_exists($this->id) && is_readable($this->id))
+ {
+ $data = file_get_contents($this->id);
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ $data = unserialize($data);
+
+ if ($data === false)
+ {
+ /*
+ This should only happen when someone changes the gzip settings and there is
+ existing data or someone has been mucking about in the cache folder manually.
+ Delete the bad entry since the file cache doesn't clean up after itself and
+ then return false so fresh data will be retrieved.
+ */
+ $this->delete();
+ return false;
+ }
+
+ return $data;
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ if (file_exists($this->id) && is_writeable($this->id))
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return (bool) file_put_contents($this->id, $data);
+ }
+ else
+ {
+ throw new CacheFile_Exception('The file system location is not writeable. Check your file system permissions and ensure that the cache directory exists.');
+ }
+
+ return false;
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ if (file_exists($this->id))
+ {
+ return unlink($this->id);
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ if ($this->timestamp() + $this->expires < time())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ clearstatcache();
+
+ if (file_exists($this->id))
+ {
+ $this->timestamp = filemtime($this->id);
+ return $this->timestamp;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ if (file_exists($this->id))
+ {
+ return touch($this->id);
+ }
+
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheFile_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php b/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php
new file mode 100755
index 00000000000..5b0f8a93061
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachemc.class.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Container for all Memcache-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/memcache Memcache
+ * @link http://php.net/memcached Memcached
+ */
+class CacheMC extends CacheCore implements ICacheCore
+{
+ /**
+ * Holds the Memcache object.
+ */
+ var $memcache = null;
+
+ /**
+ * Whether the Memcached extension is being used (as opposed to Memcache).
+ */
+ var $is_memcached = false;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+
+ // Prefer Memcached over Memcache.
+ if (class_exists('Memcached'))
+ {
+ $this->memcache = new Memcached();
+ $this->is_memcached = true;
+ }
+ elseif (class_exists('Memcache'))
+ {
+ $this->memcache = new Memcache();
+ }
+ else
+ {
+ return false;
+ }
+
+ // Enable compression, if available
+ if ($this->gzip)
+ {
+ if ($this->is_memcached)
+ {
+ $this->memcache->setOption(Memcached::OPT_COMPRESSION, true);
+ }
+ else
+ {
+ $this->gzip = MEMCACHE_COMPRESSED;
+ }
+ }
+
+ // Process Memcached servers.
+ if (isset($location) && sizeof($location) > 0)
+ {
+ foreach ($location as $loc)
+ {
+ if (isset($loc['port']) && !empty($loc['port']))
+ {
+ $this->memcache->addServer($loc['host'], $loc['port']);
+ }
+ else
+ {
+ $this->memcache->addServer($loc['host'], 11211);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->set($this->id, $data, $this->expires);
+ }
+ return $this->memcache->set($this->id, $data, $this->gzip, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->get($this->id);
+ }
+ return $this->memcache->get($this->id, $this->gzip);
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ if ($this->is_memcached)
+ {
+ return $this->memcache->replace($this->id, $data, $this->expires);
+ }
+ return $this->memcache->replace($this->id, $data, $this->gzip, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return $this->memcache->delete($this->id);
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. Memcache manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheMC_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php b/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php
new file mode 100755
index 00000000000..5716021d8fc
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachepdo.class.php
@@ -0,0 +1,297 @@
+<?php
+/**
+ * Container for all PDO-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://php.net/pdo PDO
+ */
+class CachePDO extends CacheCore implements ICacheCore
+{
+ /**
+ * Reference to the PDO connection object.
+ */
+ var $pdo = null;
+
+ /**
+ * Holds the parsed URL components.
+ */
+ var $dsn = null;
+
+ /**
+ * Holds the PDO-friendly version of the connection string.
+ */
+ var $dsn_string = null;
+
+ /**
+ * Holds the prepared statement for creating an entry.
+ */
+ var $create = null;
+
+ /**
+ * Holds the prepared statement for reading an entry.
+ */
+ var $read = null;
+
+ /**
+ * Holds the prepared statement for updating an entry.
+ */
+ var $update = null;
+
+ /**
+ * Holds the prepared statement for resetting the expiry of an entry.
+ */
+ var $reset = null;
+
+ /**
+ * Holds the prepared statement for deleting an entry.
+ */
+ var $delete = null;
+
+ /**
+ * Holds the response of the read so we only need to fetch it once instead of doing
+ * multiple queries.
+ */
+ var $store_read = null;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * Tested with [MySQL 5.0.x](http://mysql.com), [PostgreSQL](http://postgresql.com), and
+ * [SQLite 3.x](http://sqlite.org). SQLite 2.x is assumed to work. No other PDO-supported databases have
+ * been tested (e.g. Oracle, Microsoft SQL Server, IBM DB2, ODBC, Sybase, Firebird). Feel free to send
+ * patches for additional database support.
+ *
+ * See <http://php.net/pdo> for more information.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ // Make sure the name is no longer than 40 characters.
+ $name = sha1($name);
+
+ // Call parent constructor and set id.
+ parent::__construct($name, $location, $expires, $gzip);
+ $this->id = $this->name;
+ $options = array();
+
+ // Check if the location contains :// (e.g. mysql://user:pass@hostname:port/table)
+ if (stripos($location, '://') === false)
+ {
+ // No? Just pass it through.
+ $this->dsn = parse_url($location);
+ $this->dsn_string = $location;
+ }
+ else
+ {
+ // Yes? Parse and set the DSN
+ $this->dsn = parse_url($location);
+ $this->dsn_string = $this->dsn['scheme'] . ':host=' . $this->dsn['host'] . ((isset($this->dsn['port'])) ? ';port=' . $this->dsn['port'] : '') . ';dbname=' . substr($this->dsn['path'], 1);
+ }
+
+ // Make sure that user/pass are defined.
+ $user = isset($this->dsn['user']) ? $this->dsn['user'] : null;
+ $pass = isset($this->dsn['pass']) ? $this->dsn['pass'] : null;
+
+ // Set persistence for databases that support it.
+ switch ($this->dsn['scheme'])
+ {
+ case 'mysql': // MySQL
+ case 'pgsql': // PostgreSQL
+ $options[PDO::ATTR_PERSISTENT] = true;
+ break;
+ }
+
+ // Instantiate a new PDO object with a persistent connection.
+ $this->pdo = new PDO($this->dsn_string, $user, $pass, $options);
+
+ // Define prepared statements for improved performance.
+ $this->create = $this->pdo->prepare("INSERT INTO cache (id, expires, data) VALUES (:id, :expires, :data)");
+ $this->read = $this->pdo->prepare("SELECT id, expires, data FROM cache WHERE id = :id");
+ $this->reset = $this->pdo->prepare("UPDATE cache SET expires = :expires WHERE id = :id");
+ $this->delete = $this->pdo->prepare("DELETE FROM cache WHERE id = :id");
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ $this->create->bindParam(':id', $this->id);
+ $this->create->bindParam(':data', $data);
+ $this->create->bindParam(':expires', $this->generate_timestamp());
+
+ return (bool) $this->create->execute();
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if (!$this->store_read)
+ {
+ $this->read->bindParam(':id', $this->id);
+ $this->read->execute();
+ $this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
+ }
+
+ if ($this->store_read)
+ {
+ $data = $this->store_read['data'];
+ $data = $this->gzip ? gzuncompress($data) : $data;
+
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $this->delete();
+ return $this->create($data);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ $this->delete->bindParam(':id', $this->id);
+ return $this->delete->execute();
+ }
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ if ($this->timestamp() + $this->expires < time())
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ if (!$this->store_read)
+ {
+ $this->read->bindParam(':id', $this->id);
+ $this->read->execute();
+ $this->store_read = $this->read->fetch(PDO::FETCH_ASSOC);
+ }
+
+ if ($this->store_read)
+ {
+ $value = $this->store_read['expires'];
+
+ // If 'expires' isn't yet an integer, convert it into one.
+ if (!is_numeric($value))
+ {
+ $value = strtotime($value);
+ }
+
+ $this->timestamp = date('U', $value);
+ return $this->timestamp;
+ }
+
+ return false;
+ }
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ $this->reset->bindParam(':id', $this->id);
+ $this->reset->bindParam(':expires', $this->generate_timestamp());
+ return (bool) $this->reset->execute();
+ }
+
+ /**
+ * Returns a list of supported PDO database drivers. Identical to <PDO::getAvailableDrivers()>.
+ *
+ * @return array The list of supported database drivers.
+ * @link http://php.net/pdo.getavailabledrivers PHP Method
+ */
+ public function get_drivers()
+ {
+ return PDO::getAvailableDrivers();
+ }
+
+ /**
+ * Returns a timestamp value apropriate to the current database type.
+ *
+ * @return mixed Timestamp for MySQL and PostgreSQL, integer value for SQLite.
+ */
+ protected function generate_timestamp()
+ {
+ // Define 'expires' settings differently.
+ switch ($this->dsn['scheme'])
+ {
+ // These support timestamps.
+ case 'mysql': // MySQL
+ case 'pgsql': // PostgreSQL
+ $expires = date(DATE_FORMAT_MYSQL, time());
+ break;
+
+ // These support integers.
+ case 'sqlite': // SQLite 3
+ case 'sqlite2': // SQLite 2
+ $expires = time();
+ break;
+ }
+
+ return $expires;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CachePDO_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php b/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php
new file mode 100755
index 00000000000..a0f279aaea3
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/cachexcache.class.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Container for all XCache-based cache methods. Inherits additional methods from <CacheCore>. Adheres
+ * to the ICacheCore interface.
+ *
+ * @version 2012.04.17
+ * @copyright 2006-2012 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2012 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ * @link http://xcache.lighttpd.net XCache
+ */
+class CacheXCache extends CacheCore implements ICacheCore
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $name (Required) A name to uniquely identify the cache object.
+ * @param string $location (Optional) The location to store the cache object in. This may vary by cache method. The default value is NULL.
+ * @param integer $expires (Optional) The number of seconds until a cache object is considered stale. The default value is 0.
+ * @param boolean $gzip (Optional) Whether data should be gzipped before being stored. The default value is true.
+ * @return object Reference to the cache object.
+ */
+ public function __construct($name, $location = null, $expires = 0, $gzip = true)
+ {
+ parent::__construct($name, null, $expires, $gzip);
+ $this->id = $this->name;
+ }
+
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return xcache_set($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read()
+ {
+ if ($data = xcache_get($this->id))
+ {
+ $data = $this->gzip ? gzuncompress($data) : $data;
+ return unserialize($data);
+ }
+
+ return false;
+ }
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data)
+ {
+ $data = serialize($data);
+ $data = $this->gzip ? gzcompress($data) : $data;
+
+ return xcache_set($this->id, $data, $this->expires);
+ }
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete()
+ {
+ return xcache_unset($this->id);
+ }
+
+ /**
+ * Defined here, but always returns false. XCache manages it's own expirations. It's worth
+ * mentioning that if the server is configured for a long xcache.var_gc_interval then it IS
+ * possible for expired data to remain in the var cache, though it is not possible to access
+ * it.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. XCache manages its own expirations.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp()
+ {
+ return false;
+ }
+
+ /**
+ * Implemented here, but always returns `false`. XCache manages its own expirations.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset()
+ {
+ return false;
+ }
+}
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+class CacheXCache_Exception extends CacheCore_Exception {}
diff --git a/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php b/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php
new file mode 100755
index 00000000000..8d49f5bf492
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/cachecore/icachecore.interface.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Defines the methods that all implementing classes MUST have. Covers CRUD (create, read, update,
+ * delete) methods, as well as others that are used in the base <CacheCore> class.
+ *
+ * @version 2009.03.22
+ * @copyright 2006-2010 Ryan Parman
+ * @copyright 2006-2010 Foleeo, Inc.
+ * @copyright 2008-2010 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ * @link http://github.com/skyzyx/cachecore CacheCore
+ * @link http://getcloudfusion.com CloudFusion
+ */
+interface ICacheCore
+{
+ /**
+ * Creates a new cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function create($data);
+
+ /**
+ * Reads a cache.
+ *
+ * @return mixed Either the content of the cache object, or boolean `false`.
+ */
+ public function read();
+
+ /**
+ * Updates an existing cache.
+ *
+ * @param mixed $data (Required) The data to cache.
+ * @return boolean Whether the operation was successful.
+ */
+ public function update($data);
+
+ /**
+ * Deletes a cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function delete();
+
+ /**
+ * Checks whether the cache object is expired or not.
+ *
+ * @return boolean Whether the cache is expired or not.
+ */
+ public function is_expired();
+
+ /**
+ * Retrieves the timestamp of the cache.
+ *
+ * @return mixed Either the Unix time stamp of the cache creation, or boolean `false`.
+ */
+ public function timestamp();
+
+ /**
+ * Resets the freshness of the cache.
+ *
+ * @return boolean Whether the operation was successful.
+ */
+ public function reset();
+}
diff --git a/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php b/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php
new file mode 100644
index 00000000000..06ad502eebb
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/dom/ArrayToDOMDocument.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * @author Omer Hassan
+ * @author Ryan Parman
+ * @license MIT
+ */
+class Array2DOM
+{
+ const ATTRIBUTES = '__attributes__';
+ const CONTENT = '__content__';
+
+ /**
+ * @param array $source
+ * @param string $rootTagName
+ * @return DOMDocument
+ */
+ public static function arrayToDOMDocument(array $source, $rootTagName = 'root')
+ {
+ $document = new DOMDocument();
+ $document->appendChild(self::createDOMElement($source, $rootTagName, $document));
+
+ return $document;
+ }
+
+ /**
+ * @param array $source
+ * @param string $rootTagName
+ * @param bool $formatOutput
+ * @return string
+ */
+ public static function arrayToXMLString(array $source, $rootTagName = 'root', $formatOutput = true)
+ {
+ $document = self::arrayToDOMDocument($source, $rootTagName);
+ $document->formatOutput = $formatOutput;
+
+ return $document->saveXML();
+ }
+
+ /**
+ * @param DOMDocument $document
+ * @return array
+ */
+ public static function domDocumentToArray(DOMDocument $document)
+ {
+ return self::createArray($document->documentElement);
+ }
+
+ /**
+ * @param string $xmlString
+ * @return array
+ */
+ public static function xmlStringToArray($xmlString)
+ {
+ $document = new DOMDocument();
+
+ return $document->loadXML($xmlString) ? self::domDocumentToArray($document) : array();
+ }
+
+ /**
+ * @param mixed $source
+ * @param string $tagName
+ * @param DOMDocument $document
+ * @return DOMNode
+ */
+ private static function createDOMElement($source, $tagName, DOMDocument $document)
+ {
+ if (!is_array($source))
+ {
+ $element = $document->createElement($tagName);
+ $element->appendChild($document->createCDATASection($source));
+
+ return $element;
+ }
+
+ $element = $document->createElement($tagName);
+
+ foreach ($source as $key => $value)
+ {
+ if (is_string($key) && !is_numeric($key))
+ {
+ if ($key === self::ATTRIBUTES)
+ {
+ foreach ($value as $attributeName => $attributeValue)
+ {
+ $element->setAttribute($attributeName, $attributeValue);
+ }
+ }
+ elseif ($key === self::CONTENT)
+ {
+ $element->appendChild($document->createCDATASection($value));
+ }
+ elseif (is_string($value) && !is_numeric($value))
+ {
+ $element->appendChild(self::createDOMElement($value, $key, $document));
+ }
+ elseif (is_array($value) && count($value))
+ {
+ $keyNode = $document->createElement($key);
+
+ foreach ($value as $elementKey => $elementValue)
+ {
+ if (is_string($elementKey) && !is_numeric($elementKey))
+ {
+ $keyNode->appendChild(self::createDOMElement($elementValue, $elementKey, $document));
+ }
+ else
+ {
+ $element->appendChild(self::createDOMElement($elementValue, $key, $document));
+ }
+ }
+
+ if ($keyNode->hasChildNodes())
+ {
+ $element->appendChild($keyNode);
+ }
+ }
+ else
+ {
+ if (is_bool($value))
+ {
+ $value = $value ? 'true' : 'false';
+ }
+
+ $element->appendChild(self::createDOMElement($value, $key, $document));
+ }
+ }
+ else
+ {
+ $element->appendChild(self::createDOMElement($value, $tagName, $document));
+ }
+ }
+
+ return $element;
+ }
+
+ /**
+ * @param DOMNode $domNode
+ * @return array
+ */
+ private static function createArray(DOMNode $domNode)
+ {
+ $array = array();
+
+ for ($i = 0; $i < $domNode->childNodes->length; $i++)
+ {
+ $item = $domNode->childNodes->item($i);
+
+ if ($item->nodeType === XML_ELEMENT_NODE)
+ {
+ $arrayElement = array();
+
+ for ($attributeIndex = 0; !is_null($attribute = $item->attributes->item($attributeIndex)); $attributeIndex++)
+ {
+ if ($attribute->nodeType === XML_ATTRIBUTE_NODE)
+ {
+ $arrayElement[self::ATTRIBUTES][$attribute->nodeName] = $attribute->nodeValue;
+ }
+ }
+
+ $children = self::createArray($item);
+
+ if (is_array($children))
+ {
+ $arrayElement = array_merge($arrayElement, $children);
+ }
+ else
+ {
+ $arrayElement[self::CONTENT] = $children;
+ }
+
+ $array[$item->nodeName][] = $arrayElement;
+ }
+ elseif ($item->nodeType === XML_CDATA_SECTION_NODE || ($item->nodeType === XML_TEXT_NODE && trim($item->nodeValue) !== ''))
+ {
+ return $item->nodeValue;
+ }
+ }
+
+ return $array;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/requestcore/LICENSE b/3rdparty/aws-sdk/lib/requestcore/LICENSE
new file mode 100755
index 00000000000..49b38bd620a
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. 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 Ryan Parman, Foleeo Inc. 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 HOLDERS
+AND 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/aws-sdk/lib/requestcore/README.md b/3rdparty/aws-sdk/lib/requestcore/README.md
new file mode 100755
index 00000000000..373ea4dccad
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/README.md
@@ -0,0 +1,15 @@
+# RequestCore
+
+RequestCore is a lightweight cURL-based HTTP request/response class that leverages MultiCurl for parallel requests.
+
+### PEAR HTTP_Request?
+
+RequestCore was written as a replacement for [PEAR HTTP_Request](http://pear.php.net/http_request/). While PEAR HTTP_Request is full-featured and heavy, RequestCore features only the essentials and is very lightweight. It also leverages the batch request support in cURL's `curl_multi_exec()` to enable multi-threaded requests that fire in parallel.
+
+### Reference and Download
+
+You can find the class reference at <http://skyzyx.github.com/requestcore/>. You can get the code from <http://github.com/skyzyx/requestcore>.
+
+### License and Copyright
+
+This code is Copyright (c) 2008-2010, Ryan Parman. However, I'm licensing this code for others to use under the [Simplified BSD license](http://www.opensource.org/licenses/bsd-license.php).
diff --git a/3rdparty/aws-sdk/lib/requestcore/cacert.pem b/3rdparty/aws-sdk/lib/requestcore/cacert.pem
new file mode 100755
index 00000000000..80bff62fd27
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/cacert.pem
@@ -0,0 +1,3390 @@
+##
+## ca-bundle.crt -- Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Wed Jan 18 00:04:16 2012
+##
+## This is a bundle of X.509 certificates of public Certificate Authorities
+## (CA). These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the mozilla source tree:
+## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
+##
+## It contains the certificates in PEM format and therefore
+## can be directly used with curl / libcurl / php_curl, or with
+## an Apache+mod_ssl webserver for SSL client authentication.
+## Just configure this file as the SSLCACertificateFile.
+##
+
+# ***** 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 Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# 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 *****
+# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.81 $ $Date: 2012/01/17 22:02:37 $
+
+GTE CyberTrust Global Root
+==========================
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
+Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
+A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
+MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
+Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
+IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
+sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
+HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
+AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
+M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
+NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
+
+Thawte Server CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
+AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
+b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
+BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
+c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
+A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
+ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
+/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
+1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
+GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
+GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
+-----END CERTIFICATE-----
+
+Thawte Premium Server CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
+AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
+ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
+AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
+VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
+aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
+cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
+aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
+Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
+qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
+SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
+8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
+UCemDaYj+bvLpgcUQg==
+-----END CERTIFICATE-----
+
+Equifax Secure CA
+=================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
+ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
+B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
+fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
+8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
+A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
+CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
+A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
+spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
+Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
+zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
+BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
+70+sB3c4
+-----END CERTIFICATE-----
+
+Digital Signature Trust Co. Global CA 1
+=======================================
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
+ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy
+MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
+IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE
+NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i
+o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
+BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
+dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
+IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY
+MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM
+BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
+ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq
+kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4
+RbyhkwS7hp86W0N6w4pl
+-----END CERTIFICATE-----
+
+Digital Signature Trust Co. Global CA 3
+=======================================
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
+ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy
+MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
+IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD
+VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS
+xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
+BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
+dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
+IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY
+MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM
+BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
+AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi
+up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1
+mPnHfxsb1gYgAlihw6ID
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA
+TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah
+WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf
+Tqj/ZA1k
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G2
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO
+FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71
+lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT
+1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD
+Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9
+-----END CERTIFICATE-----
+
+GlobalSign Root CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
+GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
+b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
+VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
+DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
+THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
+Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
+c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
+gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
+AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
+Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
+j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
+hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
+X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
+ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
+s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
+S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
+TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
+ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
+YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
+BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
+9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
+01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
+9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+ValiCert Class 1 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy
+MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi
+GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm
+DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG
+lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX
+icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP
+Orf1LXLI
+-----END CERTIFICATE-----
+
+ValiCert Class 2 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC
+CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf
+ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ
+SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV
+UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8
+W9ViH0Pd
+-----END CERTIFICATE-----
+
+RSA Root Certificate 1
+======================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td
+3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H
+BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs
+3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF
+V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r
+on+jjBXu
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
+EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
+cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
+EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
+055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
+j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
+xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
+t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+Verisign Class 4 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS
+tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM
+8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW
+Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX
+Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt
+mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd
+RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG
+UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+
+Entrust.net Secure Server CA
+============================
+-----BEGIN CERTIFICATE-----
+MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV
+BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg
+cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl
+ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG
+A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi
+eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p
+dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ
+aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5
+gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw
+ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw
+CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l
+dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
+bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
+dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw
+NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow
+HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA
+BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN
+Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9
+n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
+-----END CERTIFICATE-----
+
+Entrust.net Premium 2048 Secure Server CA
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
+ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
+bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
+BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
+NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
+d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
+MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
+ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
+Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
+hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
+nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
+VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC
+AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER
+gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B
+AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
+oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS
+o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z
+2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX
+OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==
+-----END CERTIFICATE-----
+
+Baltimore CyberTrust Root
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
+ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
+ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
+SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
+dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
+uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
+UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
+G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
+XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
+l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
+VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
+BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
+cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
+hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
+Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
+RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+Equifax Secure Global eBusiness CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp
+bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx
+HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds
+b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV
+PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN
+qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn
+hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs
+MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN
+I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY
+NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+
+Equifax Secure eBusiness CA 1
+=============================
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB
+LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE
+ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz
+IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ
+1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a
+IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk
+MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW
+Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF
+AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5
+lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+
+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+
+Equifax Secure eBusiness CA 2
+=============================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE
+ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y
+MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT
+DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn
+2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5
+BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG
+A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx
+JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG
+A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e
+uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB
+Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1
+jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia
+78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm
+V+GRMOrN
+-----END CERTIFICATE-----
+
+AddTrust Low-Value Services Root
+================================
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
+cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
+CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
+ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
+54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
+oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
+Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
+GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
+HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
+RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
+HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
+ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
+iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
+mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
+ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+
+AddTrust External Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
+VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
+NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
+cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
+Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
+Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
+aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
+2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
+7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
+VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
+VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
+j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
+e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
+G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+AddTrust Public Services Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
+cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
+BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
+dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
+nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
+d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
+Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
+HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
+A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
+A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
+JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
+Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
+EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+
+AddTrust Qualified Certificates Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
+cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
+CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
+IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
+64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
+KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
+L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
+wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
+MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
+BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
+azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
+GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
+RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
+iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
+b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
+A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
+MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
+MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
+Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
+dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
+A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
+Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
+j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
+rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
+MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
+hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
+Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
+v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
+W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
+tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+RSA Security 2048 v3
+====================
+-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK
+ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy
+MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb
+BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7
+Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb
+WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH
+KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP
++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E
+FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY
+v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj
+0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj
+VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395
+nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA
+pKnXwiJPZ9d37CAFYd4=
+-----END CERTIFICATE-----
+
+GeoTrust Global CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
+MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
+BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
+8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
+T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
+vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
+zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
+d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
+mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
+XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
+Mw==
+-----END CERTIFICATE-----
+
+GeoTrust Global CA 2
+====================
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
+MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
+NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
+LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
+Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
+HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
+K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
+srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
+ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
+OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
+x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
+H4z1Ir+rzoPz4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
+MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
+Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
+JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
+RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
+7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
+8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
+qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
+Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
+Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
+KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
+ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
+XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
+qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
+oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
+xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
+KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
+DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
+xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
+p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
+P/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA 2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
+MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
+SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
+DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
+j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
+JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
+QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
+WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
+20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
+ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
+SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
+8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
+BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
+4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
+A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
+Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
+pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
+FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
+gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
+X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG
+v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z
+DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh
+sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP
+8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z
+o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf
+GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF
+VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft
+3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g
+Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
+sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en
+fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8
+f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO
+qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN
+RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0
+gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn
+6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid
+FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6
+Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj
+B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op
+aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY
+T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p
++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg
+JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy
+zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO
+ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh
+1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf
+GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff
+Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP
+cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=
+-----END CERTIFICATE-----
+
+Visa eCommerce Root
+===================
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
+EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
+QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
+WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
+VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
+F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
+RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
+TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
+/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
+GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
+MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
+CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
+YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
+zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
+YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+Certum Root CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
+ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
+Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
+by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
+wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
+kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
+89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
+Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
+NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
+GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
+GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
+0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
+qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
+-----END CERTIFICATE-----
+
+Comodo AAA Services root
+========================
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
+MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
+c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
+BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
+C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
+i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
+Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
+Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
+Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
+BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
+cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
+LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
+7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
+8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
+12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+Comodo Secure Services root
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
+MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
+Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
+BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
+9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
+rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
+oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
+p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
+FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
+gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
+YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
+aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
+4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
+DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
+pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
+RR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+
+Comodo Trusted Services root
+============================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
+MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
+bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
+IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
+3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
+/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
+juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
+ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
+DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
+ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
+cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
+uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
+BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
+R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
+9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+
+QuoVadis Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
+ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
+MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
+cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
+EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
+J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
+F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
+YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
+AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
+PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
+ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
+MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
+YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
+ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
+Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
+BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
+FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
+tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
+fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
+LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
+gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
+5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
+5nrQNiOKSnQ2+Q==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+Security Communication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
+8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
+DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
+5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
+DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
+JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
+0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
+mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
+s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
+6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
+FL39vmwLAw==
+-----END CERTIFICATE-----
+
+Sonera Class 2 Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
+U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
+NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
+IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
+/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
+dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
+f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
+tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
+nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
+XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
+0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
+cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
+Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
+EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
+llpwrN9M
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA
+=============================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE
+ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w
+HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh
+bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt
+vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P
+jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca
+C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth
+vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6
+22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV
+HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v
+dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN
+BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR
+EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw
+MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y
+nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
+iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
+-----END CERTIFICATE-----
+
+TDC Internet Root CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE
+ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx
+NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu
+ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j
+xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL
+znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc
+5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6
+otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI
+AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM
+VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM
+MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC
+AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe
+UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G
+CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m
+gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
+2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb
+O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU
+Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l
+-----END CERTIFICATE-----
+
+TDC OCES Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE
+ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5
+MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH
+nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0
+zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV
+iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde
+dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO
+3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB
+5DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k
+ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm
+cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp
+Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x
+LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM
+MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm
+aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
+MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647
++RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6
+NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4
+A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc
+A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9
+AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1
+AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw==
+-----END CERTIFICATE-----
+
+UTN DATACorp SGC Root CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ
+BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa
+MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w
+HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy
+dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys
+raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo
+wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA
+9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv
+33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud
+DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9
+BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD
+LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3
+DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0
+I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx
+EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP
+DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI
+-----END CERTIFICATE-----
+
+UTN USERFirst Hardware Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
+BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
+OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
+eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
+ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
+wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
+tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
+i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
+Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
+gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
+lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
+UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
+BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
+XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
+lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
+iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
+nfhmqA==
+-----END CERTIFICATE-----
+
+Camerfirma Chambers of Commerce Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
+NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
+cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
+MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
+AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
+xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
+NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
+DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
+d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
+EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
+cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
+AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
+bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
+VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
+aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
+fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
+L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
+UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
+ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
+erfutGWaIZDgqtCYvDi1czyL+Nw=
+-----END CERTIFICATE-----
+
+Camerfirma Global Chambersign Root
+==================================
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
+NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
+YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
+MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
+ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
+1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
+by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
+6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
+8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
+BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
+aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
+Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
+aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
+ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
+bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
+PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
+gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
+PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
+IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
+t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
+-----END CERTIFICATE-----
+
+NetLock Notary (Class A) Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI
+EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j
+ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX
+DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH
+EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD
+VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz
+cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM
+D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ
+z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC
+/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7
+tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6
+4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG
+A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC
+Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv
+bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
+IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn
+LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0
+ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz
+IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh
+IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu
+b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh
+bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg
+Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp
+bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5
+ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP
+ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB
+CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr
+KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM
+8CgHrTwXZoi1/baI
+-----END CERTIFICATE-----
+
+NetLock Business (Class B) Root
+===============================
+-----BEGIN CERTIFICATE-----
+MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg
+VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD
+VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv
+bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg
+VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S
+o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr
+1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
+HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ
+RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh
+dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0
+ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv
+c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg
+YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
+c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz
+Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA
+bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl
+IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2
+YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj
+cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM
+43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR
+stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI
+-----END CERTIFICATE-----
+
+NetLock Express (Class C) Root
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD
+KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j
+ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z
+W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63
+euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw
+DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN
+RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn
+YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB
+IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i
+aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0
+ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
+ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo
+dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y
+emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k
+IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ
+UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg
+YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2
+xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW
+gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A==
+-----END CERTIFICATE-----
+
+XRamp Global CA Root
+====================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
+BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
+dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
+HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
+U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
+IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
+foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
+zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
+AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
+xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
+oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
+AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
+/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
+nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
+8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+Go Daddy Class 2 CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
+VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
+A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
+ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
+qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
+YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
+vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
+BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
+atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
+MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
+PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
+Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
+vZ8=
+-----END CERTIFICATE-----
+
+Starfield Class 2 CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
+U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
+MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
+A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
+SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
+bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
+JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
+epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
+F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
+MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
+hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
+bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
+afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
+PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
+KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
+QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority
+================================
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
+ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
+NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
+LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
+U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
+o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
+Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
+eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
+2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
+6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
+osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
+untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
+UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
+37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
+YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
+AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
+Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
+U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
+LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
+cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
+dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
+AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
+3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
+vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
+fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
+fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
+EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
+1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
+lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
+g14=
+-----END CERTIFICATE-----
+
+Taiwan GRCA
+===========
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
+EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
+DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
+dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
+w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
+BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
+1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
+htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
+J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
+Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
+B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
+O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
+lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
+HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
+09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
+Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
+Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
+D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
+DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
+Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
+7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
+CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
+-----END CERTIFICATE-----
+
+Firmaprofesional Root CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT
+GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp
+Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA
+ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL
+MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT
+OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2
+ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V
+j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH
+lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf
+3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8
+NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww
+KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG
+AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD
+ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
+u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf
+wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm
+7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG
+VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA=
+-----END CERTIFICATE-----
+
+Wells Fargo Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV
+BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
+MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl
+bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv
+MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX
+x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3
+E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5
+OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j
+sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj
+YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF
+BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD
+ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv
+m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R
+OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx
+x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023
+tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=
+-----END CERTIFICATE-----
+
+Swisscom Root CA 1
+==================
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
+EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
+dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
+MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
+aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
+MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
+NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
+AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
+b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
+7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
+cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
+WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
+haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
+MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
+BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
+MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
+jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
+MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
+VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
+vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
+OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
+1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
+nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
+x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
+NY6E0F/6MBr1mmz0DlP5OlvRHA==
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
+MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
+9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
+UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
+/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
+oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
+GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
+66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
+hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
+EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
+SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
+8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+DigiCert Global Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
+MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
+TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
+BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
+4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
+7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
+o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
+8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
+BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
+EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
+tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
+UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+DigiCert High Assurance EV Root CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
+KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
+MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
+MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
+Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
+Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
+OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
+MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
+NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
+h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
+Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
+JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
+V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
+myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
+mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
+-----END CERTIFICATE-----
+
+Certplus Class 2 Primary CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
+BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
+OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
+dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
+5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
+Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
+YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
+e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
+CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
+YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
+L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
+P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
+TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
+7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
+//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+DST Root CA X3
+==============
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
+ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
+DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
+cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
+rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
+UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
+xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
+utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
+MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
+dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
+GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
+RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
+fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+DST ACES CA X6
+==============
+-----BEGIN CERTIFICATE-----
+MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
+MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
+MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
+CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
+DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
+pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
+GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
+MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
+Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
+dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
+CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
+5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
+Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
+nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
+vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
+oKfN5XozNmr6mis=
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 1
+==============================================
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP
+MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
+acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx
+MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg
+U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB
+TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC
+aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX
+yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i
+Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ
+8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4
+W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME
+BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46
+sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE
+q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
+B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY
+nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
+QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN
+MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr
+dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G
+A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
+acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe
+LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI
+x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g
+QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr
+5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB
+AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt
+Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
+Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+
+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P
+9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5
+UrbnBEI=
+-----END CERTIFICATE-----
+
+SwissSign Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+SwissSign Silver CA - G2
+========================
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
+DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
+aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
+N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
+6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
+MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
+qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
+FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
+ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
+celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
+CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
+tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
+4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
+kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
+3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
+/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
+DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
+e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
+WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
+DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
+DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
+cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
+b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
+nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
+RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
+tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
+hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
+Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
+NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
+Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
+1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+thawte Primary Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
+MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
+SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
+KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
+FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
+oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
+1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
+q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
+aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
+afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
+AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
+uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
+jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
+z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G5
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
+biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
+dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
+j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
+Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
+Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
+fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
+Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
+SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
+KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
+Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
+ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+SecureTrust CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
+dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
+BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
+OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
+DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
+GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
+01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
+ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
+SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
+mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
+nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+Secure Global CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
+bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
+YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
+bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
+8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
+HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
+0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
+oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
+CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
+3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+COMODO Certification Authority
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
+MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
+T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
+xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
+4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
+1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
+rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
+AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
+OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
+IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
+-----END CERTIFICATE-----
+
+Network Solutions Certificate Authority
+=======================================
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
+EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
+IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
+MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
+jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
+aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
+crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
+/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
+AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
+bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
+A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
+4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
+GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
+ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+WellsSecure Public Root Certificate Authority
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
+F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
+NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
+MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
+bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
+VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
+iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
+i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
+bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
+K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
+AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
+cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
+lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
+i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
+GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
+K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
+bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
+qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
+E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
+tylv2G0xffX8oRAHh84vWdw+WNs=
+-----END CERTIFICATE-----
+
+COMODO ECC Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
+GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
+4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
+wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
+FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
+U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+IGC/A
+=====
+-----BEGIN CERTIFICATE-----
+MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD
+VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE
+Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy
+MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI
+EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT
+STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2
+TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW
+So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy
+HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd
+frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ
+tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB
+egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC
+iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK
+q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q
+MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
+Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI
+lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF
+0mBWWg==
+-----END CERTIFICATE-----
+
+Security Communication EV RootCA1
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
+BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
+Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
+/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
+WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
+ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
+bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
+9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
+iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
+Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
+mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
+T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GA CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
+BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
+A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
+bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
+VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
+IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
+IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
+Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
+Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
+d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
+/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
+LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
+MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
+okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
+BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
+EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
+MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
+dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
+GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
+d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
+oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
+QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
+PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
+MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
+IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
+VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
+LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
+dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
+AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
+4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
+AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
+egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
+Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
+PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
+c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
+cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
+IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
+WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
+MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
+MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
+Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
+HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
+nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
+aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
+86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
+yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
+S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
+-----END CERTIFICATE-----
+
+Certigna
+========
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
+EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
+MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
+Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
+XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
+GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
+ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
+DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
+Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
+tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
+BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
+SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
+hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
+PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
+1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+AC Ra\xC3\xADz Certic\xC3\xA1mara S.A.
+======================================
+-----BEGIN CERTIFICATE-----
+MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT
+AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg
+LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w
+HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+
+U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh
+IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN
+yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU
+2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3
+4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP
+2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm
+8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf
+HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa
+Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK
+5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b
+czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g
+ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF
+BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug
+cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf
+AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX
+EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v
+/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3
+MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4
+3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk
+eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f
+/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h
+RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU
+Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 2 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw
+MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw
+IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2
+xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ
+Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u
+SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G
+dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ
+KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj
+TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP
+JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk
+vQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 3 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw
+MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W
+yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo
+6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ
+uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk
+2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE
+O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8
+yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9
+IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal
+092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc
+5A==
+-----END CERTIFICATE-----
+
+TC TrustCenter Universal CA I
+=============================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
+IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN
+MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg
+VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw
+JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC
+qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv
+xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw
+ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O
+gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j
+BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG
+1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy
+vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3
+ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
+ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a
+7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
+-----END CERTIFICATE-----
+
+Deutsche Telekom Root CA 2
+==========================
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
+RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
+A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
+MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
+A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
+b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
+bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
+KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
+AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
+Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
+jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
+HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
+E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
+zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
+rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
+dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+ComSign Secured CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE
+AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w
+NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD
+QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs
+49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH
+7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB
+kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1
+9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw
+AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t
+U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA
+j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC
+AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a
+BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp
+FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP
+51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
+OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
+-----END CERTIFICATE-----
+
+Cybertrust Global Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
+ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
+MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
+ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
+0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
+AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
+89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
+8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
+MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
+A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
+lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
+5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
+hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
+X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+ePKI Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
+MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
+MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
+IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
+lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
+qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
+12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
+WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
+lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
+vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
+Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
+MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
+1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
+KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
+xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
+NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
+GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
+xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
+gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
+sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
+BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3
+=============================================================================================================================
+-----BEGIN CERTIFICATE-----
+MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
+DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
+aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
+b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
+BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
+S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
+MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
+IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
+n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
+IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
+dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
+cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
+Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
+xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
+6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
+hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
+BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
+N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
+y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
+LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
+dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
+-----END CERTIFICATE-----
+
+Buypass Class 2 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2
+MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M
+cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83
+0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4
+0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R
+uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV
+1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt
+7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2
+fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w
+wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
+-----END CERTIFICATE-----
+
+Buypass Class 3 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1
+MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx
+ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0
+n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia
+AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c
+1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7
+pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA
+EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5
+htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj
+el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
+-----END CERTIFICATE-----
+
+EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1
+==========================================================================
+-----BEGIN CERTIFICATE-----
+MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg
+QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe
+Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p
+ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt
+IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by
+X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b
+gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr
+eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ
+TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy
+Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn
+uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI
+qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm
+ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0
+Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW
+Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t
+FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm
+zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k
+XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT
+bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU
+RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK
+1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt
+2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ
+Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9
+AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT
+-----END CERTIFICATE-----
+
+certSIGN ROOT CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
+VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
+Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
+CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
+JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
+rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
+ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
+0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
+AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
+Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
+AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
+SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
+x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
+vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
+TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+CNNIC ROOT
+==========
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
+ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
+OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
+o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
+VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
+VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
+czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
+y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
+wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
+lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
+Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
+O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
+BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
+G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
+mxE=
+-----END CERTIFICATE-----
+
+ApplicationCA - Japanese Government
+===================================
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
+SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
+MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
+cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
+fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
+wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
+jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
+nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
+WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
+BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
+vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
+o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
+/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
+io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
+dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
+rosot4LKGAfmt1t06SAZf7IbiVQ=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G3
+=============================================
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
+NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
+YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
+LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
+K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
+c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
+IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
+dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
+2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
+cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
+Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
+t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
+VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
+IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
+Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
+MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
+b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
+IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
+LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
+8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
+G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
+rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
+ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
+VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
+A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
+P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
+7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
+vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
+KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
+A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
+8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
+er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
+Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
+OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
+b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
+BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
+KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
+EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
+ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
+npaqBA+K
+-----END CERTIFICATE-----
+
+VeriSign Universal Root Certification Authority
+===============================================
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
+1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
+MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
+9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
+AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
+tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
+CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
+a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
+Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
+Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
+P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
+wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
+mJO37M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G4
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
+VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
+b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
+ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
+cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
+b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
+Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
+rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
+HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
+Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
+A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
+AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+NetLock Arany (Class Gold) Főtanúsítvány
+============================================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
+A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
+dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
+cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
+MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
+ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
+c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
+0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
+/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
+H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
+fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
+neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
+qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
+YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
+NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
+dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA - G2
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
+5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
+vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
+CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
+e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
+OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
+CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
+48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
+trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
+qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
+AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
+ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
+A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
+f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
+kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
+CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
+URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
+CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
+oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
+IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
+66+KAQ==
+-----END CERTIFICATE-----
+
+CA Disig
+========
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK
+QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw
+MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz
+bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm
+GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD
+Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo
+hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt
+ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w
+gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P
+AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz
+aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff
+ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa
+BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t
+WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3
+mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
+CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K
+ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA
+4Z7CRneC9VkGjCFMhwnN5ag=
+-----END CERTIFICATE-----
+
+Juur-SK
+=======
+-----BEGIN CERTIFICATE-----
+MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA
+c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw
+DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG
+SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy
+aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf
+TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC
++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw
+UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa
+Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF
+MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD
+HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh
+AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA
+cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr
+AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw
+cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
+FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G
+A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo
+ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL
+abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678
+IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh
+Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2
+yyqcjg==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 1
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
+DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
+NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
+IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
+ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
+auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
+qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
+V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
+HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
+h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
+l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
+IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
+T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
+c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
+-----END CERTIFICATE-----
+
+SecureSign RootCA11
+===================
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
+SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
+b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
+KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
+cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
+TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
+wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
+g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
+O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
+bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
+t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
+OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
+bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
+Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
+y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
+lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+ACEDICOM Root
+=============
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
+T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
+MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
+A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
+WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
+YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
+MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
+m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
+HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
+xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
+3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
+2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
+TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
+4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
+9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
+bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
+aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
+eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
+zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
+ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
+KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
+nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
+I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
+MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
+tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky
+CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX
+bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/
+D/xwzoiQ
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
+MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
+c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
+BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
+U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
+fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
+0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
+pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
+1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
+AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
+QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
+FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
+lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
+I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
+yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
+LXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
+===================================================
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz
+ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3
+MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0
+cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u
+aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY
+8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y
+jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI
+JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk
+9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG
+SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d
+F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq
+D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4
+Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
+fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
+iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
+0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
+rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
+OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
+xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
+lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
+EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
+bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
+YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
+kpeDMdmztcpHWD9f
+-----END CERTIFICATE-----
+
+TC TrustCenter Universal CA III
+===============================
+-----BEGIN CERTIFICATE-----
+MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
+IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe
+Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU
+QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex
+KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt
+QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO
+juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut
+CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1
+M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G
+A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA
+g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+
+KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK
+BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
+CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq
+woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
+EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
+DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
+bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
+ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
+51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
+R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
+T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
+Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
+osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
+crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
+saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
+KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
+6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+Izenpe.com
+==========
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+Chambers of Commerce Root - 2008
+================================
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
+Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
+ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
+EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
+cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
+XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
+h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
+ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
+NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
+D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
+lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
+0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
+EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
+G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
+BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
+bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
+bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
+CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
+AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
+wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
+3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
+RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
+M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
+YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
+9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
+zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
+nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
+-----END CERTIFICATE-----
+
+Global Chambersign Root - 2008
+==============================
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
+NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
+Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
+QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
+VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
+XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
+ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
+/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
+TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
+H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
+Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
+HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
+AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
+BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
+BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
+aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
+aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
+1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
+dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
+/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
+ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
+dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
+9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
+foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
+qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
+P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
+c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+Go Daddy Root Certificate Authority - G2
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
+MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
+A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
+9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
+fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
+NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
+BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
+vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
+5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
+N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+Starfield Root Certificate Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
+eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
+DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
+VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
+W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
+bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
+N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
+ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
+JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
+TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
+4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
+F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
+c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+Starfield Services Root Certificate Authority - G2
+==================================================
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
+IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
+dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
+h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
+hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
+LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
+rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
+SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
+E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
+xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
+YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
+-----END CERTIFICATE-----
+
+AffirmTrust Commercial
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
+MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
+DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
+C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
+BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
+MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
+HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
+hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
+qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
+0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
+sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+AffirmTrust Networking
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
+MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
+Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
+dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
+/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
+h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
+HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
+UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
+12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
+WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
+/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+AffirmTrust Premium
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
+OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
+dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
+BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
+5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
+GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
+p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
+S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
+6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
+/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
+MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
+6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
+L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
+BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
+IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
+g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
+zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+AffirmTrust Premium ECC
+=======================
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
+BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
+MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
+cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
+N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
+BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
+BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
+57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
+eQ==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
+ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
+MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
+ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
+l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
+J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
+fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
+cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
+Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
+jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
+mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
+Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+Certinomis - Autorité Racine
+=============================
+-----BEGIN CERTIFICATE-----
+MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
+Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
+LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
+A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
+JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
+wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
+Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
+2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
+jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
+c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
+lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
+xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
+530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
+4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
+KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
+WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
+R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
+nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
+CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
+JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
+qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
+WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
+wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
+vgt2Fl43N+bYdJeimUV5
+-----END CERTIFICATE-----
+
+Root CA Generalitat Valenciana
+==============================
+-----BEGIN CERTIFICATE-----
+MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE
+ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290
+IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3
+WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE
+CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2
+F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B
+ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ
+D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte
+JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB
+AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n
+dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB
+ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl
+AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA
+YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy
+AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
+aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt
+AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA
+YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu
+AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA
+OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0
+dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV
+BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G
+A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S
+b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh
+TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz
+Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63
+NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH
+iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt
++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
+-----END CERTIFICATE-----
+
+A-Trust-nQual-03
+================
+-----BEGIN CERTIFICATE-----
+MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE
+Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy
+a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R
+dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw
+RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0
+ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1
+c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA
+zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n
+yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE
+SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4
+iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V
+cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV
+eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40
+ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr
+sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd
+JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS
+mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6
+ahq97BvIxYSazQ==
+-----END CERTIFICATE-----
+
+TWCA Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
+VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
+EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
+IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
+QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
+oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
+4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
+y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
+9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
+mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
+QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
+T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
+Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+Security Communication RootCA2
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
+SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
+aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
+3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
+spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
+EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
+QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
+u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
+3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
+tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
+mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+EC-ACC
+======
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
+BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
+ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
+VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
+CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
+BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
+MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
+SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
+Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
+cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
+w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
+ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
+HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
+E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
+0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
+VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
+Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
+dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
+lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
+Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
+l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
+E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
+5EI=
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2011
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
+O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
+aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
+AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
+IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
+1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
+71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
+8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
+3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
+MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
+MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
+b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
+XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
+/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
+7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
diff --git a/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php b/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php
new file mode 100755
index 00000000000..087694f08cd
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/requestcore/requestcore.class.php
@@ -0,0 +1,1028 @@
+<?php
+/**
+ * Handles all HTTP requests using cURL and manages the responses.
+ *
+ * @version 2012.01.17
+ * @copyright 2006-2011 Ryan Parman
+ * @copyright 2006-2010 Foleeo Inc.
+ * @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2011 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ */
+class RequestCore
+{
+ /**
+ * The URL being requested.
+ */
+ public $request_url;
+
+ /**
+ * The headers being sent in the request.
+ */
+ public $request_headers;
+
+ /**
+ * The body being sent in the request.
+ */
+ public $request_body;
+
+ /**
+ * The response returned by the request.
+ */
+ public $response;
+
+ /**
+ * The headers returned by the request.
+ */
+ public $response_headers;
+
+ /**
+ * The body returned by the request.
+ */
+ public $response_body;
+
+ /**
+ * The HTTP status code returned by the request.
+ */
+ public $response_code;
+
+ /**
+ * Additional response data.
+ */
+ public $response_info;
+
+ /**
+ * The handle for the cURL object.
+ */
+ public $curl_handle;
+
+ /**
+ * The method by which the request is being made.
+ */
+ public $method;
+
+ /**
+ * Stores the proxy settings to use for the request.
+ */
+ public $proxy = null;
+
+ /**
+ * The username to use for the request.
+ */
+ public $username = null;
+
+ /**
+ * The password to use for the request.
+ */
+ public $password = null;
+
+ /**
+ * Custom CURLOPT settings.
+ */
+ public $curlopts = null;
+
+ /**
+ * The state of debug mode.
+ */
+ public $debug_mode = false;
+
+ /**
+ * The default class to use for HTTP Requests (defaults to <RequestCore>).
+ */
+ public $request_class = 'RequestCore';
+
+ /**
+ * The default class to use for HTTP Responses (defaults to <ResponseCore>).
+ */
+ public $response_class = 'ResponseCore';
+
+ /**
+ * Default useragent string to use.
+ */
+ public $useragent = 'RequestCore/1.4.4';
+
+ /**
+ * File to read from while streaming up.
+ */
+ public $read_file = null;
+
+ /**
+ * The resource to read from while streaming up.
+ */
+ public $read_stream = null;
+
+ /**
+ * The size of the stream to read from.
+ */
+ public $read_stream_size = null;
+
+ /**
+ * The length already read from the stream.
+ */
+ public $read_stream_read = 0;
+
+ /**
+ * File to write to while streaming down.
+ */
+ public $write_file = null;
+
+ /**
+ * The resource to write to while streaming down.
+ */
+ public $write_stream = null;
+
+ /**
+ * Stores the intended starting seek position.
+ */
+ public $seek_position = null;
+
+ /**
+ * The location of the cacert.pem file to use.
+ */
+ public $cacert_location = false;
+
+ /**
+ * The state of SSL certificate verification.
+ */
+ public $ssl_verification = true;
+
+ /**
+ * The user-defined callback function to call when a stream is read from.
+ */
+ public $registered_streaming_read_callback = null;
+
+ /**
+ * The user-defined callback function to call when a stream is written to.
+ */
+ public $registered_streaming_write_callback = null;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * GET HTTP Method
+ */
+ const HTTP_GET = 'GET';
+
+ /**
+ * POST HTTP Method
+ */
+ const HTTP_POST = 'POST';
+
+ /**
+ * PUT HTTP Method
+ */
+ const HTTP_PUT = 'PUT';
+
+ /**
+ * DELETE HTTP Method
+ */
+ const HTTP_DELETE = 'DELETE';
+
+ /**
+ * HEAD HTTP Method
+ */
+ const HTTP_HEAD = 'HEAD';
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR/DESTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $url (Optional) The URL to request or service endpoint to query.
+ * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($url = null, $proxy = null, $helpers = null)
+ {
+ // Set some default values.
+ $this->request_url = $url;
+ $this->method = self::HTTP_GET;
+ $this->request_headers = array();
+ $this->request_body = '';
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['request']) && !empty($helpers['request']))
+ {
+ $this->request_class = $helpers['request'];
+ }
+
+ // Set a new Request class if one was set.
+ if (isset($helpers['response']) && !empty($helpers['response']))
+ {
+ $this->response_class = $helpers['response'];
+ }
+
+ if ($proxy)
+ {
+ $this->set_proxy($proxy);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Destructs the instance. Closes opened file handles.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function __destruct()
+ {
+ if (isset($this->read_file) && isset($this->read_stream))
+ {
+ fclose($this->read_stream);
+ }
+
+ if (isset($this->write_file) && isset($this->write_stream))
+ {
+ fclose($this->write_stream);
+ }
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // REQUEST METHODS
+
+ /**
+ * Sets the credentials to use for authentication.
+ *
+ * @param string $user (Required) The username to authenticate with.
+ * @param string $pass (Required) The password to authenticate with.
+ * @return $this A reference to the current instance.
+ */
+ public function set_credentials($user, $pass)
+ {
+ $this->username = $user;
+ $this->password = $pass;
+ return $this;
+ }
+
+ /**
+ * Adds a custom HTTP header to the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @param mixed $value (Required) The value to assign to the custom HTTP header.
+ * @return $this A reference to the current instance.
+ */
+ public function add_header($key, $value)
+ {
+ $this->request_headers[$key] = $value;
+ return $this;
+ }
+
+ /**
+ * Removes an HTTP header from the cURL request.
+ *
+ * @param string $key (Required) The custom HTTP header to set.
+ * @return $this A reference to the current instance.
+ */
+ public function remove_header($key)
+ {
+ if (isset($this->request_headers[$key]))
+ {
+ unset($this->request_headers[$key]);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the method type for the request.
+ *
+ * @param string $method (Required) One of the following constants: <HTTP_GET>, <HTTP_POST>, <HTTP_PUT>, <HTTP_HEAD>, <HTTP_DELETE>.
+ * @return $this A reference to the current instance.
+ */
+ public function set_method($method)
+ {
+ $this->method = strtoupper($method);
+ return $this;
+ }
+
+ /**
+ * Sets a custom useragent string for the class.
+ *
+ * @param string $ua (Required) The useragent string to use.
+ * @return $this A reference to the current instance.
+ */
+ public function set_useragent($ua)
+ {
+ $this->useragent = $ua;
+ return $this;
+ }
+
+ /**
+ * Set the body to send in the request.
+ *
+ * @param string $body (Required) The textual content to send along in the body of the request.
+ * @return $this A reference to the current instance.
+ */
+ public function set_body($body)
+ {
+ $this->request_body = $body;
+ return $this;
+ }
+
+ /**
+ * Set the URL to make the request to.
+ *
+ * @param string $url (Required) The URL to make the request to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_request_url($url)
+ {
+ $this->request_url = $url;
+ return $this;
+ }
+
+ /**
+ * Set additional CURLOPT settings. These will merge with the default settings, and override if
+ * there is a duplicate.
+ *
+ * @param array $curlopts (Optional) A set of key-value pairs that set `CURLOPT` options. These will merge with the existing CURLOPTs, and ones passed here will override the defaults. Keys should be the `CURLOPT_*` constants, not strings.
+ * @return $this A reference to the current instance.
+ */
+ public function set_curlopts($curlopts)
+ {
+ $this->curlopts = $curlopts;
+ return $this;
+ }
+
+ /**
+ * Sets the length in bytes to read from the stream while streaming up.
+ *
+ * @param integer $size (Required) The length in bytes to read from the stream.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream_size($size)
+ {
+ $this->read_stream_size = $size;
+
+ return $this;
+ }
+
+ /**
+ * Sets the resource to read from while streaming up. Reads the stream from its current position until
+ * EOF or `$size` bytes have been read. If `$size` is not given it will be determined by <php:fstat()> and
+ * <php:ftell()>.
+ *
+ * @param resource $resource (Required) The readable resource to read from.
+ * @param integer $size (Optional) The size of the stream to read.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_stream($resource, $size = null)
+ {
+ if (!isset($size) || $size < 0)
+ {
+ $stats = fstat($resource);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $position = ftell($resource);
+
+ if ($position !== false && $position >= 0)
+ {
+ $size = $stats['size'] - $position;
+ }
+ }
+ }
+
+ $this->read_stream = $resource;
+
+ return $this->set_read_stream_size($size);
+ }
+
+ /**
+ * Sets the file to read from while streaming up.
+ *
+ * @param string $location (Required) The readable location to read from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_read_file($location)
+ {
+ $this->read_file = $location;
+ $read_file_handle = fopen($location, 'r');
+
+ return $this->set_read_stream($read_file_handle);
+ }
+
+ /**
+ * Sets the resource to write to while streaming down.
+ *
+ * @param resource $resource (Required) The writeable resource to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_stream($resource)
+ {
+ $this->write_stream = $resource;
+
+ return $this;
+ }
+
+ /**
+ * Sets the file to write to while streaming down.
+ *
+ * @param string $location (Required) The writeable location to write to.
+ * @return $this A reference to the current instance.
+ */
+ public function set_write_file($location)
+ {
+ $this->write_file = $location;
+ $write_file_handle = fopen($location, 'w');
+
+ return $this->set_write_stream($write_file_handle);
+ }
+
+ /**
+ * Set the proxy to use for making requests.
+ *
+ * @param string $proxy (Required) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @return $this A reference to the current instance.
+ */
+ public function set_proxy($proxy)
+ {
+ $proxy = parse_url($proxy);
+ $proxy['user'] = isset($proxy['user']) ? $proxy['user'] : null;
+ $proxy['pass'] = isset($proxy['pass']) ? $proxy['pass'] : null;
+ $proxy['port'] = isset($proxy['port']) ? $proxy['port'] : null;
+ $this->proxy = $proxy;
+ return $this;
+ }
+
+ /**
+ * Set the intended starting seek position.
+ *
+ * @param integer $position (Required) The byte-position of the stream to begin reading from.
+ * @return $this A reference to the current instance.
+ */
+ public function set_seek_position($position)
+ {
+ $this->seek_position = isset($position) ? (integer) $position : null;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is read from using
+ * <CFRequest::streaming_read_callback()>.
+ *
+ * The user-defined callback function should accept three arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_read_callback($callback)
+ {
+ $this->registered_streaming_read_callback = $callback;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is written to using
+ * <CFRequest::streaming_write_callback()>.
+ *
+ * The user-defined callback function should accept two arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_write_callback($callback)
+ {
+ $this->registered_streaming_write_callback = $callback;
+
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // PREPARE, SEND, AND PROCESS REQUEST
+
+ /**
+ * A callback function that is invoked by cURL for streaming up.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param resource $file_handle (Required) The open file handle resource.
+ * @param integer $length (Required) The maximum number of bytes to read.
+ * @return binary Binary data from a stream.
+ */
+ public function streaming_read_callback($curl_handle, $file_handle, $length)
+ {
+ // Once we've sent as much as we're supposed to send...
+ if ($this->read_stream_read >= $this->read_stream_size)
+ {
+ // Send EOF
+ return '';
+ }
+
+ // If we're at the beginning of an upload and need to seek...
+ if ($this->read_stream_read == 0 && isset($this->seek_position) && $this->seek_position !== ftell($this->read_stream))
+ {
+ if (fseek($this->read_stream, $this->seek_position) !== 0)
+ {
+ throw new RequestCore_Exception('The stream does not support seeking and is either not at the requested position or the position is unknown.');
+ }
+ }
+
+ $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
+ $this->read_stream_read += strlen($read);
+
+ $out = $read === false ? '' : $read;
+
+ // Execute callback function
+ if ($this->registered_streaming_read_callback)
+ {
+ call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
+ }
+
+ return $out;
+ }
+
+ /**
+ * A callback function that is invoked by cURL for streaming down.
+ *
+ * @param resource $curl_handle (Required) The cURL handle for the request.
+ * @param binary $data (Required) The data to write.
+ * @return integer The number of bytes written.
+ */
+ public function streaming_write_callback($curl_handle, $data)
+ {
+ $length = strlen($data);
+ $written_total = 0;
+ $written_last = 0;
+
+ while ($written_total < $length)
+ {
+ $written_last = fwrite($this->write_stream, substr($data, $written_total));
+
+ if ($written_last === false)
+ {
+ return $written_total;
+ }
+
+ $written_total += $written_last;
+ }
+
+ // Execute callback function
+ if ($this->registered_streaming_write_callback)
+ {
+ call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
+ }
+
+ return $written_total;
+ }
+
+ /**
+ * Prepares and adds the details of the cURL request. This can be passed along to a <php:curl_multi_exec()>
+ * function.
+ *
+ * @return resource The handle for the cURL object.
+ */
+ public function prep_request()
+ {
+ $curl_handle = curl_init();
+
+ // Set default options.
+ curl_setopt($curl_handle, CURLOPT_URL, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_FILETIME, true);
+ curl_setopt($curl_handle, CURLOPT_FRESH_CONNECT, false);
+ curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
+ curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
+ curl_setopt($curl_handle, CURLOPT_HEADER, true);
+ curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl_handle, CURLOPT_TIMEOUT, 5184000);
+ curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 120);
+ curl_setopt($curl_handle, CURLOPT_NOSIGNAL, true);
+ curl_setopt($curl_handle, CURLOPT_REFERER, $this->request_url);
+ curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
+ curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
+
+ // Verification of the SSL cert
+ if ($this->ssl_verification)
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, false);
+ }
+
+ // chmod the file as 0755
+ if ($this->cacert_location === true)
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
+ }
+ elseif (is_string($this->cacert_location))
+ {
+ curl_setopt($curl_handle, CURLOPT_CAINFO, $this->cacert_location);
+ }
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
+ }
+
+ // Handle open_basedir & safe mode
+ if (!ini_get('safe_mode') && !ini_get('open_basedir'))
+ {
+ curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
+ }
+
+ // Enable a proxy connection if requested.
+ if ($this->proxy)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPPROXYTUNNEL, true);
+
+ $host = $this->proxy['host'];
+ $host .= ($this->proxy['port']) ? ':' . $this->proxy['port'] : '';
+ curl_setopt($curl_handle, CURLOPT_PROXY, $host);
+
+ if (isset($this->proxy['user']) && isset($this->proxy['pass']))
+ {
+ curl_setopt($curl_handle, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
+ }
+ }
+
+ // Set credentials for HTTP Basic/Digest Authentication.
+ if ($this->username && $this->password)
+ {
+ curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+ curl_setopt($curl_handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
+ }
+
+ // Handle the encoding if we can.
+ if (extension_loaded('zlib'))
+ {
+ curl_setopt($curl_handle, CURLOPT_ENCODING, 'gzip, deflate');
+ }
+
+ // Process custom headers
+ if (isset($this->request_headers) && count($this->request_headers))
+ {
+ $temp_headers = array();
+
+ foreach ($this->request_headers as $k => $v)
+ {
+ $temp_headers[] = $k . ': ' . $v;
+ }
+
+ curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $temp_headers);
+ }
+
+ switch ($this->method)
+ {
+ case self::HTTP_PUT:
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'PUT');
+ if (isset($this->read_stream))
+ {
+ if (!isset($this->read_stream_size) || $this->read_stream_size < 0)
+ {
+ throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
+ }
+
+ curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
+ curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+
+ case self::HTTP_POST:
+ curl_setopt($curl_handle, CURLOPT_POST, true);
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ break;
+
+ case self::HTTP_HEAD:
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, self::HTTP_HEAD);
+ curl_setopt($curl_handle, CURLOPT_NOBODY, 1);
+ break;
+
+ default: // Assumed GET
+ curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $this->method);
+ if (isset($this->write_stream))
+ {
+ curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, array($this, 'streaming_write_callback'));
+ curl_setopt($curl_handle, CURLOPT_HEADER, false);
+ }
+ else
+ {
+ curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+ }
+ break;
+ }
+
+ // Merge in the CURLOPTs
+ if (isset($this->curlopts) && sizeof($this->curlopts) > 0)
+ {
+ foreach ($this->curlopts as $k => $v)
+ {
+ curl_setopt($curl_handle, $k, $v);
+ }
+ }
+
+ return $curl_handle;
+ }
+
+ /**
+ * Take the post-processed cURL data and break it down into useful header/body/info chunks. Uses the
+ * data stored in the `curl_handle` and `response` properties unless replacement data is passed in via
+ * parameters.
+ *
+ * @param resource $curl_handle (Optional) The reference to the already executed cURL request.
+ * @param string $response (Optional) The actual response content itself that needs to be parsed.
+ * @return ResponseCore A <ResponseCore> object containing a parsed HTTP response.
+ */
+ public function process_response($curl_handle = null, $response = null)
+ {
+ // Accept a custom one if it's passed.
+ if ($curl_handle && $response)
+ {
+ $this->curl_handle = $curl_handle;
+ $this->response = $response;
+ }
+
+ // As long as this came back as a valid resource...
+ if (is_resource($this->curl_handle))
+ {
+ // Determine what's what.
+ $header_size = curl_getinfo($this->curl_handle, CURLINFO_HEADER_SIZE);
+ $this->response_headers = substr($this->response, 0, $header_size);
+ $this->response_body = substr($this->response, $header_size);
+ $this->response_code = curl_getinfo($this->curl_handle, CURLINFO_HTTP_CODE);
+ $this->response_info = curl_getinfo($this->curl_handle);
+
+ // Parse out the headers
+ $this->response_headers = explode("\r\n\r\n", trim($this->response_headers));
+ $this->response_headers = array_pop($this->response_headers);
+ $this->response_headers = explode("\r\n", $this->response_headers);
+ array_shift($this->response_headers);
+
+ // Loop through and split up the headers.
+ $header_assoc = array();
+ foreach ($this->response_headers as $header)
+ {
+ $kv = explode(': ', $header);
+ $header_assoc[strtolower($kv[0])] = $kv[1];
+ }
+
+ // Reset the headers to the appropriate property.
+ $this->response_headers = $header_assoc;
+ $this->response_headers['_info'] = $this->response_info;
+ $this->response_headers['_info']['method'] = $this->method;
+
+ if ($curl_handle && $response)
+ {
+ return new $this->response_class($this->response_headers, $this->response_body, $this->response_code, $this->curl_handle);
+ }
+ }
+
+ // Return false
+ return false;
+ }
+
+ /**
+ * Sends the request, calling necessary utility functions to update built-in properties.
+ *
+ * @param boolean $parse (Optional) Whether to parse the response with ResponseCore or not.
+ * @return string The resulting unparsed data from the request.
+ */
+ public function send_request($parse = false)
+ {
+ set_time_limit(0);
+
+ $curl_handle = $this->prep_request();
+ $this->response = curl_exec($curl_handle);
+
+ if ($this->response === false)
+ {
+ throw new cURL_Exception('cURL resource: ' . (string) $curl_handle . '; cURL error: ' . curl_error($curl_handle) . ' (cURL error code ' . curl_errno($curl_handle) . '). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.');
+ }
+
+ $parsed_response = $this->process_response($curl_handle, $this->response);
+
+ curl_close($curl_handle);
+
+ if ($parse)
+ {
+ return $parsed_response;
+ }
+
+ return $this->response;
+ }
+
+ /**
+ * Sends the request using <php:curl_multi_exec()>, enabling parallel requests. Uses the "rolling" method.
+ *
+ * @param array $handles (Required) An indexed array of cURL handles to process simultaneously.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>callback</code> - <code>string|array</code> - Optional - The string name of a function to pass the response data to. If this is a method, pass an array where the <code>[0]</code> index is the class and the <code>[1]</code> index is the method name.</li>
+ * <li><code>limit</code> - <code>integer</code> - Optional - The number of simultaneous requests to make. This can be useful for scaling around slow server responses. Defaults to trusting cURLs judgement as to how many to use.</li></ul>
+ * @return array Post-processed cURL responses.
+ */
+ public function send_multi_request($handles, $opt = null)
+ {
+ set_time_limit(0);
+
+ // Skip everything if there are no handles to process.
+ if (count($handles) === 0) return array();
+
+ if (!$opt) $opt = array();
+
+ // Initialize any missing options
+ $limit = isset($opt['limit']) ? $opt['limit'] : -1;
+
+ // Initialize
+ $handle_list = $handles;
+ $http = new $this->request_class();
+ $multi_handle = curl_multi_init();
+ $handles_post = array();
+ $added = count($handles);
+ $last_handle = null;
+ $count = 0;
+ $i = 0;
+
+ // Loop through the cURL handles and add as many as it set by the limit parameter.
+ while ($i < $added)
+ {
+ if ($limit > 0 && $i >= $limit) break;
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ $i++;
+ }
+
+ do
+ {
+ $active = false;
+
+ // Start executing and wait for a response.
+ while (($status = curl_multi_exec($multi_handle, $active)) === CURLM_CALL_MULTI_PERFORM)
+ {
+ // Start looking for possible responses immediately when we have to add more handles
+ if (count($handles) > 0) break;
+ }
+
+ // Figure out which requests finished.
+ $to_process = array();
+
+ while ($done = curl_multi_info_read($multi_handle))
+ {
+ // Since curl_errno() isn't reliable for handles that were in multirequests, we check the 'result' of the info read, which contains the curl error number, (listed here http://curl.haxx.se/libcurl/c/libcurl-errors.html )
+ if ($done['result'] > 0)
+ {
+ throw new cURL_Multi_Exception('cURL resource: ' . (string) $done['handle'] . '; cURL error: ' . curl_error($done['handle']) . ' (cURL error code ' . $done['result'] . '). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.');
+ }
+
+ // Because curl_multi_info_read() might return more than one message about a request, we check to see if this request is already in our array of completed requests
+ elseif (!isset($to_process[(int) $done['handle']]))
+ {
+ $to_process[(int) $done['handle']] = $done;
+ }
+ }
+
+ // Actually deal with the request
+ foreach ($to_process as $pkey => $done)
+ {
+ $response = $http->process_response($done['handle'], curl_multi_getcontent($done['handle']));
+ $key = array_search($done['handle'], $handle_list, true);
+ $handles_post[$key] = $response;
+
+ if (count($handles) > 0)
+ {
+ curl_multi_add_handle($multi_handle, array_shift($handles));
+ }
+
+ curl_multi_remove_handle($multi_handle, $done['handle']);
+ curl_close($done['handle']);
+ }
+ }
+ while ($active || count($handles_post) < $added);
+
+ curl_multi_close($multi_handle);
+
+ ksort($handles_post, SORT_NUMERIC);
+ return $handles_post;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // RESPONSE METHODS
+
+ /**
+ * Get the HTTP response headers from the request.
+ *
+ * @param string $header (Optional) A specific header value to return. Defaults to all headers.
+ * @return string|array All or selected header values.
+ */
+ public function get_response_header($header = null)
+ {
+ if ($header)
+ {
+ return $this->response_headers[strtolower($header)];
+ }
+ return $this->response_headers;
+ }
+
+ /**
+ * Get the HTTP response body from the request.
+ *
+ * @return string The response body.
+ */
+ public function get_response_body()
+ {
+ return $this->response_body;
+ }
+
+ /**
+ * Get the HTTP response code from the request.
+ *
+ * @return string The HTTP response code.
+ */
+ public function get_response_code()
+ {
+ return $this->response_code;
+ }
+}
+
+
+/**
+ * Container for all response-related methods.
+ */
+class ResponseCore
+{
+ /**
+ * Stores the HTTP header information.
+ */
+ public $header;
+
+ /**
+ * Stores the SimpleXML response.
+ */
+ public $body;
+
+ /**
+ * Stores the HTTP response code.
+ */
+ public $status;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param array $header (Required) Associative array of HTTP headers (typically returned by <RequestCore::get_response_header()>).
+ * @param string $body (Required) XML-formatted response from AWS.
+ * @param integer $status (Optional) HTTP response status code from the request.
+ * @return object Contains an <php:array> `header` property (HTTP headers as an associative array), a <php:SimpleXMLElement> or <php:string> `body` property, and an <php:integer> `status` code.
+ */
+ public function __construct($header, $body, $status = null)
+ {
+ $this->header = $header;
+ $this->body = $body;
+ $this->status = $status;
+
+ return $this;
+ }
+
+ /**
+ * Did we receive the status code we expected?
+ *
+ * @param integer|array $codes (Optional) The status code(s) to expect. Pass an <php:integer> for a single acceptable value, or an <php:array> of integers for multiple acceptable values.
+ * @return boolean Whether we received the expected status code or not.
+ */
+ public function isOK($codes = array(200, 201, 204, 206))
+ {
+ if (is_array($codes))
+ {
+ return in_array($this->status, $codes);
+ }
+
+ return $this->status === $codes;
+ }
+}
+
+class cURL_Exception extends Exception {}
+class cURL_Multi_Exception extends cURL_Exception {}
+class RequestCore_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/lib/yaml/LICENSE b/3rdparty/aws-sdk/lib/yaml/LICENSE
new file mode 100644
index 00000000000..3cef853170e
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2008-2009 Fabien Potencier
+
+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.
diff --git a/3rdparty/aws-sdk/lib/yaml/README.markdown b/3rdparty/aws-sdk/lib/yaml/README.markdown
new file mode 100644
index 00000000000..e4f80cfbac4
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/README.markdown
@@ -0,0 +1,15 @@
+Symfony YAML: A PHP library that speaks YAML
+============================================
+
+Symfony YAML is a PHP library that parses YAML strings and converts them to
+PHP arrays. It can also converts PHP arrays to YAML strings. Its official
+website is at http://components.symfony-project.org/yaml/.
+
+The documentation is to be found in the `doc/` directory.
+
+Symfony YAML is licensed under the MIT license (see LICENSE file).
+
+The Symfony YAML library is developed and maintained by the
+[symfony](http://www.symfony-project.org/) project team. It has been extracted
+from symfony to be used as a standalone library. Symfony YAML is part of the
+[symfony components project](http://components.symfony-project.org/).
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php
new file mode 100644
index 00000000000..1d89ccc9736
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYaml.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * sfYaml offers convenience methods to load and dump YAML.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYaml.class.php 8988 2008-05-15 20:24:26Z fabien $
+ */
+class sfYaml
+{
+ static protected
+ $spec = '1.2';
+
+ /**
+ * Sets the YAML specification version to use.
+ *
+ * @param string $version The YAML specification version
+ */
+ static public function setSpecVersion($version)
+ {
+ if (!in_array($version, array('1.1', '1.2')))
+ {
+ throw new InvalidArgumentException(sprintf('Version %s of the YAML specifications is not supported', $version));
+ }
+
+ self::$spec = $version;
+ }
+
+ /**
+ * Gets the YAML specification version to use.
+ *
+ * @return string The YAML specification version
+ */
+ static public function getSpecVersion()
+ {
+ return self::$spec;
+ }
+
+ /**
+ * Loads YAML into a PHP array.
+ *
+ * The load method, when supplied with a YAML stream (string or file),
+ * will do its best to convert YAML in a file into a PHP array.
+ *
+ * Usage:
+ * <code>
+ * $array = sfYaml::load('config.yml');
+ * print_r($array);
+ * </code>
+ *
+ * @param string $input Path of YAML file or string containing YAML
+ *
+ * @return array The YAML converted to a PHP array
+ *
+ * @throws InvalidArgumentException If the YAML is not valid
+ */
+ public static function load($input)
+ {
+ $file = '';
+
+ // if input is a file, process it
+ if (strpos($input, "\n") === false && is_file($input))
+ {
+ $file = $input;
+
+ ob_start();
+ $retval = include($input);
+ $content = ob_get_clean();
+
+ // if an array is returned by the config file assume it's in plain php form else in YAML
+ $input = is_array($retval) ? $retval : $content;
+ }
+
+ // if an array is returned by the config file assume it's in plain php form else in YAML
+ if (is_array($input))
+ {
+ return $input;
+ }
+
+ require_once dirname(__FILE__).'/sfYamlParser.php';
+
+ $yaml = new sfYamlParser();
+
+ try
+ {
+ $ret = $yaml->parse($input);
+ }
+ catch (Exception $e)
+ {
+ throw new InvalidArgumentException(sprintf('Unable to parse %s: %s', $file ? sprintf('file "%s"', $file) : 'string', $e->getMessage()));
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Dumps a PHP array to a YAML string.
+ *
+ * The dump method, when supplied with an array, will do its best
+ * to convert the array into friendly YAML.
+ *
+ * @param array $array PHP array
+ * @param integer $inline The level where you switch to inline YAML
+ *
+ * @return string A YAML string representing the original PHP array
+ */
+ public static function dump($array, $inline = 2)
+ {
+ require_once dirname(__FILE__).'/sfYamlDumper.php';
+
+ $yaml = new sfYamlDumper();
+
+ return $yaml->dump($array, $inline);
+ }
+}
+
+/**
+ * Wraps echo to automatically provide a newline.
+ *
+ * @param string $string The string to echo with new line
+ */
+function echoln($string)
+{
+ echo $string."\n";
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php
new file mode 100644
index 00000000000..0ada2b37d21
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlDumper.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfYamlInline.php');
+
+/**
+ * sfYamlDumper dumps PHP variables to YAML strings.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlDumper.class.php 10575 2008-08-01 13:08:42Z nicolas $
+ */
+class sfYamlDumper
+{
+ /**
+ * Dumps a PHP value to YAML.
+ *
+ * @param mixed $input The PHP value
+ * @param integer $inline The level where you switch to inline YAML
+ * @param integer $indent The level o indentation indentation (used internally)
+ *
+ * @return string The YAML representation of the PHP value
+ */
+ public function dump($input, $inline = 0, $indent = 0)
+ {
+ $output = '';
+ $prefix = $indent ? str_repeat(' ', $indent) : '';
+
+ if ($inline <= 0 || !is_array($input) || empty($input))
+ {
+ $output .= $prefix.sfYamlInline::dump($input);
+ }
+ else
+ {
+ $isAHash = array_keys($input) !== range(0, count($input) - 1);
+
+ foreach ($input as $key => $value)
+ {
+ $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);
+
+ $output .= sprintf('%s%s%s%s',
+ $prefix,
+ $isAHash ? sfYamlInline::dump($key).':' : '-',
+ $willBeInlined ? ' ' : "\n",
+ $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + 2)
+ ).($willBeInlined ? "\n" : '');
+ }
+ }
+
+ return $output;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php
new file mode 100644
index 00000000000..66edb4f07ab
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlInline.php
@@ -0,0 +1,442 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once dirname(__FILE__).'/sfYaml.php';
+
+/**
+ * sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlInline.class.php 16177 2009-03-11 08:32:48Z fabien $
+ */
+class sfYamlInline
+{
+ const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';
+
+ /**
+ * Convert a YAML string to a PHP array.
+ *
+ * @param string $value A YAML string
+ *
+ * @return array A PHP array representing the YAML string
+ */
+ static public function load($value)
+ {
+ $value = trim($value);
+
+ if (0 == strlen($value))
+ {
+ return '';
+ }
+
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
+ {
+ $mbEncoding = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
+ switch ($value[0])
+ {
+ case '[':
+ $result = self::parseSequence($value);
+ break;
+ case '{':
+ $result = self::parseMapping($value);
+ break;
+ default:
+ $result = self::parseScalar($value);
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Dumps a given PHP variable to a YAML string.
+ *
+ * @param mixed $value The PHP variable to convert
+ *
+ * @return string The YAML string representing the PHP array
+ */
+ static public function dump($value)
+ {
+ if ('1.1' === sfYaml::getSpecVersion())
+ {
+ $trueValues = array('true', 'on', '+', 'yes', 'y');
+ $falseValues = array('false', 'off', '-', 'no', 'n');
+ }
+ else
+ {
+ $trueValues = array('true');
+ $falseValues = array('false');
+ }
+
+ switch (true)
+ {
+ case is_resource($value):
+ throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
+ case is_object($value):
+ return '!!php/object:'.serialize($value);
+ case is_array($value):
+ return self::dumpArray($value);
+ case null === $value:
+ return 'null';
+ case true === $value:
+ return 'true';
+ case false === $value:
+ return 'false';
+ case ctype_digit($value):
+ return is_string($value) ? "'$value'" : (int) $value;
+ case is_numeric($value):
+ return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
+ case false !== strpos($value, "\n") || false !== strpos($value, "\r"):
+ return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
+ case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ - ? | < > = ! % @ ` ]/x', $value):
+ return sprintf("'%s'", str_replace('\'', '\'\'', $value));
+ case '' == $value:
+ return "''";
+ case preg_match(self::getTimestampRegex(), $value):
+ return "'$value'";
+ case in_array(strtolower($value), $trueValues):
+ return "'$value'";
+ case in_array(strtolower($value), $falseValues):
+ return "'$value'";
+ case in_array(strtolower($value), array('null', '~')):
+ return "'$value'";
+ default:
+ return $value;
+ }
+ }
+
+ /**
+ * Dumps a PHP array to a YAML string.
+ *
+ * @param array $value The PHP array to dump
+ *
+ * @return string The YAML string representing the PHP array
+ */
+ static protected function dumpArray($value)
+ {
+ // array
+ $keys = array_keys($value);
+ if (
+ (1 == count($keys) && '0' == $keys[0])
+ ||
+ (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
+ {
+ $output = array();
+ foreach ($value as $val)
+ {
+ $output[] = self::dump($val);
+ }
+
+ return sprintf('[%s]', implode(', ', $output));
+ }
+
+ // mapping
+ $output = array();
+ foreach ($value as $key => $val)
+ {
+ $output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
+ }
+
+ return sprintf('{ %s }', implode(', ', $output));
+ }
+
+ /**
+ * Parses a scalar to a YAML string.
+ *
+ * @param scalar $scalar
+ * @param string $delimiters
+ * @param array $stringDelimiter
+ * @param integer $i
+ * @param boolean $evaluate
+ *
+ * @return string A YAML string
+ */
+ static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
+ {
+ if (in_array($scalar[$i], $stringDelimiters))
+ {
+ // quoted scalar
+ $output = self::parseQuotedScalar($scalar, $i);
+ }
+ else
+ {
+ // "normal" string
+ if (!$delimiters)
+ {
+ $output = substr($scalar, $i);
+ $i += strlen($output);
+
+ // remove comments
+ if (false !== $strpos = strpos($output, ' #'))
+ {
+ $output = rtrim(substr($output, 0, $strpos));
+ }
+ }
+ else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
+ {
+ $output = $match[1];
+ $i += strlen($output);
+ }
+ else
+ {
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
+ }
+
+ $output = $evaluate ? self::evaluateScalar($output) : $output;
+ }
+
+ return $output;
+ }
+
+ /**
+ * Parses a quoted scalar to YAML.
+ *
+ * @param string $scalar
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseQuotedScalar($scalar, &$i)
+ {
+ if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/A', substr($scalar, $i), $match))
+ {
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
+ }
+
+ $output = substr($match[0], 1, strlen($match[0]) - 2);
+
+ if ('"' == $scalar[$i])
+ {
+ // evaluate the string
+ $output = str_replace(array('\\"', '\\n', '\\r'), array('"', "\n", "\r"), $output);
+ }
+ else
+ {
+ // unescape '
+ $output = str_replace('\'\'', '\'', $output);
+ }
+
+ $i += strlen($match[0]);
+
+ return $output;
+ }
+
+ /**
+ * Parses a sequence to a YAML string.
+ *
+ * @param string $sequence
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseSequence($sequence, &$i = 0)
+ {
+ $output = array();
+ $len = strlen($sequence);
+ $i += 1;
+
+ // [foo, bar, ...]
+ while ($i < $len)
+ {
+ switch ($sequence[$i])
+ {
+ case '[':
+ // nested sequence
+ $output[] = self::parseSequence($sequence, $i);
+ break;
+ case '{':
+ // nested mapping
+ $output[] = self::parseMapping($sequence, $i);
+ break;
+ case ']':
+ return $output;
+ case ',':
+ case ' ':
+ break;
+ default:
+ $isQuoted = in_array($sequence[$i], array('"', "'"));
+ $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
+
+ if (!$isQuoted && false !== strpos($value, ': '))
+ {
+ // embedded mapping?
+ try
+ {
+ $value = self::parseMapping('{'.$value.'}');
+ }
+ catch (InvalidArgumentException $e)
+ {
+ // no, it's not
+ }
+ }
+
+ $output[] = $value;
+
+ --$i;
+ }
+
+ ++$i;
+ }
+
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
+ }
+
+ /**
+ * Parses a mapping to a YAML string.
+ *
+ * @param string $mapping
+ * @param integer $i
+ *
+ * @return string A YAML string
+ */
+ static protected function parseMapping($mapping, &$i = 0)
+ {
+ $output = array();
+ $len = strlen($mapping);
+ $i += 1;
+
+ // {foo: bar, bar:foo, ...}
+ while ($i < $len)
+ {
+ switch ($mapping[$i])
+ {
+ case ' ':
+ case ',':
+ ++$i;
+ continue 2;
+ case '}':
+ return $output;
+ }
+
+ // key
+ $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
+
+ // value
+ $done = false;
+ while ($i < $len)
+ {
+ switch ($mapping[$i])
+ {
+ case '[':
+ // nested sequence
+ $output[$key] = self::parseSequence($mapping, $i);
+ $done = true;
+ break;
+ case '{':
+ // nested mapping
+ $output[$key] = self::parseMapping($mapping, $i);
+ $done = true;
+ break;
+ case ':':
+ case ' ':
+ break;
+ default:
+ $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
+ $done = true;
+ --$i;
+ }
+
+ ++$i;
+
+ if ($done)
+ {
+ continue 2;
+ }
+ }
+ }
+
+ throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
+ }
+
+ /**
+ * Evaluates scalars and replaces magic values.
+ *
+ * @param string $scalar
+ *
+ * @return string A YAML string
+ */
+ static protected function evaluateScalar($scalar)
+ {
+ $scalar = trim($scalar);
+
+ if ('1.1' === sfYaml::getSpecVersion())
+ {
+ $trueValues = array('true', 'on', '+', 'yes', 'y');
+ $falseValues = array('false', 'off', '-', 'no', 'n');
+ }
+ else
+ {
+ $trueValues = array('true');
+ $falseValues = array('false');
+ }
+
+ switch (true)
+ {
+ case 'null' == strtolower($scalar):
+ case '' == $scalar:
+ case '~' == $scalar:
+ return null;
+ case 0 === strpos($scalar, '!str'):
+ return (string) substr($scalar, 5);
+ case 0 === strpos($scalar, '! '):
+ return intval(self::parseScalar(substr($scalar, 2)));
+ case 0 === strpos($scalar, '!!php/object:'):
+ return unserialize(substr($scalar, 13));
+ case ctype_digit($scalar):
+ $raw = $scalar;
+ $cast = intval($scalar);
+ return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
+ case in_array(strtolower($scalar), $trueValues):
+ return true;
+ case in_array(strtolower($scalar), $falseValues):
+ return false;
+ case is_numeric($scalar):
+ return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
+ case 0 == strcasecmp($scalar, '.inf'):
+ case 0 == strcasecmp($scalar, '.NaN'):
+ return -log(0);
+ case 0 == strcasecmp($scalar, '-.inf'):
+ return log(0);
+ case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
+ return floatval(str_replace(',', '', $scalar));
+ case preg_match(self::getTimestampRegex(), $scalar):
+ return strtotime($scalar);
+ default:
+ return (string) $scalar;
+ }
+ }
+
+ static protected function getTimestampRegex()
+ {
+ return <<<EOF
+ ~^
+ (?P<year>[0-9][0-9][0-9][0-9])
+ -(?P<month>[0-9][0-9]?)
+ -(?P<day>[0-9][0-9]?)
+ (?:(?:[Tt]|[ \t]+)
+ (?P<hour>[0-9][0-9]?)
+ :(?P<minute>[0-9][0-9])
+ :(?P<second>[0-9][0-9])
+ (?:\.(?P<fraction>[0-9]*))?
+ (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
+ (?::(?P<tz_minute>[0-9][0-9]))?))?)?
+ $~x
+EOF;
+ }
+}
diff --git a/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php
new file mode 100644
index 00000000000..4c56a56db07
--- /dev/null
+++ b/3rdparty/aws-sdk/lib/yaml/lib/sfYamlParser.php
@@ -0,0 +1,612 @@
+<?php
+
+/*
+ * This file is part of the symfony package.
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require_once(dirname(__FILE__).'/sfYamlInline.php');
+
+if (!defined('PREG_BAD_UTF8_OFFSET_ERROR'))
+{
+ define('PREG_BAD_UTF8_OFFSET_ERROR', 5);
+}
+
+/**
+ * sfYamlParser parses YAML strings to convert them to PHP arrays.
+ *
+ * @package symfony
+ * @subpackage yaml
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ * @version SVN: $Id: sfYamlParser.class.php 10832 2008-08-13 07:46:08Z fabien $
+ */
+class sfYamlParser
+{
+ protected
+ $offset = 0,
+ $lines = array(),
+ $currentLineNb = -1,
+ $currentLine = '',
+ $refs = array();
+
+ /**
+ * Constructor
+ *
+ * @param integer $offset The offset of YAML document (used for line numbers in error messages)
+ */
+ public function __construct($offset = 0)
+ {
+ $this->offset = $offset;
+ }
+
+ /**
+ * Parses a YAML string to a PHP value.
+ *
+ * @param string $value A YAML string
+ *
+ * @return mixed A PHP value
+ *
+ * @throws InvalidArgumentException If the YAML is not valid
+ */
+ public function parse($value)
+ {
+ $value = str_replace("\t", ' ', $value); // Convert tabs to spaces.
+
+ $this->currentLineNb = -1;
+ $this->currentLine = '';
+ $this->lines = explode("\n", $this->cleanup($value));
+
+ if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2)
+ {
+ $mbEncoding = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
+ $data = array();
+ while ($this->moveToNextLine())
+ {
+ if ($this->isCurrentLineEmpty())
+ {
+ continue;
+ }
+
+ // tab?
+ if (preg_match('#^\t+#', $this->currentLine))
+ {
+ throw new InvalidArgumentException(sprintf('A YAML file cannot contain tabs as indentation at line %d (%s).', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+
+ $isRef = $isInPlace = $isProcessed = false;
+ if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+ {
+ if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+ {
+ $isRef = $matches['ref'];
+ $values['value'] = $matches['value'];
+ }
+
+ // array
+ if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+ {
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $data[] = $parser->parse($this->getNextEmbedBlock());
+ }
+ else
+ {
+ if (isset($values['leadspaces'])
+ && ' ' == $values['leadspaces']
+ && preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"\{].*?) *\:(\s+(?P<value>.+?))?\s*$#', $values['value'], $matches))
+ {
+ // this is a compact notation element, add to next block and parse
+ $c = $this->getRealCurrentLineNb();
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+
+ $block = $values['value'];
+ if (!$this->isNextLineIndented())
+ {
+ $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
+ }
+
+ $data[] = $parser->parse($block);
+ }
+ else
+ {
+ $data[] = $this->parseValue($values['value']);
+ }
+ }
+ }
+ else if (preg_match('#^(?P<key>'.sfYamlInline::REGEX_QUOTED_STRING.'|[^ \'"].*?) *\:(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values))
+ {
+ $key = sfYamlInline::parseScalar($values['key']);
+
+ if ('<<' === $key)
+ {
+ if (isset($values['value']) && '*' === substr($values['value'], 0, 1))
+ {
+ $isInPlace = substr($values['value'], 1);
+ if (!array_key_exists($isInPlace, $this->refs))
+ {
+ throw new InvalidArgumentException(sprintf('Reference "%s" does not exist at line %s (%s).', $isInPlace, $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+ else
+ {
+ if (isset($values['value']) && $values['value'] !== '')
+ {
+ $value = $values['value'];
+ }
+ else
+ {
+ $value = $this->getNextEmbedBlock();
+ }
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $parsed = $parser->parse($value);
+
+ $merged = array();
+ if (!is_array($parsed))
+ {
+ throw new InvalidArgumentException(sprintf("YAML merge keys used with a scalar value instead of an array at line %s (%s)", $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ else if (isset($parsed[0]))
+ {
+ // Numeric array, merge individual elements
+ foreach (array_reverse($parsed) as $parsedItem)
+ {
+ if (!is_array($parsedItem))
+ {
+ throw new InvalidArgumentException(sprintf("Merge items must be arrays at line %s (%s).", $this->getRealCurrentLineNb() + 1, $parsedItem));
+ }
+ $merged = array_merge($parsedItem, $merged);
+ }
+ }
+ else
+ {
+ // Associative array, merge
+ $merged = array_merge($merge, $parsed);
+ }
+
+ $isProcessed = $merged;
+ }
+ }
+ else if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#', $values['value'], $matches))
+ {
+ $isRef = $matches['ref'];
+ $values['value'] = $matches['value'];
+ }
+
+ if ($isProcessed)
+ {
+ // Merge keys
+ $data = $isProcessed;
+ }
+ // hash
+ else if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#'))
+ {
+ // if next line is less indented or equal, then it means that the current value is null
+ if ($this->isNextLineIndented())
+ {
+ $data[$key] = null;
+ }
+ else
+ {
+ $c = $this->getRealCurrentLineNb() + 1;
+ $parser = new sfYamlParser($c);
+ $parser->refs =& $this->refs;
+ $data[$key] = $parser->parse($this->getNextEmbedBlock());
+ }
+ }
+ else
+ {
+ if ($isInPlace)
+ {
+ $data = $this->refs[$isInPlace];
+ }
+ else
+ {
+ $data[$key] = $this->parseValue($values['value']);
+ }
+ }
+ }
+ else
+ {
+ // 1-liner followed by newline
+ if (2 == count($this->lines) && empty($this->lines[1]))
+ {
+ $value = sfYamlInline::load($this->lines[0]);
+ if (is_array($value))
+ {
+ $first = reset($value);
+ if ('*' === substr($first, 0, 1))
+ {
+ $data = array();
+ foreach ($value as $alias)
+ {
+ $data[] = $this->refs[substr($alias, 1)];
+ }
+ $value = $data;
+ }
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return $value;
+ }
+
+ switch (preg_last_error())
+ {
+ case PREG_INTERNAL_ERROR:
+ $error = 'Internal PCRE error on line';
+ break;
+ case PREG_BACKTRACK_LIMIT_ERROR:
+ $error = 'pcre.backtrack_limit reached on line';
+ break;
+ case PREG_RECURSION_LIMIT_ERROR:
+ $error = 'pcre.recursion_limit reached on line';
+ break;
+ case PREG_BAD_UTF8_ERROR:
+ $error = 'Malformed UTF-8 data on line';
+ break;
+ case PREG_BAD_UTF8_OFFSET_ERROR:
+ $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point on line';
+ break;
+ default:
+ $error = 'Unable to parse line';
+ }
+
+ throw new InvalidArgumentException(sprintf('%s %d (%s).', $error, $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+
+ if ($isRef)
+ {
+ $this->refs[$isRef] = end($data);
+ }
+ }
+
+ if (isset($mbEncoding))
+ {
+ mb_internal_encoding($mbEncoding);
+ }
+
+ return empty($data) ? null : $data;
+ }
+
+ /**
+ * Returns the current line number (takes the offset into account).
+ *
+ * @return integer The current line number
+ */
+ protected function getRealCurrentLineNb()
+ {
+ return $this->currentLineNb + $this->offset;
+ }
+
+ /**
+ * Returns the current line indentation.
+ *
+ * @return integer The current line indentation
+ */
+ protected function getCurrentLineIndentation()
+ {
+ return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
+ }
+
+ /**
+ * Returns the next embed block of YAML.
+ *
+ * @param integer $indentation The indent level at which the block is to be read, or null for default
+ *
+ * @return string A YAML string
+ */
+ protected function getNextEmbedBlock($indentation = null)
+ {
+ $this->moveToNextLine();
+
+ if (null === $indentation)
+ {
+ $newIndent = $this->getCurrentLineIndentation();
+
+ if (!$this->isCurrentLineEmpty() && 0 == $newIndent)
+ {
+ throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+ else
+ {
+ $newIndent = $indentation;
+ }
+
+ $data = array(substr($this->currentLine, $newIndent));
+
+ while ($this->moveToNextLine())
+ {
+ if ($this->isCurrentLineEmpty())
+ {
+ if ($this->isCurrentLineBlank())
+ {
+ $data[] = substr($this->currentLine, $newIndent);
+ }
+
+ continue;
+ }
+
+ $indent = $this->getCurrentLineIndentation();
+
+ if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match))
+ {
+ // empty line
+ $data[] = $match['text'];
+ }
+ else if ($indent >= $newIndent)
+ {
+ $data[] = substr($this->currentLine, $newIndent);
+ }
+ else if (0 == $indent)
+ {
+ $this->moveToPreviousLine();
+
+ break;
+ }
+ else
+ {
+ throw new InvalidArgumentException(sprintf('Indentation problem at line %d (%s)', $this->getRealCurrentLineNb() + 1, $this->currentLine));
+ }
+ }
+
+ return implode("\n", $data);
+ }
+
+ /**
+ * Moves the parser to the next line.
+ */
+ protected function moveToNextLine()
+ {
+ if ($this->currentLineNb >= count($this->lines) - 1)
+ {
+ return false;
+ }
+
+ $this->currentLine = $this->lines[++$this->currentLineNb];
+
+ return true;
+ }
+
+ /**
+ * Moves the parser to the previous line.
+ */
+ protected function moveToPreviousLine()
+ {
+ $this->currentLine = $this->lines[--$this->currentLineNb];
+ }
+
+ /**
+ * Parses a YAML value.
+ *
+ * @param string $value A YAML value
+ *
+ * @return mixed A PHP value
+ */
+ protected function parseValue($value)
+ {
+ if ('*' === substr($value, 0, 1))
+ {
+ if (false !== $pos = strpos($value, '#'))
+ {
+ $value = substr($value, 1, $pos - 2);
+ }
+ else
+ {
+ $value = substr($value, 1);
+ }
+
+ if (!array_key_exists($value, $this->refs))
+ {
+ throw new InvalidArgumentException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine));
+ }
+ return $this->refs[$value];
+ }
+
+ if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches))
+ {
+ $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';
+
+ return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
+ }
+ else
+ {
+ return sfYamlInline::load($value);
+ }
+ }
+
+ /**
+ * Parses a folded scalar.
+ *
+ * @param string $separator The separator that was used to begin this folded scalar (| or >)
+ * @param string $indicator The indicator that was used to begin this folded scalar (+ or -)
+ * @param integer $indentation The indentation that was used to begin this folded scalar
+ *
+ * @return string The text value
+ */
+ protected function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
+ {
+ $separator = '|' == $separator ? "\n" : ' ';
+ $text = '';
+
+ $notEOF = $this->moveToNextLine();
+
+ while ($notEOF && $this->isCurrentLineBlank())
+ {
+ $text .= "\n";
+
+ $notEOF = $this->moveToNextLine();
+ }
+
+ if (!$notEOF)
+ {
+ return '';
+ }
+
+ if (!preg_match('#^(?P<indent>'.($indentation ? str_repeat(' ', $indentation) : ' +').')(?P<text>.*)$#', $this->currentLine, $matches))
+ {
+ $this->moveToPreviousLine();
+
+ return '';
+ }
+
+ $textIndent = $matches['indent'];
+ $previousIndent = 0;
+
+ $text .= $matches['text'].$separator;
+ while ($this->currentLineNb + 1 < count($this->lines))
+ {
+ $this->moveToNextLine();
+
+ if (preg_match('#^(?P<indent> {'.strlen($textIndent).',})(?P<text>.+)$#', $this->currentLine, $matches))
+ {
+ if (' ' == $separator && $previousIndent != $matches['indent'])
+ {
+ $text = substr($text, 0, -1)."\n";
+ }
+ $previousIndent = $matches['indent'];
+
+ $text .= str_repeat(' ', $diff = strlen($matches['indent']) - strlen($textIndent)).$matches['text'].($diff ? "\n" : $separator);
+ }
+ else if (preg_match('#^(?P<text> *)$#', $this->currentLine, $matches))
+ {
+ $text .= preg_replace('#^ {1,'.strlen($textIndent).'}#', '', $matches['text'])."\n";
+ }
+ else
+ {
+ $this->moveToPreviousLine();
+
+ break;
+ }
+ }
+
+ if (' ' == $separator)
+ {
+ // replace last separator by a newline
+ $text = preg_replace('/ (\n*)$/', "\n$1", $text);
+ }
+
+ switch ($indicator)
+ {
+ case '':
+ $text = preg_replace('#\n+$#s', "\n", $text);
+ break;
+ case '+':
+ break;
+ case '-':
+ $text = preg_replace('#\n+$#s', '', $text);
+ break;
+ }
+
+ return $text;
+ }
+
+ /**
+ * Returns true if the next line is indented.
+ *
+ * @return Boolean Returns true if the next line is indented, false otherwise
+ */
+ protected function isNextLineIndented()
+ {
+ $currentIndentation = $this->getCurrentLineIndentation();
+ $notEOF = $this->moveToNextLine();
+
+ while ($notEOF && $this->isCurrentLineEmpty())
+ {
+ $notEOF = $this->moveToNextLine();
+ }
+
+ if (false === $notEOF)
+ {
+ return false;
+ }
+
+ $ret = false;
+ if ($this->getCurrentLineIndentation() <= $currentIndentation)
+ {
+ $ret = true;
+ }
+
+ $this->moveToPreviousLine();
+
+ return $ret;
+ }
+
+ /**
+ * Returns true if the current line is blank or if it is a comment line.
+ *
+ * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
+ */
+ protected function isCurrentLineEmpty()
+ {
+ return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
+ }
+
+ /**
+ * Returns true if the current line is blank.
+ *
+ * @return Boolean Returns true if the current line is blank, false otherwise
+ */
+ protected function isCurrentLineBlank()
+ {
+ return '' == trim($this->currentLine, ' ');
+ }
+
+ /**
+ * Returns true if the current line is a comment line.
+ *
+ * @return Boolean Returns true if the current line is a comment line, false otherwise
+ */
+ protected function isCurrentLineComment()
+ {
+ //checking explicitly the first char of the trim is faster than loops or strpos
+ $ltrimmedLine = ltrim($this->currentLine, ' ');
+ return $ltrimmedLine[0] === '#';
+ }
+
+ /**
+ * Cleanups a YAML string to be parsed.
+ *
+ * @param string $value The input YAML string
+ *
+ * @return string A cleaned up YAML string
+ */
+ protected function cleanup($value)
+ {
+ $value = str_replace(array("\r\n", "\r"), "\n", $value);
+
+ if (!preg_match("#\n$#", $value))
+ {
+ $value .= "\n";
+ }
+
+ // strip YAML header
+ $count = 0;
+ $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#s', '', $value, -1, $count);
+ $this->offset += $count;
+
+ // remove leading comments and/or ---
+ $trimmedValue = preg_replace('#^((\#.*?\n)|(\-\-\-.*?\n))*#s', '', $value, -1, $count);
+ if ($count == 1)
+ {
+ // items have been removed, update the offset
+ $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
+ $value = $trimmedValue;
+ }
+
+ return $value;
+ }
+}
diff --git a/3rdparty/aws-sdk/sdk.class.php b/3rdparty/aws-sdk/sdk.class.php
new file mode 100755
index 00000000000..8dcb7bf252f
--- /dev/null
+++ b/3rdparty/aws-sdk/sdk.class.php
@@ -0,0 +1,1435 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default CFRuntime Exception.
+ */
+class CFRuntime_Exception extends Exception {}
+
+/**
+ * Parsing Exception.
+ */
+class Parser_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// DETERMINE WHAT ENVIRONMENT DATA TO ADD TO THE USERAGENT FOR METRIC TRACKING
+
+/*
+ Define a temporary callback function for this calculation. Get the PHP version and any
+ required/optional extensions that are leveraged.
+
+ Tracking this data gives Amazon better metrics about what configurations are being used
+ so that forward-looking plans for the code can be made with more certainty (e.g. What
+ version of PHP are most people running? Do they tend to have the latest PCRE?).
+*/
+function __aws_sdk_ua_callback()
+{
+ $ua_append = '';
+ $extensions = get_loaded_extensions();
+ $sorted_extensions = array();
+
+ if ($extensions)
+ {
+ foreach ($extensions as $extension)
+ {
+ if ($extension === 'curl' && function_exists('curl_version'))
+ {
+ $curl_version = curl_version();
+ $sorted_extensions[strtolower($extension)] = $curl_version['version'];
+ }
+ elseif ($extension === 'pcre' && defined('PCRE_VERSION'))
+ {
+ $pcre_version = explode(' ', PCRE_VERSION);
+ $sorted_extensions[strtolower($extension)] = $pcre_version[0];
+ }
+ elseif ($extension === 'openssl' && defined('OPENSSL_VERSION_TEXT'))
+ {
+ $openssl_version = explode(' ', OPENSSL_VERSION_TEXT);
+ $sorted_extensions[strtolower($extension)] = $openssl_version[1];
+ }
+ else
+ {
+ $sorted_extensions[strtolower($extension)] = phpversion($extension);
+ }
+ }
+ }
+
+ foreach (array('simplexml', 'json', 'pcre', 'spl', 'curl', 'openssl', 'apc', 'xcache', 'memcache', 'memcached', 'pdo', 'pdo_sqlite', 'sqlite', 'sqlite3', 'zlib', 'xdebug') as $ua_ext)
+ {
+ if (isset($sorted_extensions[$ua_ext]) && $sorted_extensions[$ua_ext])
+ {
+ $ua_append .= ' ' . $ua_ext . '/' . $sorted_extensions[$ua_ext];
+ }
+ elseif (isset($sorted_extensions[$ua_ext]))
+ {
+ $ua_append .= ' ' . $ua_ext . '/0';
+ }
+ }
+
+ foreach (array('memory_limit', 'date.timezone', 'open_basedir', 'safe_mode', 'zend.enable_gc') as $cfg)
+ {
+ $cfg_value = ini_get($cfg);
+
+ if (in_array($cfg, array('memory_limit', 'date.timezone'), true))
+ {
+ $ua_append .= ' ' . $cfg . '/' . str_replace('/', '.', $cfg_value);
+ }
+ elseif (in_array($cfg, array('open_basedir', 'safe_mode', 'zend.enable_gc'), true))
+ {
+ if ($cfg_value === false || $cfg_value === '' || $cfg_value === 0)
+ {
+ $cfg_value = 'off';
+ }
+ elseif ($cfg_value === true || $cfg_value === '1' || $cfg_value === 1)
+ {
+ $cfg_value = 'on';
+ }
+
+ $ua_append .= ' ' . $cfg . '/' . $cfg_value;
+ }
+ }
+
+ return $ua_append;
+}
+
+
+/*%******************************************************************************************%*/
+// INTERMEDIARY CONSTANTS
+
+define('CFRUNTIME_NAME', 'aws-sdk-php');
+define('CFRUNTIME_VERSION', '1.5.6.2');
+define('CFRUNTIME_BUILD', '20120529180000');
+define('CFRUNTIME_USERAGENT', CFRUNTIME_NAME . '/' . CFRUNTIME_VERSION . ' PHP/' . PHP_VERSION . ' ' . str_replace(' ', '_', php_uname('s')) . '/' . str_replace(' ', '_', php_uname('r')) . ' Arch/' . php_uname('m') . ' SAPI/' . php_sapi_name() . ' Integer/' . PHP_INT_MAX . ' Build/' . CFRUNTIME_BUILD . __aws_sdk_ua_callback());
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Core functionality and default settings shared across all SDK classes. All methods and properties in this
+ * class are inherited by the service-specific classes.
+ *
+ * @version 2012.05.29
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFRuntime
+{
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * Name of the software.
+ */
+ const NAME = CFRUNTIME_NAME;
+
+ /**
+ * Version of the software.
+ */
+ const VERSION = CFRUNTIME_VERSION;
+
+ /**
+ * Build ID of the software.
+ */
+ const BUILD = CFRUNTIME_BUILD;
+
+ /**
+ * User agent string used to identify the software.
+ */
+ const USERAGENT = CFRUNTIME_USERAGENT;
+
+
+ /*%******************************************************************************************%*/
+ // PROPERTIES
+
+ /**
+ * The Amazon API Key.
+ */
+ public $key;
+
+ /**
+ * The Amazon API Secret Key.
+ */
+ public $secret_key;
+
+ /**
+ * The Amazon Authentication Token.
+ */
+ public $auth_token;
+
+ /**
+ * Handle for the utility functions.
+ */
+ public $util;
+
+ /**
+ * An identifier for the current AWS service.
+ */
+ public $service = null;
+
+ /**
+ * The supported API version.
+ */
+ public $api_version = null;
+
+ /**
+ * The state of whether auth should be handled as AWS Query.
+ */
+ public $use_aws_query = true;
+
+ /**
+ * The default class to use for utilities (defaults to <CFUtilities>).
+ */
+ public $utilities_class = 'CFUtilities';
+
+ /**
+ * The default class to use for HTTP requests (defaults to <CFRequest>).
+ */
+ public $request_class = 'CFRequest';
+
+ /**
+ * The default class to use for HTTP responses (defaults to <CFResponse>).
+ */
+ public $response_class = 'CFResponse';
+
+ /**
+ * The default class to use for parsing XML (defaults to <CFSimpleXML>).
+ */
+ public $parser_class = 'CFSimpleXML';
+
+ /**
+ * The default class to use for handling batch requests (defaults to <CFBatchRequest>).
+ */
+ public $batch_class = 'CFBatchRequest';
+
+ /**
+ * The state of SSL/HTTPS use.
+ */
+ public $use_ssl = true;
+
+ /**
+ * The state of SSL certificate verification.
+ */
+ public $ssl_verification = true;
+
+ /**
+ * The proxy to use for connecting.
+ */
+ public $proxy = null;
+
+ /**
+ * The alternate hostname to use, if any.
+ */
+ public $hostname = null;
+
+ /**
+ * The state of the capability to override the hostname with <set_hostname()>.
+ */
+ public $override_hostname = true;
+
+ /**
+ * The alternate port number to use, if any.
+ */
+ public $port_number = null;
+
+ /**
+ * The alternate resource prefix to use, if any.
+ */
+ public $resource_prefix = null;
+
+ /**
+ * The state of cache flow usage.
+ */
+ public $use_cache_flow = false;
+
+ /**
+ * The caching class to use.
+ */
+ public $cache_class = null;
+
+ /**
+ * The caching location to use.
+ */
+ public $cache_location = null;
+
+ /**
+ * When the cache should be considered stale.
+ */
+ public $cache_expires = null;
+
+ /**
+ * The state of cache compression.
+ */
+ public $cache_compress = null;
+
+ /**
+ * The current instantiated cache object.
+ */
+ public $cache_object = null;
+
+ /**
+ * The current instantiated batch request object.
+ */
+ public $batch_object = null;
+
+ /**
+ * The internally instantiated batch request object.
+ */
+ public $internal_batch_object = null;
+
+ /**
+ * The state of batch flow usage.
+ */
+ public $use_batch_flow = false;
+
+ /**
+ * The state of the cache deletion setting.
+ */
+ public $delete_cache = false;
+
+ /**
+ * The state of the debug mode setting.
+ */
+ public $debug_mode = false;
+
+ /**
+ * The number of times to retry failed requests.
+ */
+ public $max_retries = 3;
+
+ /**
+ * The user-defined callback function to call when a stream is read from.
+ */
+ public $registered_streaming_read_callback = null;
+
+ /**
+ * The user-defined callback function to call when a stream is written to.
+ */
+ public $registered_streaming_write_callback = null;
+
+ /**
+ * The credentials to use for authentication.
+ */
+ public $credentials = array();
+
+ /**
+ * The authentication class to use.
+ */
+ public $auth_class = null;
+
+ /**
+ * The operation to execute.
+ */
+ public $operation = null;
+
+ /**
+ * The payload to send.
+ */
+ public $payload = array();
+
+ /**
+ * The string prefix to prepend to the operation name.
+ */
+ public $operation_prefix = '';
+
+ /**
+ * The number of times a request has been retried.
+ */
+ public $redirects = 0;
+
+ /**
+ * The state of whether the response should be parsed or not.
+ */
+ public $parse_the_response = true;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * The constructor. This class should not be instantiated directly. Rather, a service-specific class
+ * should be instantiated.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ // Instantiate the utilities class.
+ $this->util = new $this->utilities_class();
+
+ // Determine the current service.
+ $this->service = get_class($this);
+
+ // Create credentials based on the options
+ $instance_credentials = new CFCredential($options);
+
+ // Retreive a credential set from config.inc.php if it exists
+ if (isset($options['credentials']))
+ {
+ // Use a specific credential set and merge with the instance credentials
+ $this->credentials = CFCredentials::get($options['credentials'])
+ ->merge($instance_credentials);
+ }
+ else
+ {
+ try
+ {
+ // Use the default credential set and merge with the instance credentials
+ $this->credentials = CFCredentials::get(CFCredentials::DEFAULT_KEY)
+ ->merge($instance_credentials);
+ }
+ catch (CFCredentials_Exception $e)
+ {
+ if (isset($options['key']) && isset($options['secret']))
+ {
+ // Only the instance credentials were provided
+ $this->credentials = $instance_credentials;
+ }
+ else
+ {
+ // No credentials provided in the config file or constructor
+ throw new CFCredentials_Exception('No credentials were provided to ' . $this->service . '.');
+ }
+ }
+ }
+
+ // Set internal credentials after they are resolved
+ $this->key = $this->credentials->key;
+ $this->secret_key = $this->credentials->secret;
+ $this->auth_token = $this->credentials->token;
+
+ // Automatically enable whichever caching mechanism is set to default.
+ $this->set_cache_config($this->credentials->default_cache_config);
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public static function factory(array $options = array())
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::factory().');
+ }
+
+ $self = get_called_class();
+ return new $self($options);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MAGIC METHODS
+
+ /**
+ * A magic method that allows `camelCase` method names to be translated into `snake_case` names.
+ *
+ * @param string $name (Required) The name of the method.
+ * @param array $arguments (Required) The arguments passed to the method.
+ * @return mixed The results of the intended method.
+ */
+ public function __call($name, $arguments)
+ {
+ // Convert camelCase method calls to snake_case.
+ $method_name = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $name));
+
+ if (method_exists($this, $method_name))
+ {
+ return call_user_func_array(array($this, $method_name), $arguments);
+ }
+
+ throw new CFRuntime_Exception('The method ' . $name . '() is undefined. Attempted to map to ' . $method_name . '() which is also undefined. Error occurred');
+ }
+
+
+ /*%******************************************************************************************%*/
+ // SET CUSTOM SETTINGS
+
+ /**
+ * Set the proxy settings to use.
+ *
+ * @param string $proxy (Required) Accepts proxy credentials in the following format: `proxy://user:pass@hostname:port`
+ * @return $this A reference to the current instance.
+ */
+ public function set_proxy($proxy)
+ {
+ $this->proxy = $proxy;
+ return $this;
+ }
+
+ /**
+ * Set the hostname to connect to. This is useful for alternate services that are API-compatible with
+ * AWS, but run from a different hostname.
+ *
+ * @param string $hostname (Required) The alternate hostname to use in place of the default one. Useful for mock or test applications living on different hostnames.
+ * @param integer $port_number (Optional) The alternate port number to use in place of the default one. Useful for mock or test applications living on different port numbers.
+ * @return $this A reference to the current instance.
+ */
+ public function set_hostname($hostname, $port_number = null)
+ {
+ if ($this->override_hostname)
+ {
+ $this->hostname = $hostname;
+
+ if ($port_number)
+ {
+ $this->port_number = $port_number;
+ $this->hostname .= ':' . (string) $this->port_number;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set the resource prefix to use. This method is useful for alternate services that are API-compatible
+ * with AWS.
+ *
+ * @param string $prefix (Required) An alternate prefix to prepend to the resource path. Useful for mock or test applications.
+ * @return $this A reference to the current instance.
+ */
+ public function set_resource_prefix($prefix)
+ {
+ $this->resource_prefix = $prefix;
+ return $this;
+ }
+
+ /**
+ * Disables any subsequent use of the <set_hostname()> method.
+ *
+ * @param boolean $override (Optional) Whether or not subsequent calls to <set_hostname()> should be obeyed. A `false` value disables the further effectiveness of <set_hostname()>. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function allow_hostname_override($override = true)
+ {
+ $this->override_hostname = $override;
+ return $this;
+ }
+
+ /**
+ * Disables SSL/HTTPS connections for hosts that don't support them. Some services, however, still
+ * require SSL support.
+ *
+ * This method will throw a user warning when invoked, which can be hidden by changing your
+ * <php:error_reporting()> settings.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function disable_ssl()
+ {
+ trigger_error('Disabling SSL connections is potentially unsafe and highly discouraged.', E_USER_WARNING);
+ $this->use_ssl = false;
+ return $this;
+ }
+
+ /**
+ * Disables the verification of the SSL Certificate Authority. Doing so can enable an attacker to carry
+ * out a man-in-the-middle attack.
+ *
+ * https://secure.wikimedia.org/wikipedia/en/wiki/Man-in-the-middle_attack
+ *
+ * This method will throw a user warning when invoked, which can be hidden by changing your
+ * <php:error_reporting()> settings.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function disable_ssl_verification($ssl_verification = false)
+ {
+ trigger_error('Disabling the verification of SSL certificates can lead to man-in-the-middle attacks. It is potentially unsafe and highly discouraged.', E_USER_WARNING);
+ $this->ssl_verification = $ssl_verification;
+ return $this;
+ }
+
+ /**
+ * Enables HTTP request/response header logging to `STDERR`.
+ *
+ * @param boolean $enabled (Optional) Whether or not to enable debug mode. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function enable_debug_mode($enabled = true)
+ {
+ $this->debug_mode = $enabled;
+ return $this;
+ }
+
+ /**
+ * Sets the maximum number of times to retry failed requests.
+ *
+ * @param integer $retries (Optional) The maximum number of times to retry failed requests. Defaults to `3`.
+ * @return $this A reference to the current instance.
+ */
+ public function set_max_retries($retries = 3)
+ {
+ $this->max_retries = $retries;
+ return $this;
+ }
+
+ /**
+ * Set the caching configuration to use for response caching.
+ *
+ * @param string $location (Required) <p>The location to store the cache object in. This may vary by cache method.</p><ul><li>File - The local file system paths such as <code>./cache</code> (relative) or <code>/tmp/cache/</code> (absolute). The location must be server-writable.</li><li>APC - Pass in <code>apc</code> to use this lightweight cache. You must have the <a href="http://php.net/apc">APC extension</a> installed.</li><li>XCache - Pass in <code>xcache</code> to use this lightweight cache. You must have the <a href="http://xcache.lighttpd.net">XCache</a> extension installed.</li><li>Memcached - Pass in an indexed array of associative arrays. Each associative array should have a <code>host</code> and a <code>port</code> value representing a <a href="http://php.net/memcached">Memcached</a> server to connect to.</li><li>PDO - A URL-style string (e.g. <code>pdo.mysql://user:pass@localhost/cache</code>) or a standard DSN-style string (e.g. <code>pdo.sqlite:/sqlite/cache.db</code>). MUST be prefixed with <code>pdo.</code>. See <code>CachePDO</code> and <a href="http://php.net/pdo">PDO</a> for more details.</li></ul>
+ * @param boolean $gzip (Optional) Whether or not data should be gzipped before being stored. A value of `true` will compress the contents before caching them. A value of `false` will leave the contents uncompressed. Defaults to `true`.
+ * @return $this A reference to the current instance.
+ */
+ public function set_cache_config($location, $gzip = true)
+ {
+ // If we have an array, we're probably passing in Memcached servers and ports.
+ if (is_array($location))
+ {
+ $this->cache_class = 'CacheMC';
+ }
+ else
+ {
+ // I would expect locations like `/tmp/cache`, `pdo.mysql://user:pass@hostname:port`, `pdo.sqlite:memory:`, and `apc`.
+ $type = strtolower(substr($location, 0, 3));
+ switch ($type)
+ {
+ case 'apc':
+ $this->cache_class = 'CacheAPC';
+ break;
+
+ case 'xca': // First three letters of `xcache`
+ $this->cache_class = 'CacheXCache';
+ break;
+
+ case 'pdo':
+ $this->cache_class = 'CachePDO';
+ $location = substr($location, 4);
+ break;
+
+ default:
+ $this->cache_class = 'CacheFile';
+ break;
+ }
+ }
+
+ // Set the remaining cache information.
+ $this->cache_location = $location;
+ $this->cache_compress = $gzip;
+
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is read from using
+ * <CFRequest::streaming_read_callback()>.
+ *
+ * The user-defined callback function should accept three arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_read_callback($callback)
+ {
+ $this->registered_streaming_read_callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Register a callback function to execute whenever a data stream is written to using
+ * <CFRequest::streaming_write_callback()>.
+ *
+ * The user-defined callback function should accept two arguments:
+ *
+ * <ul>
+ * <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+ * <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+ * </ul>
+ *
+ * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+ * <li>The name of a global function to execute, passed as a string.</li>
+ * <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+ * <li>An anonymous function (PHP 5.3+).</li></ul>
+ * @return $this A reference to the current instance.
+ */
+ public function register_streaming_write_callback($callback)
+ {
+ $this->registered_streaming_write_callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Fetches and caches STS credentials. This is meant to be used by the constructor, and is not to be
+ * manually invoked.
+ *
+ * @param CacheCore $cache (Required) The a reference to the cache object that is being used to handle the caching.
+ * @param array $options (Required) The options that were passed into the constructor.
+ * @return mixed The data to be cached, or NULL.
+ */
+ public function cache_sts_credentials($cache, $options)
+ {
+ $token = new AmazonSTS($options);
+ $response = $token->get_session_token();
+
+ if ($response->isOK())
+ {
+ // Update the expiration
+ $expiration_time = strtotime((string) $response->body->GetSessionTokenResult->Credentials->Expiration);
+ $expiration_duration = round(($expiration_time - time()) * 0.85);
+ $cache->expire_in($expiration_duration);
+
+ // Return the important data
+ return array(
+ 'key' => (string) $response->body->GetSessionTokenResult->Credentials->AccessKeyId,
+ 'secret' => (string) $response->body->GetSessionTokenResult->Credentials->SecretAccessKey,
+ 'token' => (string) $response->body->GetSessionTokenResult->Credentials->SessionToken,
+ 'expires' => (string) $response->body->GetSessionTokenResult->Credentials->Expiration,
+ );
+ }
+
+ return null;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // SET CUSTOM CLASSES
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFUtilities>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_utilities_class($class = 'CFUtilities')
+ {
+ $this->utilities_class = $class;
+ $this->util = new $this->utilities_class();
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFRequest>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @param $this A reference to the current instance.
+ */
+ public function set_request_class($class = 'CFRequest')
+ {
+ $this->request_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFResponse>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_response_class($class = 'CFResponse')
+ {
+ $this->response_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFSimpleXML>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_parser_class($class = 'CFSimpleXML')
+ {
+ $this->parser_class = $class;
+ return $this;
+ }
+
+ /**
+ * Set a custom class for this functionality. Use this method when extending/overriding existing classes
+ * with new functionality.
+ *
+ * The replacement class must extend from <CFBatchRequest>.
+ *
+ * @param string $class (Optional) The name of the new class to use for this functionality.
+ * @return $this A reference to the current instance.
+ */
+ public function set_batch_class($class = 'CFBatchRequest')
+ {
+ $this->batch_class = $class;
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // AUTHENTICATION
+
+ /**
+ * Default, shared method for authenticating a connection to AWS.
+ *
+ * @param string $operation (Required) Indicates the operation to perform.
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
+ * @return CFResponse Object containing a parsed HTTP response.
+ */
+ public function authenticate($operation, $payload)
+ {
+ $original_payload = $payload;
+ $method_arguments = func_get_args();
+ $curlopts = array();
+ $return_curl_handle = false;
+
+ if (substr($operation, 0, strlen($this->operation_prefix)) !== $this->operation_prefix)
+ {
+ $operation = $this->operation_prefix . $operation;
+ }
+
+ // Extract the custom CURLOPT settings from the payload
+ if (is_array($payload) && isset($payload['curlopts']))
+ {
+ $curlopts = $payload['curlopts'];
+ unset($payload['curlopts']);
+ }
+
+ // Determine whether the response or curl handle should be returned
+ if (is_array($payload) && isset($payload['returnCurlHandle']))
+ {
+ $return_curl_handle = isset($payload['returnCurlHandle']) ? $payload['returnCurlHandle'] : false;
+ unset($payload['returnCurlHandle']);
+ }
+
+ // Use the caching flow to determine if we need to do a round-trip to the server.
+ if ($this->use_cache_flow)
+ {
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . $operation . '_' . sha1(serialize($method_arguments));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
+
+ // Parse the XML body
+ $data = $this->parse_callback($data);
+
+ // End!
+ return $data;
+ }
+
+ /*%******************************************************************************************%*/
+
+ // Signer
+ $signer = new $this->auth_class($this->hostname, $operation, $payload, $this->credentials);
+ $signer->key = $this->key;
+ $signer->secret_key = $this->secret_key;
+ $signer->auth_token = $this->auth_token;
+ $signer->api_version = $this->api_version;
+ $signer->utilities_class = $this->utilities_class;
+ $signer->request_class = $this->request_class;
+ $signer->response_class = $this->response_class;
+ $signer->use_ssl = $this->use_ssl;
+ $signer->proxy = $this->proxy;
+ $signer->util = $this->util;
+ $signer->registered_streaming_read_callback = $this->registered_streaming_read_callback;
+ $signer->registered_streaming_write_callback = $this->registered_streaming_write_callback;
+ $request = $signer->authenticate();
+
+ // Update RequestCore settings
+ $request->request_class = $this->request_class;
+ $request->response_class = $this->response_class;
+ $request->ssl_verification = $this->ssl_verification;
+
+ /*%******************************************************************************************%*/
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ $request->debug_mode = $this->debug_mode;
+ }
+
+ // Set custom CURLOPT settings
+ if (count($curlopts))
+ {
+ $request->set_curlopts($curlopts);
+ }
+
+ // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
+ if ($this->use_batch_flow)
+ {
+ $handle = $request->prep_request();
+ $this->batch_object->add($handle);
+ $this->use_batch_flow = false;
+
+ return $handle;
+ }
+ elseif ($return_curl_handle)
+ {
+ return $request->prep_request();
+ }
+
+ // Send!
+ $request->send_request();
+
+ // Prepare the response.
+ $headers = $request->get_response_header();
+ $headers['x-aws-stringtosign'] = $signer->string_to_sign;
+
+ if (isset($signer->canonical_request))
+ {
+ $headers['x-aws-canonicalrequest'] = $signer->canonical_request;
+ }
+
+ $headers['x-aws-request-headers'] = $request->request_headers;
+ $headers['x-aws-body'] = $signer->querystring;
+
+ $data = new $this->response_class($headers, ($this->parse_the_response === true) ? $this->parse_callback($request->get_response_body()) : $request->get_response_body(), $request->get_response_code());
+
+ // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
+ if (
+ (integer) $request->get_response_code() === 500 || // Internal Error (presumably transient)
+ (integer) $request->get_response_code() === 503) // Service Unavailable (presumably transient)
+ {
+ if ($this->redirects <= $this->max_retries)
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ }
+
+ // DynamoDB has custom logic
+ elseif (
+ (integer) $request->get_response_code() === 400 &&
+ stripos((string) $request->get_response_body(), 'com.amazonaws.dynamodb.') !== false && (
+ stripos((string) $request->get_response_body(), 'ProvisionedThroughputExceededException') !== false
+ )
+ )
+ {
+ if ($this->redirects === 0)
+ {
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ elseif ($this->redirects <= max($this->max_retries, 10))
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(2, ($this->redirects - 1)) * 50000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($operation, $original_payload);
+ }
+ }
+
+ $this->redirects = 0;
+ return $data;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BATCH REQUEST LAYER
+
+ /**
+ * Specifies that the intended request should be queued for a later batch request.
+ *
+ * @param CFBatchRequest $queue (Optional) The <CFBatchRequest> instance to use for managing batch requests. If not available, it generates a new instance of <CFBatchRequest>.
+ * @return $this A reference to the current instance.
+ */
+ public function batch(CFBatchRequest &$queue = null)
+ {
+ if ($queue)
+ {
+ $this->batch_object = $queue;
+ }
+ elseif ($this->internal_batch_object)
+ {
+ $this->batch_object = &$this->internal_batch_object;
+ }
+ else
+ {
+ $this->internal_batch_object = new $this->batch_class();
+ $this->batch_object = &$this->internal_batch_object;
+ }
+
+ $this->use_batch_flow = true;
+
+ return $this;
+ }
+
+ /**
+ * Executes the batch request queue by sending all queued requests.
+ *
+ * @param boolean $clear_after_send (Optional) Whether or not to clear the batch queue after sending a request. Defaults to `true`. Set this to `false` if you are caching batch responses and want to retrieve results later.
+ * @return array An array of <CFResponse> objects.
+ */
+ public function send($clear_after_send = true)
+ {
+ if ($this->use_batch_flow)
+ {
+ // When we send the request, disable batch flow.
+ $this->use_batch_flow = false;
+
+ // If we're not caching, simply send the request.
+ if (!$this->use_cache_flow)
+ {
+ $response = $this->batch_object->send();
+ $parsed_data = array_map(array($this, 'parse_callback'), $response);
+ $parsed_data = new CFArray($parsed_data);
+
+ // Clear the queue
+ if ($clear_after_send)
+ {
+ $this->batch_object->queue = array();
+ }
+
+ return $parsed_data;
+ }
+
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . sha1(serialize($this->batch_object));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data_set = $this->cache_object->response_manager(array($this, 'cache_callback_batch'), array($this->batch_object));
+ $parsed_data = array_map(array($this, 'parse_callback'), $data_set);
+ $parsed_data = new CFArray($parsed_data);
+
+ // Clear the queue
+ if ($clear_after_send)
+ {
+ $this->batch_object->queue = array();
+ }
+
+ // End!
+ return $parsed_data;
+ }
+
+ // Load the class
+ $null = new CFBatchRequest();
+ unset($null);
+
+ throw new CFBatchRequest_Exception('You must use $object->batch()->send()');
+ }
+
+ /**
+ * Parses a response body into a PHP object if appropriate.
+ *
+ * @param CFResponse|string $response (Required) The <CFResponse> object to parse, or an XML string that would otherwise be a response body.
+ * @param string $content_type (Optional) The content-type to use when determining how to parse the content.
+ * @return CFResponse|string A parsed <CFResponse> object, or parsed XML.
+ */
+ public function parse_callback($response, $headers = null)
+ {
+ // Bail out
+ if (!$this->parse_the_response) return $response;
+
+ // Shorten this so we have a (mostly) single code path
+ if (isset($response->body))
+ {
+ if (is_string($response->body))
+ {
+ $body = $response->body;
+ }
+ else
+ {
+ return $response;
+ }
+ }
+ elseif (is_string($response))
+ {
+ $body = $response;
+ }
+ else
+ {
+ return $response;
+ }
+
+ // Decompress gzipped content
+ if (isset($headers['content-encoding']))
+ {
+ switch (strtolower(trim($headers['content-encoding'], "\x09\x0A\x0D\x20")))
+ {
+ case 'gzip':
+ case 'x-gzip':
+ $decoder = new CFGzipDecode($body);
+ if ($decoder->parse())
+ {
+ $body = $decoder->data;
+ }
+ break;
+
+ case 'deflate':
+ if (($uncompressed = gzuncompress($body)) !== false)
+ {
+ $body = $uncompressed;
+ }
+ elseif (($uncompressed = gzinflate($body)) !== false)
+ {
+ $body = $uncompressed;
+ }
+ break;
+ }
+ }
+
+ // Look for XML cues
+ if (
+ (isset($headers['content-type']) && ($headers['content-type'] === 'text/xml' || $headers['content-type'] === 'application/xml')) || // We know it's XML
+ (!isset($headers['content-type']) && (stripos($body, '<?xml') === 0 || strpos($body, '<Error>') === 0) || preg_match('/^<(\w*) xmlns="http(s?):\/\/(\w*).amazon(aws)?.com/im', $body)) // Sniff for XML
+ )
+ {
+ // Strip the default XML namespace to simplify XPath expressions
+ $body = str_replace("xmlns=", "ns=", $body);
+
+ try {
+ // Parse the XML body
+ $body = new $this->parser_class($body);
+ }
+ catch (Exception $e)
+ {
+ throw new Parser_Exception($e->getMessage());
+ }
+ }
+ // Look for JSON cues
+ elseif (
+ (isset($headers['content-type']) && ($headers['content-type'] === 'application/json') || $headers['content-type'] === 'application/x-amz-json-1.0') || // We know it's JSON
+ (!isset($headers['content-type']) && $this->util->is_json($body)) // Sniff for JSON
+ )
+ {
+ // Normalize JSON to a CFSimpleXML object
+ $body = CFJSON::to_xml($body, $this->parser_class);
+ }
+
+ // Put the parsed data back where it goes
+ if (isset($response->body))
+ {
+ $response->body = $body;
+ }
+ else
+ {
+ $response = $body;
+ }
+
+ return $response;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CACHING LAYER
+
+ /**
+ * Specifies that the resulting <CFResponse> object should be cached according to the settings from
+ * <set_cache_config()>.
+ *
+ * @param string|integer $expires (Required) The time the cache is to expire. Accepts a number of seconds as an integer, or an amount of time, as a string, that is understood by <php:strtotime()> (e.g. "1 hour").
+ * @param $this A reference to the current instance.
+ * @return $this
+ */
+ public function cache($expires)
+ {
+ // Die if they haven't used set_cache_config().
+ if (!$this->cache_class)
+ {
+ throw new CFRuntime_Exception('Must call set_cache_config() before using cache()');
+ }
+
+ if (is_string($expires))
+ {
+ $expires = strtotime($expires);
+ $this->cache_expires = $expires - time();
+ }
+ elseif (is_int($expires))
+ {
+ $this->cache_expires = $expires;
+ }
+
+ $this->use_cache_flow = true;
+
+ return $this;
+ }
+
+ /**
+ * The callback function that is executed when the cache doesn't exist or has expired. The response of
+ * this method is cached. Accepts identical parameters as the <authenticate()> method. Never call this
+ * method directly -- it is used internally by the caching system.
+ *
+ * @param string $operation (Required) Indicates the operation to perform.
+ * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
+ * @return CFResponse A parsed HTTP response.
+ */
+ public function cache_callback($operation, $payload)
+ {
+ // Disable the cache flow since it's already been handled.
+ $this->use_cache_flow = false;
+
+ // Make the request
+ $response = $this->authenticate($operation, $payload);
+
+ // If this is an XML document, convert it back to a string.
+ if (isset($response->body) && ($response->body instanceof SimpleXMLElement))
+ {
+ $response->body = $response->body->asXML();
+ }
+
+ return $response;
+ }
+
+ /**
+ * Used for caching the results of a batch request. Never call this method directly; it is used
+ * internally by the caching system.
+ *
+ * @param CFBatchRequest $batch (Required) The batch request object to send.
+ * @return CFResponse A parsed HTTP response.
+ */
+ public function cache_callback_batch(CFBatchRequest $batch)
+ {
+ return $batch->send();
+ }
+
+ /**
+ * Deletes a cached <CFResponse> object using the specified cache storage type.
+ *
+ * @return boolean A value of `true` if cached object exists and is successfully deleted, otherwise `false`.
+ */
+ public function delete_cache()
+ {
+ $this->use_cache_flow = true;
+ $this->delete_cache = true;
+
+ return $this;
+ }
+}
+
+
+/**
+ * Contains the functionality for auto-loading service classes.
+ */
+class CFLoader
+{
+ /*%******************************************************************************************%*/
+ // AUTO-LOADER
+
+ /**
+ * Automatically load classes that aren't included.
+ *
+ * @param string $class (Required) The classname to load.
+ * @return boolean Whether or not the file was successfully loaded.
+ */
+ public static function autoloader($class)
+ {
+ $path = dirname(__FILE__) . DIRECTORY_SEPARATOR;
+
+ // Amazon SDK classes
+ if (strstr($class, 'Amazon'))
+ {
+ if (file_exists($require_this = $path . 'services' . DIRECTORY_SEPARATOR . str_ireplace('Amazon', '', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Utility classes
+ elseif (strstr($class, 'CF'))
+ {
+ if (file_exists($require_this = $path . 'utilities' . DIRECTORY_SEPARATOR . str_ireplace('CF', '', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load CacheCore
+ elseif (strstr($class, 'Cache'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'cachecore' . DIRECTORY_SEPARATOR . strtolower($class) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load RequestCore
+ elseif (strstr($class, 'RequestCore') || strstr($class, 'ResponseCore'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'requestcore' . DIRECTORY_SEPARATOR . 'requestcore.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load array-to-domdocument
+ elseif (strstr($class, 'Array2DOM'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'dom' . DIRECTORY_SEPARATOR . 'ArrayToDOMDocument.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Authentication Signers
+ elseif (strstr($class, 'Auth'))
+ {
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . str_replace('auth', 'signature_', strtolower($class)) . '.class.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Signer interface
+ elseif ($class === 'Signer')
+ {
+ if (!interface_exists('Signable', false) &&
+ file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signable.interface.php'))
+ {
+ require_once $require_this;
+ }
+
+ if (file_exists($require_this = $path . 'authentication' . DIRECTORY_SEPARATOR . 'signer.abstract.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Load Symfony YAML classes
+ elseif (strstr($class, 'sfYaml'))
+ {
+ if (file_exists($require_this = $path . 'lib' . DIRECTORY_SEPARATOR . 'yaml' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sfYaml.php'))
+ {
+ require_once $require_this;
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+}
+
+// Register the autoloader.
+spl_autoload_register(array('CFLoader', 'autoloader'));
+
+// Don't look for any configuration files, the Amazon S3 storage backend handles configuration
+
+// /*%******************************************************************************************%*/
+// // CONFIGURATION
+//
+// // Look for include file in the same directory (e.g. `./config.inc.php`).
+// if (file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php'))
+// {
+// include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'config.inc.php';
+// }
+// // Fallback to `~/.aws/sdk/config.inc.php`
+// else
+// {
+// if (!isset($_ENV['HOME']) && isset($_SERVER['HOME']))
+// {
+// $_ENV['HOME'] = $_SERVER['HOME'];
+// }
+// elseif (!isset($_ENV['HOME']) && !isset($_SERVER['HOME']))
+// {
+// $_ENV['HOME'] = `cd ~ && pwd`;
+// if (!$_ENV['HOME'])
+// {
+// switch (strtolower(PHP_OS))
+// {
+// case 'darwin':
+// $_ENV['HOME'] = '/Users/' . get_current_user();
+// break;
+//
+// case 'windows':
+// case 'winnt':
+// case 'win32':
+// $_ENV['HOME'] = 'c:' . DIRECTORY_SEPARATOR . 'Documents and Settings' . DIRECTORY_SEPARATOR . get_current_user();
+// break;
+//
+// default:
+// $_ENV['HOME'] = '/home/' . get_current_user();
+// break;
+// }
+// }
+// }
+//
+// if (getenv('HOME') && file_exists(getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php'))
+// {
+// include_once getenv('HOME') . DIRECTORY_SEPARATOR . '.aws' . DIRECTORY_SEPARATOR . 'sdk' . DIRECTORY_SEPARATOR . 'config.inc.php';
+// }
+// }
diff --git a/3rdparty/aws-sdk/services/s3.class.php b/3rdparty/aws-sdk/services/s3.class.php
new file mode 100755
index 00000000000..2e9e1cd52b1
--- /dev/null
+++ b/3rdparty/aws-sdk/services/s3.class.php
@@ -0,0 +1,3979 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default S3 Exception.
+ */
+class S3_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// MAIN CLASS
+
+/**
+ * Amazon S3 is a web service that enables you to store data in the cloud. You can then download the data
+ * or use the data with other AWS services, such as Amazon Elastic Cloud Computer (EC2).
+ *
+ * Amazon Simple Storage Service (Amazon S3) is storage for the Internet. You can use Amazon S3 to store
+ * and retrieve any amount of data at any time, from anywhere on the web. You can accomplish these tasks
+ * using the AWS Management Console, which is a simple and intuitive web interface.
+ *
+ * To get the most out of Amazon S3, you need to understand a few simple concepts. Amazon S3 stores data
+ * as objects in buckets. An object is comprised of a file and optionally any metadata that describes
+ * that file.
+ *
+ * To store an object in Amazon S3, you upload the file you want to store to a bucket. When you upload a
+ * file, you can set permissions on the object as well as any metadata.
+ *
+ * Buckets are the containers for objects. You can have one or more buckets. For each bucket, you can control
+ * access to the bucket (who can create, delete, and list objects in the bucket), view access logs for the
+ * bucket and its objects, and choose the geographical region where Amazon S3 will store the bucket and its
+ * contents.
+ *
+ * Visit <http://aws.amazon.com/s3/> for more information.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/s3/ Amazon Simple Storage Service
+ * @link http://aws.amazon.com/documentation/s3/ Amazon Simple Storage Service documentation
+ */
+class AmazonS3 extends CFRuntime
+{
+ /*%******************************************************************************************%*/
+ // REGIONAL ENDPOINTS
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_US_E1 = 's3.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_VIRGINIA = self::REGION_US_E1;
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
+ */
+ const REGION_US_STANDARD = self::REGION_US_E1;
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Region.
+ */
+ const REGION_US_W1 = 's3-us-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Region.
+ */
+ const REGION_CALIFORNIA = self::REGION_US_W1;
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Region.
+ */
+ const REGION_US_W2 = 's3-us-west-2.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Region.
+ */
+ const REGION_OREGON = self::REGION_US_W2;
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Region.
+ */
+ const REGION_EU_W1 = 's3-eu-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Region.
+ */
+ const REGION_IRELAND = self::REGION_EU_W1;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
+ */
+ const REGION_APAC_SE1 = 's3-ap-southeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Region.
+ */
+ const REGION_SINGAPORE = self::REGION_APAC_SE1;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
+ */
+ const REGION_APAC_NE1 = 's3-ap-northeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Region.
+ */
+ const REGION_TOKYO = self::REGION_APAC_NE1;
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Region.
+ */
+ const REGION_SA_E1 = 's3-sa-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Region.
+ */
+ const REGION_SAO_PAULO = self::REGION_SA_E1;
+
+ /**
+ * Specify the queue URL for the United States GovCloud Region.
+ */
+ const REGION_US_GOV1 = 's3-us-gov-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the United States GovCloud FIPS 140-2 Region.
+ */
+ const REGION_US_GOV1_FIPS = 's3-fips-us-gov-west-1.amazonaws.com';
+
+ /**
+ * The default endpoint.
+ */
+ const DEFAULT_URL = self::REGION_US_E1;
+
+
+ /*%******************************************************************************************%*/
+ // REGIONAL WEBSITE ENDPOINTS
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_US_E1_WEBSITE = 's3-website-us-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_VIRGINIA_WEBSITE = self::REGION_US_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
+ */
+ const REGION_US_STANDARD_WEBSITE = self::REGION_US_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Website Region.
+ */
+ const REGION_US_W1_WEBSITE = 's3-website-us-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 1 (Northern California) Website Region.
+ */
+ const REGION_CALIFORNIA_WEBSITE = self::REGION_US_W1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Website Region.
+ */
+ const REGION_US_W2_WEBSITE = 's3-website-us-west-2.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the US-West 2 (Oregon) Website Region.
+ */
+ const REGION_OREGON_WEBSITE = self::REGION_US_W2_WEBSITE;
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Website Region.
+ */
+ const REGION_EU_W1_WEBSITE = 's3-website-eu-west-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the EU (Ireland) Website Region.
+ */
+ const REGION_IRELAND_WEBSITE = self::REGION_EU_W1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
+ */
+ const REGION_APAC_SE1_WEBSITE = 's3-website-ap-southeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
+ */
+ const REGION_SINGAPORE_WEBSITE = self::REGION_APAC_SE1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Website Region.
+ */
+ const REGION_APAC_NE1_WEBSITE = 's3-website-ap-northeast-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the Asia Pacific (Japan) Website Region.
+ */
+ const REGION_TOKYO_WEBSITE = self::REGION_APAC_NE1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Website Region.
+ */
+ const REGION_SA_E1_WEBSITE = 's3-website-sa-east-1.amazonaws.com';
+
+ /**
+ * Specify the queue URL for the South America (Sao Paulo) Website Region.
+ */
+ const REGION_SAO_PAULO_WEBSITE = self::REGION_SA_E1_WEBSITE;
+
+ /**
+ * Specify the queue URL for the United States GovCloud Website Region.
+ */
+ const REGION_US_GOV1_WEBSITE = 's3-website-us-gov-west-1.amazonaws.com';
+
+
+ /*%******************************************************************************************%*/
+ // ACL
+
+ /**
+ * ACL: Owner-only read/write.
+ */
+ const ACL_PRIVATE = 'private';
+
+ /**
+ * ACL: Owner read/write, public read.
+ */
+ const ACL_PUBLIC = 'public-read';
+
+ /**
+ * ACL: Public read/write.
+ */
+ const ACL_OPEN = 'public-read-write';
+
+ /**
+ * ACL: Owner read/write, authenticated read.
+ */
+ const ACL_AUTH_READ = 'authenticated-read';
+
+ /**
+ * ACL: Bucket owner read.
+ */
+ const ACL_OWNER_READ = 'bucket-owner-read';
+
+ /**
+ * ACL: Bucket owner full control.
+ */
+ const ACL_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
+
+
+ /*%******************************************************************************************%*/
+ // GRANTS
+
+ /**
+ * When applied to a bucket, grants permission to list the bucket. When applied to an object, this
+ * grants permission to read the object data and/or metadata.
+ */
+ const GRANT_READ = 'READ';
+
+ /**
+ * When applied to a bucket, grants permission to create, overwrite, and delete any object in the
+ * bucket. This permission is not supported for objects.
+ */
+ const GRANT_WRITE = 'WRITE';
+
+ /**
+ * Grants permission to read the ACL for the applicable bucket or object. The owner of a bucket or
+ * object always has this permission implicitly.
+ */
+ const GRANT_READ_ACP = 'READ_ACP';
+
+ /**
+ * Gives permission to overwrite the ACP for the applicable bucket or object. The owner of a bucket
+ * or object always has this permission implicitly. Granting this permission is equivalent to granting
+ * FULL_CONTROL because the grant recipient can make any changes to the ACP.
+ */
+ const GRANT_WRITE_ACP = 'WRITE_ACP';
+
+ /**
+ * Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions. It does not convey additional rights and
+ * is provided only for convenience.
+ */
+ const GRANT_FULL_CONTROL = 'FULL_CONTROL';
+
+
+ /*%******************************************************************************************%*/
+ // USERS
+
+ /**
+ * The "AuthenticatedUsers" group for access control policies.
+ */
+ const USERS_AUTH = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers';
+
+ /**
+ * The "AllUsers" group for access control policies.
+ */
+ const USERS_ALL = 'http://acs.amazonaws.com/groups/global/AllUsers';
+
+ /**
+ * The "LogDelivery" group for access control policies.
+ */
+ const USERS_LOGGING = 'http://acs.amazonaws.com/groups/s3/LogDelivery';
+
+
+ /*%******************************************************************************************%*/
+ // PATTERNS
+
+ /**
+ * PCRE: Match all items
+ */
+ const PCRE_ALL = '/.*/i';
+
+
+ /*%******************************************************************************************%*/
+ // STORAGE
+
+ /**
+ * Standard storage redundancy.
+ */
+ const STORAGE_STANDARD = 'STANDARD';
+
+ /**
+ * Reduced storage redundancy.
+ */
+ const STORAGE_REDUCED = 'REDUCED_REDUNDANCY';
+
+
+ /*%******************************************************************************************%*/
+ // PROPERTIES
+
+ /**
+ * The request URL.
+ */
+ public $request_url;
+
+ /**
+ * The virtual host setting.
+ */
+ public $vhost;
+
+ /**
+ * The base XML elements to use for access control policy methods.
+ */
+ public $base_acp_xml;
+
+ /**
+ * The base XML elements to use for creating buckets in regions.
+ */
+ public $base_location_constraint;
+
+ /**
+ * The base XML elements to use for logging methods.
+ */
+ public $base_logging_xml;
+
+ /**
+ * The base XML elements to use for notifications.
+ */
+ public $base_notification_xml;
+
+ /**
+ * The base XML elements to use for versioning.
+ */
+ public $base_versioning_xml;
+
+ /**
+ * The base XML elements to use for completing a multipart upload.
+ */
+ public $complete_mpu_xml;
+
+ /**
+ * The base XML elements to use for website support.
+ */
+ public $website_config_xml;
+
+ /**
+ * The base XML elements to use for multi-object delete support.
+ */
+ public $multi_object_delete_xml;
+
+ /**
+ * The base XML elements to use for object expiration support.
+ */
+ public $object_expiration_xml;
+
+ /**
+ * The DNS vs. Path-style setting.
+ */
+ public $path_style = false;
+
+ /**
+ * The state of whether the prefix change is temporary or permanent.
+ */
+ public $temporary_prefix = false;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of <AmazonS3>.
+ *
+ * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
+ * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
+ * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
+ * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
+ * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
+ * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ $this->vhost = null;
+ $this->api_version = '2006-03-01';
+ $this->hostname = self::DEFAULT_URL;
+
+ $this->base_acp_xml = '<?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/latest/"></AccessControlPolicy>';
+ $this->base_location_constraint = '<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><LocationConstraint></LocationConstraint></CreateBucketConfiguration>';
+ $this->base_logging_xml = '<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/' . $this->api_version . '"></BucketLoggingStatus>';
+ $this->base_notification_xml = '<?xml version="1.0" encoding="utf-8"?><NotificationConfiguration></NotificationConfiguration>';
+ $this->base_versioning_xml = '<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"></VersioningConfiguration>';
+ $this->complete_mpu_xml = '<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>';
+ $this->website_config_xml = '<?xml version="1.0" encoding="utf-8"?><WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><IndexDocument><Suffix>index.html</Suffix></IndexDocument><ErrorDocument><Key>error.html</Key></ErrorDocument></WebsiteConfiguration>';
+ $this->multi_object_delete_xml = '<?xml version="1.0" encoding="utf-8"?><Delete></Delete>';
+ $this->object_expiration_xml = '<?xml version="1.0" encoding="utf-8"?><LifecycleConfiguration></LifecycleConfiguration>';
+
+ parent::__construct($options);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // AUTHENTICATION
+
+ /**
+ * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
+ * this class.
+ *
+ * @param string $operation (Required) The name of the bucket to operate on (S3 Only).
+ * @param array $payload (Required) An associative array of parameters for authenticating. See inline comments for allowed keys.
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_Authentication.html REST authentication
+ */
+ public function authenticate($operation, $payload)
+ {
+ /*
+ * Overriding or extending this class? You can pass the following "magic" keys into $opt.
+ *
+ * ## verb, resource, sub_resource and query_string ##
+ * <verb> /<resource>?<sub_resource>&<query_string>
+ * GET /filename.txt?versions&prefix=abc&max-items=1
+ *
+ * ## versionId, uploadId, partNumber, response-* ##
+ * These don't follow the same rules as above, in that the they needs to be signed, while
+ * other query_string values do not.
+ *
+ * ## curlopts ##
+ * These values get passed directly to the cURL methods in RequestCore.
+ *
+ * ## fileUpload, fileDownload, seekTo ##
+ * These are slightly modified and then passed to the cURL methods in RequestCore.
+ *
+ * ## headers ##
+ * $opt['headers'] is an array, whose keys are HTTP headers to be sent.
+ *
+ * ## body ##
+ * This is the request body that is sent to the server via PUT/POST.
+ *
+ * ## preauth ##
+ * This is a hook that tells authenticate() to generate a pre-authenticated URL.
+ *
+ * ## returnCurlHandle ##
+ * Tells authenticate() to return the cURL handle for the request instead of executing it.
+ */
+
+ // Rename variables (to overcome inheritence issues)
+ $bucket = $operation;
+ $opt = $payload;
+
+ // Validate the S3 bucket name
+ if (!$this->validate_bucketname_support($bucket))
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception('S3 does not support "' . $bucket . '" as a valid bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
+ // @codeCoverageIgnoreEnd
+ }
+
+ // Die if $opt isn't set.
+ if (!$opt) return false;
+
+ $method_arguments = func_get_args();
+
+ // Use the caching flow to determine if we need to do a round-trip to the server.
+ if ($this->use_cache_flow)
+ {
+ // Generate an identifier specific to this particular set of arguments.
+ $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
+
+ // Instantiate the appropriate caching object.
+ $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
+
+ if ($this->delete_cache)
+ {
+ $this->use_cache_flow = false;
+ $this->delete_cache = false;
+ return $this->cache_object->delete();
+ }
+
+ // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
+ $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
+
+ if ($this->parse_the_response)
+ {
+ // Parse the XML body
+ $data = $this->parse_callback($data);
+ }
+
+ // End!
+ return $data;
+ }
+
+ // If we haven't already set a resource prefix and the bucket name isn't DNS-valid...
+ if ((!$this->resource_prefix && !$this->validate_bucketname_create($bucket)) || $this->path_style)
+ {
+ // Fall back to the older path-style URI
+ $this->set_resource_prefix('/' . $bucket);
+ $this->temporary_prefix = true;
+ }
+
+ // Determine hostname
+ $scheme = $this->use_ssl ? 'https://' : 'http://';
+ if ($this->resource_prefix || $this->path_style) // Use bucket-in-path method.
+ {
+ $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
+ }
+ else
+ {
+ $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
+ }
+
+ // Get the UTC timestamp in RFC 2616 format
+ $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
+
+ // Storage for request parameters.
+ $resource = '';
+ $sub_resource = '';
+ $querystringparams = array();
+ $signable_querystringparams = array();
+ $string_to_sign = '';
+ $headers = array(
+ 'Content-MD5' => '',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'Date' => $date
+ );
+
+ /*%******************************************************************************************%*/
+
+ // Do we have an authentication token?
+ if ($this->auth_token)
+ {
+ $headers['X-Amz-Security-Token'] = $this->auth_token;
+ }
+
+ // Handle specific resources
+ if (isset($opt['resource']))
+ {
+ $resource .= $opt['resource'];
+ }
+
+ // Merge query string values
+ if (isset($opt['query_string']))
+ {
+ $querystringparams = array_merge($querystringparams, $opt['query_string']);
+ }
+ $query_string = $this->util->to_query_string($querystringparams);
+
+ // Merge the signable query string values. Must be alphabetical.
+ $signable_list = array(
+ 'partNumber',
+ 'response-cache-control',
+ 'response-content-disposition',
+ 'response-content-encoding',
+ 'response-content-language',
+ 'response-content-type',
+ 'response-expires',
+ 'uploadId',
+ 'versionId'
+ );
+ foreach ($signable_list as $item)
+ {
+ if (isset($opt[$item]))
+ {
+ $signable_querystringparams[$item] = $opt[$item];
+ }
+ }
+ $signable_query_string = $this->util->to_query_string($signable_querystringparams);
+
+ // Merge the HTTP headers
+ if (isset($opt['headers']))
+ {
+ $headers = array_merge($headers, $opt['headers']);
+ }
+
+ // Compile the URI to request
+ $conjunction = '?';
+ $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
+ $non_signable_resource = '';
+
+ if (isset($opt['sub_resource']))
+ {
+ $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
+ $conjunction = '&';
+ }
+ if ($signable_query_string !== '')
+ {
+ $signable_query_string = $conjunction . $signable_query_string;
+ $conjunction = '&';
+ }
+ if ($query_string !== '')
+ {
+ $non_signable_resource .= $conjunction . $query_string;
+ $conjunction = '&';
+ }
+ if (substr($hostname, -1) === substr($signable_resource, 0, 1))
+ {
+ $signable_resource = ltrim($signable_resource, '/');
+ }
+
+ $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
+
+ if (isset($opt['location']))
+ {
+ $this->request_url = $opt['location'];
+ }
+
+ // Gather information to pass along to other classes.
+ $helpers = array(
+ 'utilities' => $this->utilities_class,
+ 'request' => $this->request_class,
+ 'response' => $this->response_class,
+ );
+
+ // Instantiate the request class
+ $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
+
+ // Update RequestCore settings
+ $request->request_class = $this->request_class;
+ $request->response_class = $this->response_class;
+ $request->ssl_verification = $this->ssl_verification;
+
+ // Pass along registered stream callbacks
+ if ($this->registered_streaming_read_callback)
+ {
+ $request->register_streaming_read_callback($this->registered_streaming_read_callback);
+ }
+
+ if ($this->registered_streaming_write_callback)
+ {
+ $request->register_streaming_write_callback($this->registered_streaming_write_callback);
+ }
+
+ // Streaming uploads
+ if (isset($opt['fileUpload']))
+ {
+ if (is_resource($opt['fileUpload']))
+ {
+ // Determine the length to read from the stream
+ $length = null; // From current position until EOF by default, size determined by set_read_stream()
+
+ if (isset($headers['Content-Length']))
+ {
+ $length = $headers['Content-Length'];
+ }
+ elseif (isset($opt['seekTo']))
+ {
+ // Read from seekTo until EOF by default
+ $stats = fstat($opt['fileUpload']);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $length = $stats['size'] - (integer) $opt['seekTo'];
+ }
+ }
+
+ $request->set_read_stream($opt['fileUpload'], $length);
+
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $headers['Content-Type'] = 'application/octet-stream';
+ }
+ }
+ else
+ {
+ $request->set_read_file($opt['fileUpload']);
+
+ // Determine the length to read from the file
+ $length = $request->read_stream_size; // The file size by default
+
+ if (isset($headers['Content-Length']))
+ {
+ $length = $headers['Content-Length'];
+ }
+ elseif (isset($opt['seekTo']) && isset($length))
+ {
+ // Read from seekTo until EOF by default
+ $length -= (integer) $opt['seekTo'];
+ }
+
+ $request->set_read_stream_size($length);
+
+ // Attempt to guess the correct mime-type
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $extension = explode('.', $opt['fileUpload']);
+ $extension = array_pop($extension);
+ $mime_type = CFMimeTypes::get_mimetype($extension);
+ $headers['Content-Type'] = $mime_type;
+ }
+ }
+
+ $headers['Content-Length'] = $request->read_stream_size;
+ $headers['Content-MD5'] = '';
+ }
+
+ // Handle streaming file offsets
+ if (isset($opt['seekTo']))
+ {
+ // Pass the seek position to RequestCore
+ $request->set_seek_position((integer) $opt['seekTo']);
+ }
+
+ // Streaming downloads
+ if (isset($opt['fileDownload']))
+ {
+ if (is_resource($opt['fileDownload']))
+ {
+ $request->set_write_stream($opt['fileDownload']);
+ }
+ else
+ {
+ $request->set_write_file($opt['fileDownload']);
+ }
+ }
+
+ $curlopts = array();
+
+ // Set custom CURLOPT settings
+ if (isset($opt['curlopts']))
+ {
+ $curlopts = $opt['curlopts'];
+ }
+
+ // Debug mode
+ if ($this->debug_mode)
+ {
+ $curlopts[CURLOPT_VERBOSE] = true;
+ }
+
+ // Set the curl options.
+ if (count($curlopts))
+ {
+ $request->set_curlopts($curlopts);
+ }
+
+ // Do we have a verb?
+ if (isset($opt['verb']))
+ {
+ $request->set_method($opt['verb']);
+ $string_to_sign .= $opt['verb'] . "\n";
+ }
+
+ // Add headers and content when we have a body
+ if (isset($opt['body']))
+ {
+ $request->set_body($opt['body']);
+ $headers['Content-Length'] = strlen($opt['body']);
+
+ if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
+ {
+ $headers['Content-Type'] = 'application/octet-stream';
+ }
+
+ if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
+ {
+ $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
+ }
+ }
+
+ // Handle query-string authentication
+ if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ {
+ unset($headers['Date']);
+ $headers['Content-Type'] = '';
+ $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
+ }
+
+ // Sort headers
+ uksort($headers, 'strnatcasecmp');
+
+ // Add headers to request and compute the string to sign
+ foreach ($headers as $header_key => $header_value)
+ {
+ // Strip linebreaks from header values as they're illegal and can allow for security issues
+ $header_value = str_replace(array("\r", "\n"), '', $header_value);
+
+ // Add the header if it has a value
+ if ($header_value !== '')
+ {
+ $request->add_header($header_key, $header_value);
+ }
+
+ // Generate the string to sign
+ if (
+ strtolower($header_key) === 'content-md5' ||
+ strtolower($header_key) === 'content-type' ||
+ strtolower($header_key) === 'date' ||
+ (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ )
+ {
+ $string_to_sign .= $header_value . "\n";
+ }
+ elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
+ {
+ $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+ }
+ }
+
+ // Add the signable resource location
+ $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
+ $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource . urldecode($signable_query_string);
+
+ // Hash the AWS secret key and generate a signature for the request.
+ $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
+ $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
+
+ // If we're generating a URL, return the URL to the calling method.
+ if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
+ {
+ $query_params = array(
+ 'AWSAccessKeyId' => $this->key,
+ 'Expires' => $headers['Expires'],
+ 'Signature' => $signature,
+ );
+
+ // If using short-term credentials, add the token to the query string
+ if ($this->auth_token)
+ {
+ $query_params['x-amz-security-token'] = $this->auth_token;
+ }
+
+ return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
+ }
+ elseif (isset($opt['preauth']))
+ {
+ return $this->request_url;
+ }
+
+ /*%******************************************************************************************%*/
+
+ // If our changes were temporary, reset them.
+ if ($this->temporary_prefix)
+ {
+ $this->temporary_prefix = false;
+ $this->resource_prefix = null;
+ }
+
+ // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
+ if ($this->use_batch_flow)
+ {
+ $handle = $request->prep_request();
+ $this->batch_object->add($handle);
+ $this->use_batch_flow = false;
+
+ return $handle;
+ }
+ elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
+ {
+ return $request->prep_request();
+ }
+
+ // Send!
+ $request->send_request();
+
+ // Prepare the response
+ $headers = $request->get_response_header();
+ $headers['x-aws-request-url'] = $this->request_url;
+ $headers['x-aws-redirects'] = $this->redirects;
+ $headers['x-aws-stringtosign'] = $string_to_sign;
+ $headers['x-aws-requestheaders'] = $request->request_headers;
+
+ // Did we have a request body?
+ if (isset($opt['body']))
+ {
+ $headers['x-aws-requestbody'] = $opt['body'];
+ }
+
+ $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
+
+ // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
+ // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
+ // @codeCoverageIgnoreStart
+ if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
+ {
+ $this->redirects++;
+ $opt['location'] = $headers['location'];
+ $data = $this->authenticate($bucket, $opt);
+ }
+
+ // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
+ elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
+ {
+ if ($this->redirects <= $this->max_retries)
+ {
+ // Exponential backoff
+ $delay = (integer) (pow(4, $this->redirects) * 100000);
+ usleep($delay);
+ $this->redirects++;
+ $data = $this->authenticate($bucket, $opt);
+ }
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Return!
+ $this->redirects = 0;
+ return $data;
+ }
+
+ /**
+ * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
+ * method is leveraged by any method that creates buckets.
+ *
+ * @param string $bucket (Required) The name of the bucket to validate.
+ * @return boolean Whether or not the specified Amazon S3 bucket name is valid for DNS-style access. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
+ */
+ public function validate_bucketname_create($bucket)
+ {
+ // list_buckets() uses this. Let it pass.
+ if ($bucket === '') return true;
+
+ if (
+ ($bucket === null || $bucket === false) || // Must not be null or false
+ preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
+ !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
+ !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
+ (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
+ (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
+ (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
+ preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
+ preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
+ ) return false;
+
+ return true;
+ }
+
+ /**
+ * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
+ * method is leveraged by any method that reads from buckets.
+ *
+ * @param string $bucket (Required) The name of the bucket to validate.
+ * @return boolean Whether or not the bucket name is valid. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
+ */
+ public function validate_bucketname_support($bucket)
+ {
+ // list_buckets() uses this. Let it pass.
+ if ($bucket === '') return true;
+
+ // Validate
+ if (
+ ($bucket === null || $bucket === false) || // Must not be null or false
+ preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
+ !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
+ !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
+ preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
+ ) return false;
+
+ return true;
+ }
+
+ /*%******************************************************************************************%*/
+ // SETTERS
+
+ /**
+ * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
+ * <enable_path_style()>.
+ *
+ * @param string $region (Required) The region to use for subsequent Amazon S3 operations. For a complete list of REGION constants, see the <code>AmazonS3</code> Constants page in the API reference.
+ * @return $this A reference to the current instance.
+ */
+ public function set_region($region)
+ {
+ // @codeCoverageIgnoreStart
+ $this->set_hostname($region);
+
+ switch ($region)
+ {
+ case self::REGION_US_E1: // Northern Virginia
+ $this->enable_path_style(false);
+ break;
+
+ case self::REGION_EU_W1: // Ireland
+ $this->enable_path_style(); // Always use path-style access for EU endpoint.
+ break;
+
+ default:
+ $this->enable_path_style(false);
+ break;
+
+ }
+ // @codeCoverageIgnoreEnd
+
+ return $this;
+ }
+
+ /**
+ * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
+ *
+ * @param string $vhost (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
+ * @return $this A reference to the current instance.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html Virtual Hosting of Buckets
+ */
+ public function set_vhost($vhost)
+ {
+ $this->vhost = $vhost;
+ return $this;
+ }
+
+ /**
+ * Enables the use of the older path-style URI access for all requests.
+ *
+ * @param string $style (Optional) Whether or not to enable path-style URI access for all requests. The default value is <code>true</code>.
+ * @return $this A reference to the current instance.
+ */
+ public function enable_path_style($style = true)
+ {
+ $this->path_style = $style;
+ return $this;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET METHODS
+
+ /**
+ * Creates an Amazon S3 bucket.
+ *
+ * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
+ * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
+ * However, bucket names must be unique across all of Amazon S3.
+ *
+ * @param string $bucket (Required) The name of the bucket to create.
+ * @param string $region (Required) The preferred geographical location for the bucket. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`, `AmazonS3::REGION_APAC_NE1`]
+ * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/UsingBucket.html Working with Amazon S3 Buckets
+ */
+ public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // If the bucket contains uppercase letters...
+ if (preg_match('/[A-Z]/', $bucket))
+ {
+ // Throw a warning
+ trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
+
+ // Force the bucketname to lowercase
+ $bucket = strtolower($bucket);
+ }
+
+ // Validate the S3 bucket name for creation
+ if (!$this->validate_bucketname_create($bucket))
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception('"' . $bucket . '" is not DNS-valid (i.e., <bucketname>.s3.amazonaws.com), and cannot be used as an S3 bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
+ // @codeCoverageIgnoreEnd
+ }
+
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml',
+ 'x-amz-acl' => $acl
+ );
+
+ // Defaults
+ $this->set_region($region); // Also sets path-style
+ $xml = simplexml_load_string($this->base_location_constraint);
+
+ switch ($region)
+ {
+ case self::REGION_US_E1: // Northern Virginia
+ $opt['body'] = '';
+ break;
+
+ case self::REGION_EU_W1: // Ireland
+ $xml->LocationConstraint = 'EU';
+ $opt['body'] = $xml->asXML();
+ break;
+
+ default:
+ $xml->LocationConstraint = str_replace(array('s3-', '.amazonaws.com'), '', $region);
+ $opt['body'] = $xml->asXML();
+ break;
+ }
+
+ $response = $this->authenticate($bucket, $opt);
+
+ // Make sure we're set back to DNS-style URLs
+ $this->enable_path_style(false);
+
+ return $response;
+ }
+
+ /**
+ * Gets the region in which the specified Amazon S3 bucket is located.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_region($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'location';
+
+ // Authenticate to S3
+ $response = $this->authenticate($bucket, $opt);
+
+ if ($response->isOK())
+ {
+ // Handle body
+ $response->body = (string) $response->body;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Gets the HTTP headers for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_headers($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'HEAD';
+
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be deleted.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param boolean $force (Optional) Whether to force-delete the bucket and all of its contents. The default value is <code>false</code>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return mixed A <CFResponse> object if the bucket was deleted successfully. Returns boolean <code>false</code> if otherwise.
+ */
+ public function delete_bucket($bucket, $force = false, $opt = null)
+ {
+ // Set default value
+ $success = true;
+
+ if ($force)
+ {
+ // Delete all of the items from the bucket.
+ $success = $this->delete_all_object_versions($bucket);
+ }
+
+ // As long as we were successful...
+ if ($success)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+
+ return $this->authenticate($bucket, $opt);
+ }
+
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets a list of all buckets contained in the caller's Amazon S3 account.
+ *
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_buckets($opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+
+ return $this->authenticate('', $opt);
+ }
+
+ /**
+ * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function get_bucket_acl($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'acl';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'acl';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Make sure these are defined.
+ // @codeCoverageIgnoreStart
+ if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
+ {
+ // Fetch the data live.
+ $canonical = $this->get_canonical_user_id();
+ $this->credentials->canonical_id = $canonical['id'];
+ $this->credentials->canonical_name = $canonical['display_name'];
+ }
+ // @codeCoverageIgnoreEnd
+
+ if (is_array($acl))
+ {
+ $opt['body'] = $this->generate_access_policy($this->credentials->canonical_id, $this->credentials->canonical_name, $acl);
+ }
+ else
+ {
+ $opt['body'] = '';
+ $opt['headers']['x-amz-acl'] = $acl;
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // OBJECT METHODS
+
+ /**
+ * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
+ *
+ * Each standard object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
+ * to multiple storage servers in multiple data centers. This ensures the data remains available in the
+ * event of internal network or hardware failure.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>body</code> - <code>string</code> - Required; Conditional - The data to be stored in the object. Either this parameter or <code>fileUpload</code> must be specified.</li>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required; Conditional - The URL/path for the file to upload, or an open resource. Either this parameter or <code>body</code> is required.</li>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent in the body. If a file is being uploaded via <code>fileUpload</code> as a file system path, it will attempt to determine the correct mime-type based on the file extension. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the object in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Represented by <code>x-amz-meta-:</code>. Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes within the file/stream to upload from.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function create_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ // Handle content type. Can also be passed as an HTTP header.
+ if (isset($opt['contentType']))
+ {
+ $opt['headers']['Content-Type'] = $opt['contentType'];
+ unset($opt['contentType']);
+ }
+
+ // Handle Access Control Lists. Can also be passed as an HTTP header.
+ if (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ $opt['headers']['Expect'] = '100-continue';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the contents of an Amazon S3 object in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>etag</code> - <code>string</code> - Optional - The <code>ETag</code> header passed in from a previous request. If specified, request <code>LastModified</code> option must be specified as well. Will trigger a <code>304 Not Modified</code> status code if the file hasn't changed.</li>
+ * <li><code>fileDownload</code> - <code>string|resource</code> - Optional - The file system location to download the file to, or an open file resource. Must be a server-writable location.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>lastmodified</code> - <code>string</code> - Optional - The <code>LastModified</code> header passed in from a previous request. If specified, request <code>ETag</code> option must be specified as well. Will trigger a <code>304 Not Modified</code> status code if the file hasn't changed.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>range</code> - <code>string</code> - Optional - The range of bytes to fetch from the object. Specify this parameter when downloading partial bits or completing incomplete object downloads. The specified range must be notated with a hyphen (e.g., 0-10485759). Defaults to the byte range of the complete Amazon S3 object.</li>
+ * <li><code>response</code> - <code>array</code> - Optional - Allows adjustments to specific response headers. Pass an associative array where each key is one of the following: <code>cache-control</code>, <code>content-disposition</code>, <code>content-encoding</code>, <code>content-language</code>, <code>content-type</code>, <code>expires</code>. The <code>expires</code> value should use <php:gmdate()> and be formatted with the <code>DATE_RFC2822</code> constant.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+
+ if (!isset($opt['headers']) || !is_array($opt['headers']))
+ {
+ $opt['headers'] = array();
+ }
+
+ if (isset($opt['lastmodified']))
+ {
+ $opt['headers']['If-Modified-Since'] = $opt['lastmodified'];
+ }
+
+ if (isset($opt['etag']))
+ {
+ $opt['headers']['If-None-Match'] = $opt['etag'];
+ }
+
+ // Partial content range
+ if (isset($opt['range']))
+ {
+ $opt['headers']['Range'] = 'bytes=' . $opt['range'];
+ }
+
+ // GET responses
+ if (isset($opt['response']))
+ {
+ foreach ($opt['response'] as $key => $value)
+ {
+ $opt['response-' . $key] = $value;
+ unset($opt['response'][$key]);
+ }
+ }
+
+ // Authenticate to S3
+ $this->parse_the_response = false;
+ $response = $this->authenticate($bucket, $opt);
+ $this->parse_the_response = true;
+
+ return $response;
+ }
+
+ /**
+ * Gets the HTTP headers for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_object_headers($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'HEAD';
+ $opt['resource'] = $filename;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes an Amazon S3 object from the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to delete. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function delete_object($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['resource'] = $filename;
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']))
+ {
+ $opt['headers'] = array(
+ 'x-amz-mfa' => ($opt['MFASerial'] . ' ' . $opt['MFAToken'])
+ );
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes two or more specified Amazon S3 objects from the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>objects</code> - <code>array</code> - Required - The object references to delete from the bucket. <ul>
+ * <li><code>key</code> - <code>string</code> - Required - The name of the object (e.g., the "key") to delete. This should include the entire file path including all "subdirectories".</li>
+ * <li><code>version_id</code> - <code>string</code> - Optional - If the object is versioned, include the version ID to delete.</li>
+ * </ul></li>
+ * <li><code>quiet</code> - <code>boolean</code> - Optional - Whether or not Amazon S3 should use "Quiet" mode for this operation. A value of <code>true</code> will enable Quiet mode. A value of <code>false</code> will use Verbose mode. The default value is <code>false</code>.</li>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code> and <code>MFAToken</code> must both be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function delete_objects($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'POST';
+ $opt['sub_resource'] = 'delete';
+ $opt['body'] = '';
+
+ // Bail out
+ if (!isset($opt['objects']) || !is_array($opt['objects']))
+ {
+ throw new S3_Exception('The ' . __FUNCTION__ . ' method requires the "objects" option to be set as an array.');
+ }
+
+ $xml = new SimpleXMLElement($this->multi_object_delete_xml);
+
+ // Add the objects
+ foreach ($opt['objects'] as $object)
+ {
+ $xobject = $xml->addChild('Object');
+ $xobject->addChild('Key', $object['key']);
+
+ if (isset($object['version_id']))
+ {
+ $xobject->addChild('VersionId', $object['version_id']);
+ }
+ }
+
+ // Quiet mode?
+ if (isset($opt['quiet']))
+ {
+ $quiet = 'false';
+ if (is_bool($opt['quiet'])) // Boolean
+ {
+ $quiet = $opt['quiet'] ? 'true' : 'false';
+ }
+ elseif (is_string($opt['quiet'])) // String
+ {
+ $quiet = ($opt['quiet'] === 'true') ? 'true' : 'false';
+ }
+
+ $xml->addChild('Quiet', $quiet);
+ }
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']))
+ {
+ $opt['headers'] = array(
+ 'x-amz-mfa' => ($opt['MFASerial'] . ' ' . $opt['MFAToken'])
+ );
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets a list of all Amazon S3 objects in the specified bucket.
+ *
+ * NOTE: <strong>This method is paginated</strong>, and will not return more than <code>max-keys</code> keys. If you want to retrieve a list of all keys, you will need to make multiple calls to this function using the <code>marker</code> option to specify the pagination offset (the key of the last processed key--lexically ordered) and the <code>IsTruncated</code> response key to detect when all results have been processed. See: <a href="http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTBucketGET.html">the S3 REST documentation for get_bucket</a> for more information.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the marker.</li>
+ * <li><code>max-keys</code> - <code>string</code> - Optional - The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return fewer. The default value is 1000.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to contain results that begin only with the specified prefix.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_objects($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+
+ foreach (array('delimiter', 'marker', 'max-keys', 'prefix') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Copies an Amazon S3 object to a new location, whether in the same Amazon S3 region, bucket, or otherwise.
+ *
+ * @param array $source (Required) The bucket and file name to copy from. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket containing the source object.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name of the source object to copy.</li></ul>
+ * @param array $dest (Required) The bucket and file name to copy to. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket to copy the object to.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name to copy the object to.</li></ul>
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to copy. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>ifMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) matches the specified tag; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifUnmodifiedSince</code>.</li>
+ * <li><code>ifUnmodifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it hasn't been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifMatch</code>.</li>
+ * <li><code>ifNoneMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) is different than the specified ETag; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifModifiedSince</code>.</li>
+ * <li><code>ifModifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it has been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifNoneMatch</code>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - Associative array of key-value pairs. Represented by <code>x-amz-meta-:</code> Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>metadataDirective</code> - <code>string</code> - Optional - Accepts either COPY or REPLACE. You will likely never need to use this, as it manages itself with no issues.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/API/RESTObjectCOPY.html Copying Amazon S3 Objects
+ */
+ public function copy_object($source, $dest, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $batch = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $dest['filename'];
+ $opt['body'] = '';
+
+ // Handle copy source
+ if (isset($source['bucket']) && isset($source['filename']))
+ {
+ $opt['headers']['x-amz-copy-source'] = '/' . $source['bucket'] . '/' . rawurlencode($source['filename'])
+ . (isset($opt['versionId']) ? ('?' . 'versionId=' . rawurlencode($opt['versionId'])) : ''); // Append the versionId to copy, if available
+ unset($opt['versionId']);
+
+ // Determine if we need to lookup the pre-existing content-type.
+ if (
+ (!$this->use_batch_flow && !isset($opt['returnCurlHandle'])) &&
+ !in_array(strtolower('content-type'), array_map('strtolower', array_keys($opt['headers'])))
+ )
+ {
+ $response = $this->get_object_headers($source['bucket'], $source['filename']);
+ if ($response->isOK())
+ {
+ $opt['headers']['Content-Type'] = $response->header['content-type'];
+ }
+ }
+ }
+
+ // Handle metadata directive
+ $opt['headers']['x-amz-metadata-directive'] = 'COPY';
+ if ($source['bucket'] === $dest['bucket'] && $source['filename'] === $dest['filename'])
+ {
+ $opt['headers']['x-amz-metadata-directive'] = 'REPLACE';
+ }
+ if (isset($opt['metadataDirective']))
+ {
+ $opt['headers']['x-amz-metadata-directive'] = $opt['metadataDirective'];
+ unset($opt['metadataDirective']);
+ }
+
+ // Handle Access Control Lists. Can also pass canned ACLs as an HTTP header.
+ if (isset($opt['acl']) && is_array($opt['acl']))
+ {
+ $batch[] = $this->set_object_acl($dest['bucket'], $dest['filename'], $opt['acl'], array(
+ 'returnCurlHandle' => true
+ ));
+ unset($opt['acl']);
+ }
+ elseif (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle conditional-copy parameters
+ if (isset($opt['ifMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-match'] = $opt['ifMatch'];
+ unset($opt['ifMatch']);
+ }
+ if (isset($opt['ifNoneMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-none-match'] = $opt['ifNoneMatch'];
+ unset($opt['ifNoneMatch']);
+ }
+ if (isset($opt['ifUnmodifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-unmodified-since'] = $opt['ifUnmodifiedSince'];
+ unset($opt['ifUnmodifiedSince']);
+ }
+ if (isset($opt['ifModifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-modified-since'] = $opt['ifModifiedSince'];
+ unset($opt['ifModifiedSince']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ // Authenticate to S3
+ $response = $this->authenticate($dest['bucket'], $opt);
+
+ // Attempt to reset ACLs
+ $http = new RequestCore();
+ $http->send_multi_request($batch);
+
+ return $response;
+ }
+
+ /**
+ * Updates an Amazon S3 object with new headers or other metadata. To replace the content of the
+ * specified Amazon S3 object, call <create_object()> with the same bucket and file name parameters.
+ *
+ * @param string $bucket (Required) The name of the bucket that contains the source file.
+ * @param string $filename (Required) The source file name that you want to update.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <ACL_PRIVATE>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header with the <code>x-amz-meta-</code> prefix is considered user metadata and is stored with the Amazon S3 object. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/API/RESTObjectCOPY.html Copying Amazon S3 Objects
+ */
+ public function update_object($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['metadataDirective'] = 'REPLACE';
+
+ // Authenticate to S3
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ACCESS CONTROL LISTS
+
+ /**
+ * Gets the access control list (ACL) settings for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function get_object_acl($bucket, $filename, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'acl';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Sets the access control list (ACL) settings for the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $acl (Optional) The ACL settings for the specified object. Accepts any of the following constants: [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function set_object_acl($bucket, $filename, $acl = self::ACL_PRIVATE, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'acl';
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ContentType'])
+ {
+ $opt['headers']['Content-Type'] = $metadata['ContentType'];
+ }
+ if ($metadata && $metadata['StorageClass'])
+ {
+ $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
+ }
+
+ // Make sure these are defined.
+ // @codeCoverageIgnoreStart
+ if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
+ {
+ // Fetch the data live.
+ $canonical = $this->get_canonical_user_id();
+ $this->credentials->canonical_id = $canonical['id'];
+ $this->credentials->canonical_name = $canonical['display_name'];
+ }
+ // @codeCoverageIgnoreEnd
+
+ if (is_array($acl))
+ {
+ $opt['body'] = $this->generate_access_policy($this->credentials->canonical_id, $this->credentials->canonical_name, $acl);
+ }
+ else
+ {
+ $opt['body'] = '';
+ $opt['headers']['x-amz-acl'] = $acl;
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Generates the XML to be used for the Access Control Policy.
+ *
+ * @param string $canonical_id (Required) The canonical ID for the bucket owner. This is provided as the `id` return value from <get_canonical_user_id()>.
+ * @param string $canonical_name (Required) The canonical display name for the bucket owner. This is provided as the `display_name` value from <get_canonical_user_id()>.
+ * @param array $users (Optional) An array of associative arrays. Each associative array contains an `id` value and a `permission` value.
+ * @return string Access Control Policy XML.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_ACLs.html Access Control Lists
+ */
+ public function generate_access_policy($canonical_id, $canonical_name, $users)
+ {
+ $xml = simplexml_load_string($this->base_acp_xml);
+ $owner = $xml->addChild('Owner');
+ $owner->addChild('ID', $canonical_id);
+ $owner->addChild('DisplayName', $canonical_name);
+ $acl = $xml->addChild('AccessControlList');
+
+ foreach ($users as $user)
+ {
+ $grant = $acl->addChild('Grant');
+ $grantee = $grant->addChild('Grantee');
+
+ switch ($user['id'])
+ {
+ // Authorized Users
+ case self::USERS_AUTH:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_AUTH);
+ break;
+
+ // All Users
+ case self::USERS_ALL:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_ALL);
+ break;
+
+ // The Logging User
+ case self::USERS_LOGGING:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_LOGGING);
+ break;
+
+ // Email Address or Canonical Id
+ default:
+ if (strpos($user['id'], '@'))
+ {
+ $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('EmailAddress', $user['id']);
+ }
+ else
+ {
+ // Assume Canonical Id
+ $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('ID', $user['id']);
+ }
+ break;
+ }
+
+ $grant->addChild('Permission', $user['permission']);
+ }
+
+ return $xml->asXML();
+ }
+
+
+ /*%******************************************************************************************%*/
+ // LOGGING METHODS
+
+ /**
+ * Gets the access logs associated with the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use. Pass a `null` value when using the <set_vhost()> method.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/ServerLogs.html Server Access Logging
+ */
+ public function get_logs($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'logging';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Enables access logging for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to enable logging for. Pass a `null` value when using the <set_vhost()> method.
+ * @param string $target_bucket (Required) The name of the bucket to store the logs in.
+ * @param string $target_prefix (Required) The prefix to give to the log file names.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>users</code> - <code>array</code> - Optional - An array of associative arrays specifying any user to give access to. Each associative array contains an <code>id</code> and <code>permission</code> value.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/LoggingAPI.html Server Access Logging Configuration API
+ */
+ public function enable_logging($bucket, $target_bucket, $target_prefix, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'logging';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_logging_xml);
+ $LoggingEnabled = $xml->addChild('LoggingEnabled');
+ $LoggingEnabled->addChild('TargetBucket', $target_bucket);
+ $LoggingEnabled->addChild('TargetPrefix', $target_prefix);
+ $TargetGrants = $LoggingEnabled->addChild('TargetGrants');
+
+ if (isset($opt['users']) && is_array($opt['users']))
+ {
+ foreach ($opt['users'] as $user)
+ {
+ $grant = $TargetGrants->addChild('Grant');
+ $grantee = $grant->addChild('Grantee');
+
+ switch ($user['id'])
+ {
+ // Authorized Users
+ case self::USERS_AUTH:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_AUTH);
+ break;
+
+ // All Users
+ case self::USERS_ALL:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_ALL);
+ break;
+
+ // The Logging User
+ case self::USERS_LOGGING:
+ $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('URI', self::USERS_LOGGING);
+ break;
+
+ // Email Address or Canonical Id
+ default:
+ if (strpos($user['id'], '@'))
+ {
+ $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('EmailAddress', $user['id']);
+ }
+ else
+ {
+ // Assume Canonical Id
+ $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
+ $grantee->addChild('ID', $user['id']);
+ }
+ break;
+ }
+
+ $grant->addChild('Permission', $user['permission']);
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Disables access logging for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use. Pass `null` if using <set_vhost()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/LoggingAPI.html Server Access Logging Configuration API
+ */
+ public function disable_logging($bucket, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'logging';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+ $opt['body'] = $this->base_logging_xml;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONVENIENCE METHODS
+
+ /**
+ * Gets whether or not the specified Amazon S3 bucket exists in Amazon S3. This includes buckets
+ * that do not belong to the caller.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return boolean A value of <code>true</code> if the bucket exists, or a value of <code>false</code> if it does not.
+ */
+ public function if_bucket_exists($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $header = $this->get_bucket_headers($bucket);
+ return (bool) $header->isOK();
+ }
+
+ /**
+ * Gets whether or not the specified Amazon S3 object exists in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @return boolean A value of <code>true</code> if the object exists, or a value of <code>false</code> if it does not.
+ */
+ public function if_object_exists($bucket, $filename)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $header = $this->get_object_headers($bucket, $filename);
+
+ if ($header->isOK()) { return true; }
+ elseif ($header->status === 404) { return false; }
+
+ // @codeCoverageIgnoreStart
+ return null;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets whether or not the specified Amazon S3 bucket has a bucket policy associated with it.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return boolean A value of <code>true</code> if a bucket policy exists, or a value of <code>false</code> if one does not.
+ */
+ public function if_bucket_policy_exists($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ $response = $this->get_bucket_policy($bucket);
+
+ if ($response->isOK()) { return true; }
+ elseif ($response->status === 404) { return false; }
+
+ // @codeCoverageIgnoreStart
+ return null;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets the number of Amazon S3 objects in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @return integer The number of Amazon S3 objects in the bucket.
+ */
+ public function get_bucket_object_count($bucket)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ return count($this->get_object_list($bucket));
+ }
+
+ /**
+ * Gets the cumulative file size of the contents of the Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param boolean $friendly_format (Optional) A value of <code>true</code> will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of <code>false</code> will format the return value as the raw number of bytes.
+ * @return integer|string The number of bytes as an integer, or the friendly format as a string.
+ */
+ public function get_bucket_filesize($bucket, $friendly_format = false)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $filesize = 0;
+ $list = $this->list_objects($bucket);
+
+ foreach ($list->body->Contents as $filename)
+ {
+ $filesize += (integer) $filename->Size;
+ }
+
+ while ((string) $list->body->IsTruncated === 'true')
+ {
+ $body = (array) $list->body;
+ $list = $this->list_objects($bucket, array(
+ 'marker' => (string) end($body['Contents'])->Key
+ ));
+
+ foreach ($list->body->Contents as $object)
+ {
+ $filesize += (integer) $object->Size;
+ }
+ }
+
+ if ($friendly_format)
+ {
+ $filesize = $this->util->size_readable($filesize);
+ }
+
+ return $filesize;
+ }
+
+ /**
+ * Gets the file size of the specified Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param boolean $friendly_format (Optional) A value of <code>true</code> will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of <code>false</code> will format the return value as the raw number of bytes.
+ * @return integer|string The number of bytes as an integer, or the friendly format as a string.
+ */
+ public function get_object_filesize($bucket, $filename, $friendly_format = false)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $object = $this->get_object_headers($bucket, $filename);
+ $filesize = (integer) $object->header['content-length'];
+
+ if ($friendly_format)
+ {
+ $filesize = $this->util->size_readable($filesize);
+ }
+
+ return $filesize;
+ }
+
+ /**
+ * Changes the content type for an existing Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $contentType (Required) The content-type to apply to the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function change_content_type($bucket, $filename, $contentType, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ACL'])
+ {
+ $opt['acl'] = $metadata['ACL'];
+ }
+ if ($metadata && $metadata['StorageClass'])
+ {
+ $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
+ }
+
+ // Merge optional parameters
+ $opt = array_merge_recursive(array(
+ 'headers' => array(
+ 'Content-Type' => $contentType
+ ),
+ 'metadataDirective' => 'COPY'
+ ), $opt);
+
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+ /**
+ * Changes the storage redundancy for an existing object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $storage (Required) The storage setting to apply to the object. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function change_storage_redundancy($bucket, $filename, $storage, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Retrieve the original metadata
+ $metadata = $this->get_object_metadata($bucket, $filename);
+ if ($metadata && $metadata['ACL'])
+ {
+ $opt['acl'] = $metadata['ACL'];
+ }
+ if ($metadata && $metadata['ContentType'])
+ {
+ $opt['headers']['Content-Type'] = $metadata['ContentType'];
+ }
+
+ // Merge optional parameters
+ $opt = array_merge(array(
+ 'storage' => $storage,
+ 'metadataDirective' => 'COPY',
+ ), $opt);
+
+ return $this->copy_object(
+ array('bucket' => $bucket, 'filename' => $filename),
+ array('bucket' => $bucket, 'filename' => $filename),
+ $opt
+ );
+ }
+
+ /**
+ * Gets a simplified list of bucket names on an Amazon S3 account.
+ *
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the bucket names against.
+ * @return array The list of matching bucket names. If there are no results, the method will return an empty array.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function get_bucket_list($pcre = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ // Get a list of buckets.
+ $list = $this->list_buckets();
+ if ($list = $list->body->query('descendant-or-self::Name'))
+ {
+ $list = $list->map_string($pcre);
+ return $list;
+ }
+
+ // @codeCoverageIgnoreStart
+ return array();
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * Gets a simplified list of Amazon S3 object file names contained in a bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the marker.</li>
+ * <li><code>max-keys</code> - <code>integer</code> - Optional - The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return less. A value of zero is treated as if you did not specify max-keys.</li>
+ * <li><code>pcre</code> - <code>string</code> - Optional - A Perl-Compatible Regular Expression (PCRE) to filter the names against. This is applied only AFTER any native Amazon S3 filtering from specified <code>prefix</code>, <code>marker</code>, <code>max-keys</code>, or <code>delimiter</code> values are applied.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to contain results that begin only with the specified prefix.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * @return array The list of matching object names. If there are no results, the method will return an empty array.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function get_object_list($bucket, $opt = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ if (!$opt) $opt = array();
+ unset($opt['returnCurlHandle']); // This would cause problems
+
+ // Set some default values
+ $pcre = isset($opt['pcre']) ? $opt['pcre'] : null;
+ $max_keys = (isset($opt['max-keys']) && is_int($opt['max-keys'])) ? $opt['max-keys'] : null;
+ $objects = array();
+
+ if (!$max_keys)
+ {
+ // No max-keys specified. Get everything.
+ do
+ {
+ $list = $this->list_objects($bucket, $opt);
+ if ($keys = $list->body->query('descendant-or-self::Key')->map_string($pcre))
+ {
+ $objects = array_merge($objects, $keys);
+ }
+
+ $body = (array) $list->body;
+ $opt = array_merge($opt, array(
+ 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
+ ((string) end($body['Contents'])->Key) :
+ ((string) $list->body->Contents->Key)
+ ));
+ }
+ while ((string) $list->body->IsTruncated === 'true');
+ }
+ else
+ {
+ // Max-keys specified. Approximate number of loops and make the requests.
+
+ $max_keys = $opt['max-keys'];
+ $loops = ceil($max_keys / 1000);
+
+ do
+ {
+ $list = $this->list_objects($bucket, $opt);
+ $keys = $list->body->query('descendant-or-self::Key')->map_string($pcre);
+
+ if ($count = count($keys))
+ {
+ $objects = array_merge($objects, $keys);
+
+ if ($count < 1000)
+ {
+ break;
+ }
+ }
+
+ if ($max_keys > 1000)
+ {
+ $max_keys -= 1000;
+ }
+
+ $body = (array) $list->body;
+ $opt = array_merge($opt, array(
+ 'max-keys' => $max_keys,
+ 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
+ ((string) end($body['Contents'])->Key) :
+ ((string) $list->body->Contents->Key)
+ ));
+ }
+ while (--$loops);
+ }
+
+ return $objects;
+ }
+
+ /**
+ * Deletes all Amazon S3 objects inside the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
+ * @return boolean A value of <code>true</code> means that all objects were successfully deleted. A value of <code>false</code> means that at least one object failed to delete.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function delete_all_objects($bucket, $pcre = self::PCRE_ALL)
+ {
+ // Collect all matches
+ $list = $this->get_object_list($bucket, array('pcre' => $pcre));
+
+ // As long as we have at least one match...
+ if (count($list) > 0)
+ {
+ $objects = array();
+
+ foreach ($list as $object)
+ {
+ $objects[] = array('key' => $object);
+ }
+
+ $batch = new CFBatchRequest();
+ $batch->use_credentials($this->credentials);
+
+ foreach (array_chunk($objects, 1000) as $object_set)
+ {
+ $this->batch($batch)->delete_objects($bucket, array(
+ 'objects' => $object_set
+ ));
+ }
+
+ $responses = $this->batch($batch)->send();
+ $is_ok = true;
+
+ foreach ($responses as $response)
+ {
+ if (!$response->isOK() || isset($response->body->Error))
+ {
+ $is_ok = false;
+ }
+ }
+
+ return $is_ok;
+ }
+
+ // If there are no matches, return true
+ return true;
+ }
+
+ /**
+ * Deletes all of the versions of all Amazon S3 objects inside the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
+ * @return boolean A value of <code>true</code> means that all object versions were successfully deleted. A value of <code>false</code> means that at least one object/version failed to delete.
+ * @link http://php.net/pcre Regular Expressions (Perl-Compatible)
+ */
+ public function delete_all_object_versions($bucket, $pcre = null)
+ {
+ // Instantiate
+ $versions = $this->list_bucket_object_versions($bucket);
+
+ // Gather all nodes together into a single array
+ if ($versions->body->DeleteMarker() && $versions->body->Version())
+ {
+ $markers = array_merge($versions->body->DeleteMarker()->getArrayCopy(), $versions->body->Version()->getArrayCopy());
+ }
+ elseif ($versions->body->DeleteMarker())
+ {
+ $markers = $versions->body->DeleteMarker()->getArrayCopy();
+ }
+ elseif ($versions->body->Version())
+ {
+ $markers = $versions->body->Version()->getArrayCopy();
+ }
+ else
+ {
+ $markers = array();
+ }
+
+ while ((string) $versions->body->IsTruncated === 'true')
+ {
+ $versions = $this->list_bucket_object_versions($bucket, array(
+ 'key-marker' => (string) $versions->body->NextKeyMarker
+ ));
+
+ // Gather all nodes together into a single array
+ if ($versions->body->DeleteMarker() && $versions->body->Version())
+ {
+ $markers = array_merge($markers, $versions->body->DeleteMarker()->getArrayCopy(), $versions->body->Version()->getArrayCopy());
+ }
+ elseif ($versions->body->DeleteMarker())
+ {
+ $markers = array_merge($markers, $versions->body->DeleteMarker()->getArrayCopy());
+ }
+ elseif ($versions->body->Version())
+ {
+ $markers = array_merge($markers, $versions->body->Version()->getArrayCopy());
+ }
+ }
+
+ $objects = array();
+
+ // Loop through markers
+ foreach ($markers as $marker)
+ {
+ if ($pcre)
+ {
+ if (preg_match($pcre, (string) $marker->Key))
+ {
+ $xx = array('key' => (string) $marker->Key);
+ if ((string) $marker->VersionId !== 'null')
+ {
+ $xx['version_id'] = (string) $marker->VersionId;
+ }
+ $objects[] = $xx;
+ unset($xx);
+ }
+ }
+ else
+ {
+ $xx = array('key' => (string) $marker->Key);
+ if ((string) $marker->VersionId !== 'null')
+ {
+ $xx['version_id'] = (string) $marker->VersionId;
+ }
+ $objects[] = $xx;
+ unset($xx);
+ }
+ }
+
+ $batch = new CFBatchRequest();
+ $batch->use_credentials($this->credentials);
+
+ foreach (array_chunk($objects, 1000) as $object_set)
+ {
+ $this->batch($batch)->delete_objects($bucket, array(
+ 'objects' => $object_set
+ ));
+ }
+
+ $responses = $this->batch($batch)->send();
+ $is_ok = true;
+
+ foreach ($responses as $response)
+ {
+ if (!$response->isOK() || isset($response->body->Error))
+ {
+ $is_ok = false;
+ }
+ }
+
+ return $is_ok;
+ }
+
+ /**
+ * Gets the collective metadata for the given Amazon S3 object.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the Amazon S3 object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to retrieve. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return mixed If the object exists, the method returns the collective metadata for the Amazon S3 object. If the object does not exist, the method returns boolean <code>false</code>.
+ */
+ public function get_object_metadata($bucket, $filename, $opt = null)
+ {
+ $batch = new CFBatchRequest();
+ $this->batch($batch)->get_object_acl($bucket, $filename); // Get ACL info
+ $this->batch($batch)->get_object_headers($bucket, $filename); // Get content-type
+ $this->batch($batch)->list_objects($bucket, array( // Get other metadata
+ 'max-keys' => 1,
+ 'prefix' => $filename
+ ));
+ $response = $this->batch($batch)->send();
+
+ // Fail if any requests were unsuccessful
+ if (!$response->areOK())
+ {
+ return false;
+ }
+
+ $data = array(
+ 'ACL' => array(),
+ 'ContentType' => null,
+ 'ETag' => null,
+ 'Headers' => null,
+ 'Key' => null,
+ 'LastModified' => null,
+ 'Owner' => array(),
+ 'Size' => null,
+ 'StorageClass' => null,
+ );
+
+ // Add the content type
+ $data['ContentType'] = (string) $response[1]->header['content-type'];
+
+ // Add the other metadata (including storage type)
+ $contents = json_decode(json_encode($response[2]->body->query('descendant-or-self::Contents')->first()), true);
+ $data = array_merge($data, (is_array($contents) ? $contents : array()));
+
+ // Add ACL info
+ $grants = $response[0]->body->query('descendant-or-self::Grant');
+ $max = count($grants);
+
+ // Add raw header info
+ $data['Headers'] = $response[1]->header;
+ foreach (array('_info', 'x-amz-id-2', 'x-amz-request-id', 'cneonction', 'server', 'content-length', 'content-type', 'etag') as $header)
+ {
+ unset($data['Headers'][$header]);
+ }
+ ksort($data['Headers']);
+
+ if (count($grants) > 0)
+ {
+ foreach ($grants as $grant)
+ {
+ $dgrant = array(
+ 'id' => (string) $this->util->try_these(array('ID', 'URI'), $grant->Grantee),
+ 'permission' => (string) $grant->Permission
+ );
+
+ $data['ACL'][] = $dgrant;
+ }
+ }
+
+ return $data;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // URLS
+
+ /**
+ * Gets the web-accessible URL for the Amazon S3 object or generates a time-limited signed request for
+ * a private file.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the Amazon S3 object.
+ * @param integer|string $preauth (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>https</code> - <code>boolean</code> - Optional - Set to <code>true</code> if you would like the URL be in https mode. Otherwise, the default behavior is always to use http regardless of your SSL settings.
+ * <li><code>method</code> - <code>string</code> - Optional - The HTTP method to use for the request. Defaults to a value of <code>GET</code>.</li>
+ * <li><code>response</code> - <code>array</code> - Optional - Allows adjustments to specific response headers. Pass an associative array where each key is one of the following: <code>cache-control</code>, <code>content-disposition</code>, <code>content-encoding</code>, <code>content-language</code>, <code>content-type</code>, <code>expires</code>. The <code>expires</code> value should use <php:gmdate()> and be formatted with the <code>DATE_RFC2822</code> constant.</li>
+ * <li><code>torrent</code> - <code>boolean</code> - Optional - A value of <code>true</code> will return a URL to a torrent of the Amazon S3 object. A value of <code>false</code> will return a non-torrent URL. Defaults to <code>false</code>.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return string The file URL, with authentication and/or torrent parameters if requested.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_QSAuth.html Using Query String Authentication
+ */
+ public function get_object_url($bucket, $filename, $preauth = 0, $opt = null)
+ {
+ // Add this to our request
+ if (!$opt) $opt = array();
+ $opt['verb'] = isset($opt['method']) ? $opt['method'] : 'GET';
+ $opt['resource'] = $filename;
+ $opt['preauth'] = $preauth;
+
+ if (isset($opt['torrent']) && $opt['torrent'])
+ {
+ $opt['sub_resource'] = 'torrent';
+ unset($opt['torrent']);
+ }
+
+ // GET responses
+ if (isset($opt['response']))
+ {
+ foreach ($opt['response'] as $key => $value)
+ {
+ $opt['response-' . $key] = $value;
+ unset($opt['response'][$key]);
+ }
+ }
+
+ // Determine whether or not to use SSL
+ $use_ssl = isset($opt['https']) ? (bool) $opt['https'] : false;
+ unset($opt['https']);
+ $current_use_ssl_setting = $this->use_ssl;
+
+ // Authenticate to S3
+ $this->use_ssl = $use_ssl;
+ $response = $this->authenticate($bucket, $opt);
+ $this->use_ssl = $current_use_ssl_setting;
+
+ return $response;
+ }
+
+ /**
+ * Gets the web-accessible URL to a torrent of the Amazon S3 object. The Amazon S3 object's access
+ * control list settings (ACL) MUST be set to <ACL_PUBLIC> for a valid URL to be returned.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param integer|string $preauth (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.
+ * @return string The torrent URL, with authentication parameters if requested.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?S3TorrentRetrieve.html Using BitTorrent to Retrieve Objects Stored in Amazon S3
+ */
+ public function get_torrent_url($bucket, $filename, $preauth = 0)
+ {
+ return $this->get_object_url($bucket, $filename, $preauth, array(
+ 'torrent' => true
+ ));
+ }
+
+
+ /*%******************************************************************************************%*/
+ // VERSIONING
+
+ /**
+ * Enables versioning support for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>MFASerial</code> - string (Optional) The serial number on the back of the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - string (Optional) The current token displayed on the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAStatus</code> - string (Optional) The MFA Delete status. Can be <code>Enabled</code> or <code>Disabled</code>. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function enable_versioning($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'versioning';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_versioning_xml);
+ $xml->addChild('Status', 'Enabled');
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
+ {
+ $xml->addChild('MfaDelete', $opt['MFAStatus']);
+ $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Disables versioning support for the specified Amazon S3 bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>MFASerial</code> - <code>string</code> - Optional - The serial number on the back of the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAToken</code> - <code>string</code> - Optional - The current token displayed on the Gemalto device. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>MFAStatus</code> - <code>string</code> - Optional - The MFA Delete status. Can be <code>Enabled</code> or <code>Disabled</code>. <code>MFASerial</code>, <code>MFAToken</code> and <code>MFAStatus</code> must all be set for MFA to work.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://aws.amazon.com/mfa/ Multi-Factor Authentication
+ */
+ public function disable_versioning($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'versioning';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_versioning_xml);
+ $xml->addChild('Status', 'Suspended');
+
+ // Enable MFA delete?
+ // @codeCoverageIgnoreStart
+ if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
+ {
+ $xml->addChild('MfaDelete', $opt['MFAStatus']);
+ $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
+ }
+ // @codeCoverageIgnoreEnd
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets an Amazon S3 bucket's versioning status.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_versioning_status($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'versioning';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets a list of all the versions of Amazon S3 objects in the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Unicode string parameter. Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>key-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>key-marker</code>.</li>
+ * <li><code>max-keys</code> - <code>string</code> - Optional - Limits the number of results returned in response to your query. Will return no more than this number of results, but possibly less.</li>
+ * <li><code>prefix</code> - <code>string</code> - Optional - Restricts the response to only contain results that begin with the specified prefix.</li>
+ * <li><code>version-id-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>version-id-marker</code>.</li>
+ * <li><code>preauth</code> - <code>integer|string</code> - Optional - Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with <php:strtotime()>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_bucket_object_versions($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'versions';
+
+ foreach (array('delimiter', 'key-marker', 'max-keys', 'prefix', 'version-id-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET POLICIES
+
+ /**
+ * Sets the policy sub-resource for the specified Amazon S3 bucket. The specified policy replaces any
+ * policy the bucket already has.
+ *
+ * To perform this operation, the caller must be authorized to set a policy for the bucket and have
+ * PutPolicy permissions. If the caller does not have PutPolicy permissions for the bucket, Amazon S3
+ * returns a `403 Access Denied` error. If the caller has the correct permissions but has not been
+ * authorized by the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param CFPolicy $policy (Required) The JSON policy to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/AccessPolicyLanguage.html Appendix: The Access Policy Language
+ */
+ public function set_bucket_policy($bucket, CFPolicy $policy, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'policy';
+ $opt['body'] = $policy->get_json();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the policy of the specified Amazon S3 bucket.
+ *
+ * To use this operation, the caller must have GetPolicy permissions for the specified bucket and must be
+ * the bucket owner. If the caller does not have GetPolicy permissions, this method will generate a
+ * `403 Access Denied` error. If the caller has the correct permissions but is not the bucket owner, this
+ * method will generate a `405 Method Not Allowed` error. If the bucket does not have a policy defined for
+ * it, this method will generate a `404 Policy Not Found` error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_bucket_policy($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'policy';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Deletes the bucket policy for the specified Amazon S3 bucket. To delete the policy, the caller must
+ * be the bucket owner and have `DeletePolicy` permissions for the specified bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response. If you do not have `DeletePolicy` permissions, Amazon S3 returns a `403 Access Denied` error. If you have the correct permissions, but are not the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error. If the bucket doesn't have a policy, Amazon S3 returns a `204 No Content` error.
+ */
+ public function delete_bucket_policy($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'policy';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // BUCKET NOTIFICATIONS
+
+ /**
+ * Enables notifications of specified events for an Amazon S3 bucket. Currently, the
+ * `s3:ReducedRedundancyLostObject` event is the only event supported for notifications. The
+ * `s3:ReducedRedundancyLostObject` event is triggered when Amazon S3 detects that it has lost all
+ * copies of an Amazon S3 object and can no longer service requests for that object.
+ *
+ * If the bucket owner and Amazon SNS topic owner are the same, the bucket owner has permission to
+ * publish notifications to the topic by default. Otherwise, the owner of the topic must create a
+ * policy to enable the bucket owner to publish to the topic.
+ *
+ * By default, only the bucket owner can configure notifications on a bucket. However, bucket owners
+ * can use bucket policies to grant permission to other users to set this configuration with the
+ * `s3:PutBucketNotification` permission.
+ *
+ * After a PUT operation is called to configure notifications on a bucket, Amazon S3 publishes a test
+ * notification to ensure that the topic exists and that the bucket owner has permission to publish
+ * to the specified topic. If the notification is successfully published to the SNS topic, the PUT
+ * operation updates the bucket configuration and returns the 200 OK responses with a
+ * `x-amz-sns-test-message-id` header containing the message ID of the test notification sent to topic.
+ *
+ * @param string $bucket (Required) The name of the bucket to create bucket notifications for.
+ * @param string $topic_arn (Required) The SNS topic ARN to send notifications to.
+ * @param string $event (Required) The event type to listen for.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function create_bucket_notification($bucket, $topic_arn, $event, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'notification';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->base_notification_xml);
+ $topic_config = $xml->addChild('TopicConfiguration');
+ $topic_config->addChild('Topic', $topic_arn);
+ $topic_config->addChild('Event', $event);
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Gets the notification configuration of a bucket. Currently, the `s3:ReducedRedundancyLostObject` event
+ * is the only event supported for notifications. The `s3:ReducedRedundancyLostObject` event is triggered
+ * when Amazon S3 detects that it has lost all replicas of a Reduced Redundancy Storage object and can no
+ * longer service requests for that object.
+ *
+ * If notifications are not enabled on the bucket, the operation returns an empty
+ * `NotificatonConfiguration` element.
+ *
+ * By default, you must be the bucket owner to read the notification configuration of a bucket. However,
+ * the bucket owner can use a bucket policy to grant permission to other users to read this configuration
+ * with the `s3:GetBucketNotification` permission.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function get_bucket_notifications($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'notification';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Empties the list of SNS topics to send notifications to.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html Setting Up Notification of Bucket Events
+ */
+ public function delete_bucket_notification($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'notification';
+ $opt['body'] = $this->base_notification_xml;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MULTIPART UPLOAD
+
+ /**
+ * Calculates the correct values for sequentially reading a file for multipart upload. This method should
+ * be used in conjunction with <upload_part()>.
+ *
+ * @param integer $filesize (Required) The size in bytes of the entire file.
+ * @param integer $part_size (Required) The size in bytes of the part of the file to send.
+ * @return array An array containing key-value pairs. The keys are `seekTo` and `length`.
+ */
+ public function get_multipart_counts($filesize, $part_size)
+ {
+ $i = 0;
+ $sizecount = $filesize;
+ $values = array();
+
+ while ($sizecount > 0)
+ {
+ $sizecount -= $part_size;
+ $values[] = array(
+ 'seekTo' => ($part_size * $i),
+ 'length' => (($sizecount > 0) ? $part_size : ($sizecount + $part_size)),
+ );
+ $i++;
+ }
+
+ return $values;
+ }
+
+ /**
+ * Initiates a multipart upload and returns an `UploadId`.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header starting with <code>x-amz-meta-:</code> is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function initiate_multipart_upload($bucket, $filename, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'POST';
+ $opt['resource'] = $filename;
+ $opt['sub_resource'] = 'uploads';
+ $opt['body'] = '';
+
+ // Handle content type. Can also be passed as an HTTP header.
+ if (isset($opt['contentType']))
+ {
+ $opt['headers']['Content-Type'] = $opt['contentType'];
+ unset($opt['contentType']);
+ }
+
+ // Set a default content type.
+ if (!isset($opt['headers']['Content-Type']))
+ {
+ $opt['headers']['Content-Type'] = 'application/octet-stream';
+ }
+
+ // Handle Access Control Lists. Can also be passed as an HTTP header.
+ if (isset($opt['acl']))
+ {
+ $opt['headers']['x-amz-acl'] = $opt['acl'];
+ unset($opt['acl']);
+ }
+
+ // Handle storage settings. Can also be passed as an HTTP header.
+ if (isset($opt['storage']))
+ {
+ $opt['headers']['x-amz-storage-class'] = $opt['storage'];
+ unset($opt['storage']);
+ }
+
+ // Handle encryption settings. Can also be passed as an HTTP header.
+ if (isset($opt['encryption']))
+ {
+ $opt['headers']['x-amz-server-side-encryption'] = $opt['encryption'];
+ unset($opt['encryption']);
+ }
+
+ // Handle meta tags. Can also be passed as an HTTP header.
+ if (isset($opt['meta']))
+ {
+ foreach ($opt['meta'] as $meta_key => $meta_value)
+ {
+ // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
+ $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
+ }
+ unset($opt['meta']);
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Uploads a single part of a multipart upload. The part size cannot be smaller than 5 MB
+ * or larger than 5 TB. A multipart upload can have no more than 10,000 parts.
+ *
+ * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
+ * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
+ * requests) costs slightly less but has lower upload reliability.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required - The URL/path for the file to upload or an open resource.</li>
+ * <li><code>partNumber</code> - <code>integer</code> - Required - The part number order of the multipart upload.</li>
+ * <li><code>expect</code> - <code>string</code> - Optional - Specifies that the SDK not send the request body until it receives an acknowledgement. If the message is rejected based on the headers, the body of the message is not sent. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20">RFC 2616, section 14.20</a>. The value can also be passed to the <code>header</code> option as <code>Expect</code>. [Allowed values: <code>100-continue</code>]</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the part in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>md5</code> - <code>string</code> - Optional - The base64 encoded 128-bit MD5 digest of the part data. This header can be used as a message integrity check to verify that the part data is the same data that was originally sent. Although it is optional, we recommend using this mechanism as an end-to-end integrity check. For more information, see <a href="http://www.ietf.org/rfc/rfc1864.txt">RFC 1864</a>. The value can also be passed to the <code>header</code> option as <code>Content-MD5</code>.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes for the piece of the file/stream to upload.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function upload_part($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+
+ if (!isset($opt['fileUpload']) || !isset($opt['partNumber']))
+ {
+ throw new S3_Exception('The `fileUpload` and `partNumber` options are both required in ' . __FUNCTION__ . '().');
+ }
+
+ // Handle expectation. Can also be passed as an HTTP header.
+ if (isset($opt['expect']))
+ {
+ $opt['headers']['Expect'] = $opt['expect'];
+ unset($opt['expect']);
+ }
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ // Handle content md5. Can also be passed as an HTTP header.
+ if (isset($opt['md5']))
+ {
+ $opt['headers']['Content-MD5'] = $opt['md5'];
+ unset($opt['md5']);
+ }
+
+ $opt['headers']['Expect'] = '100-continue';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Lists the completed parts of an in-progress multipart upload.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>max-parts</code> - <code>integer</code> - Optional - The maximum number of parts to return in the response body.</li>
+ * <li><code>part-number-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur numerically after the value of the <code>part-number-marker</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_parts($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+ $opt['query_string'] = array();
+
+ foreach (array('max-parts', 'part-number-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Aborts an in-progress multipart upload. This operation cannot be reversed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function abort_multipart_upload($bucket, $filename, $upload_id, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'DELETE';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Completes an in-progress multipart upload. A multipart upload is completed by describing the part
+ * numbers and corresponding ETag values in order, and submitting that data to Amazon S3 as an XML document.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param string|array|SimpleXMLElement|CFResponse $parts (Required) The completion XML document. This document can be provided in multiple ways; as a string of XML, as a <php:SimpleXMLElement> object representing the XML document, as an indexed array of associative arrays where the keys are <code>PartNumber</code> and <code>ETag</code>, or as a <CFResponse> object returned by <list_parts()>.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function complete_multipart_upload($bucket, $filename, $upload_id, $parts, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'POST';
+ $opt['resource'] = $filename;
+ $opt['uploadId'] = $upload_id;
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Disable Content-MD5 calculation for this operation
+ $opt['NoContentMD5'] = true;
+
+ if (is_string($parts))
+ {
+ // Assume it's the intended XML.
+ $opt['body'] = $parts;
+ }
+ elseif ($parts instanceof SimpleXMLElement)
+ {
+ // Assume it's a SimpleXMLElement object representing the XML.
+ $opt['body'] = $parts->asXML();
+ }
+ elseif (is_array($parts) || $parts instanceof CFResponse)
+ {
+ $xml = simplexml_load_string($this->complete_mpu_xml);
+
+ if (is_array($parts))
+ {
+ // Generate the appropriate XML.
+ foreach ($parts as $node)
+ {
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', $node['PartNumber']);
+ $part->addChild('ETag', $node['ETag']);
+ }
+
+ }
+ elseif ($parts instanceof CFResponse)
+ {
+ // Assume it's a response from list_parts().
+ foreach ($parts->body->Part as $node)
+ {
+ $part = $xml->addChild('Part');
+ $part->addChild('PartNumber', (string) $node->PartNumber);
+ $part->addChild('ETag', (string) $node->ETag);
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Lists the in-progress multipart uploads.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>delimiter</code> - <code>string</code> - Optional - Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.</li>
+ * <li><code>key-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>key-marker</code>. If used in conjunction with <code>upload-id-marker</code>, the results will be filtered to include keys whose upload ID is alphabetically after the value of <code>upload-id-marker</code>.</li>
+ * <li><code>upload-id-marker</code> - <code>string</code> - Optional - Restricts the response to contain results that only occur alphabetically after the value of the <code>upload-id-marker</code>. Must be used in conjunction with <code>key-marker</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function list_multipart_uploads($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'uploads';
+
+ foreach (array('key-marker', 'max-uploads', 'upload-id-marker') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $opt['query_string'][$param] = $opt[$param];
+ unset($opt[$param]);
+ }
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Since Amazon S3's standard <copy_object()> operation only supports copying objects that are smaller than
+ * 5 GB, the ability to copy large objects (greater than 5 GB) requires the use of "Multipart Copy".
+ *
+ * Copying large objects requires the developer to initiate a new multipart "upload", copy pieces of the
+ * large object (specifying a range of bytes up to 5 GB from the large source file), then complete the
+ * multipart "upload".
+ *
+ * NOTE: <strong>This is a synchronous operation</strong>, not an <em>asynchronous</em> operation, which means
+ * that Amazon S3 will not return a response for this operation until the copy has completed across the Amazon
+ * S3 server fleet. Copying objects within a single region will complete more quickly than copying objects
+ * <em>across</em> regions. The synchronous nature of this operation is different from other services where
+ * responses are typically returned immediately, even if the operation itself has not yet been completed on
+ * the server-side.
+ *
+ * @param array $source (Required) The bucket and file name to copy from. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket containing the source object.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name of the source object to copy.</li></ul>
+ * @param array $dest (Required) The bucket and file name to copy to. The following keys must be set: <ul>
+ * <li><code>bucket</code> - <code>string</code> - Required - Specifies the name of the bucket to copy the object to.</li>
+ * <li><code>filename</code> - <code>string</code> - Required - Specifies the file name to copy the object to.</li></ul>
+ * @param string $upload_id (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
+ * @param integer $part_number (Required) A part number uniquely identifies a part and defines its position within the destination object. When you complete a multipart upload, a complete object is created by concatenating parts in ascending order based on part number. If you copy a new part using the same part number as a previously copied/uploaded part, the previously written part is overwritten.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>ifMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) matches the specified tag; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifUnmodifiedSince</code>.</li>
+ * <li><code>ifUnmodifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it hasn't been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (precondition failed). Used in conjunction with <code>ifMatch</code>.</li>
+ * <li><code>ifNoneMatch</code> - <code>string</code> - Optional - The ETag header from a previous request. Copies the object if its entity tag (ETag) is different than the specified ETag; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifModifiedSince</code>.</li>
+ * <li><code>ifModifiedSince</code> - <code>string</code> - Optional - The LastModified header from a previous request. Copies the object if it has been modified since the specified time; otherwise, the request returns a <code>412</code> HTTP status code error (failed condition). Used in conjunction with <code>ifNoneMatch</code>.</li>
+ * <li><code>range</code> - <code>string</code> - Optional - The range of bytes to copy from the object. Specify this parameter when copying partial bits. The specified range must be notated with a hyphen (e.g., 0-10485759). Defaults to the byte range of the complete Amazon S3 object.</li>
+ * <li><code>versionId</code> - <code>string</code> - Optional - The version of the object to copy. Version IDs are returned in the <code>x-amz-version-id</code> header of any previous object-related request.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function copy_part($source, $dest, $upload_id, $part_number, $opt = null)
+ {
+ if (!$opt) $opt = array();
+
+ // Add this to our request
+ $opt['verb'] = 'PUT';
+ $opt['resource'] = $dest['filename'];
+ $opt['uploadId'] = $upload_id;
+ $opt['partNumber'] = $part_number;
+
+ // Handle copy source
+ if (isset($source['bucket']) && isset($source['filename']))
+ {
+ $opt['headers']['x-amz-copy-source'] = '/' . $source['bucket'] . '/' . rawurlencode($source['filename'])
+ . (isset($opt['versionId']) ? ('?' . 'versionId=' . rawurlencode($opt['versionId'])) : ''); // Append the versionId to copy, if available
+ unset($opt['versionId']);
+ }
+
+ // Handle conditional-copy parameters
+ if (isset($opt['ifMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-match'] = $opt['ifMatch'];
+ unset($opt['ifMatch']);
+ }
+ if (isset($opt['ifNoneMatch']))
+ {
+ $opt['headers']['x-amz-copy-source-if-none-match'] = $opt['ifNoneMatch'];
+ unset($opt['ifNoneMatch']);
+ }
+ if (isset($opt['ifUnmodifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-unmodified-since'] = $opt['ifUnmodifiedSince'];
+ unset($opt['ifUnmodifiedSince']);
+ }
+ if (isset($opt['ifModifiedSince']))
+ {
+ $opt['headers']['x-amz-copy-source-if-modified-since'] = $opt['ifModifiedSince'];
+ unset($opt['ifModifiedSince']);
+ }
+
+ // Partial content range
+ if (isset($opt['range']))
+ {
+ $opt['headers']['x-amz-copy-source-range'] = 'bytes=' . $opt['range'];
+ }
+
+ // Authenticate to S3
+ return $this->authenticate($dest['bucket'], $opt);
+ }
+
+ /**
+ * Creates an Amazon S3 object using the multipart upload APIs. It is analogous to <create_object()>.
+ *
+ * While each individual part of a multipart upload can hold up to 5 GB of data, this method limits the
+ * part size to a maximum of 500 MB. The combined size of all parts can not exceed 5 TB of data. When an
+ * object is stored in Amazon S3, the data is streamed to multiple storage servers in multiple data
+ * centers. This ensures the data remains available in the event of internal network or hardware failure.
+ *
+ * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
+ * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
+ * requests) costs slightly less but has lower upload reliability.
+ *
+ * In certain cases with large objects, it's possible for this method to attempt to open more file system
+ * connections than allowed by the OS. In this case, either
+ * <a href="https://forums.aws.amazon.com/thread.jspa?threadID=70216">increase the number of connections
+ * allowed</a> or increase the value of the <code>partSize</code> parameter to use a larger part size.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string $filename (Required) The file name for the object.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>fileUpload</code> - <code>string|resource</code> - Required - The URL/path for the file to upload, or an open resource.</li>
+ * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. The default value is <code>ACL_PRIVATE</code>.</li>
+ * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent in the body. The default value is <code>application/octet-stream</code>.</li>
+ * <li><code>headers</code> - <code>array</code> - Optional - Standard HTTP headers to send along in the request. Accepts an associative array of key-value pairs.</li>
+ * <li><code>length</code> - <code>integer</code> - Optional - The size of the object in bytes. For more information, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">RFC 2616, section 14.13</a>. The value can also be passed to the <code>header</code> option as <code>Content-Length</code>.</li>
+ * <li><code>limit</code> - <code>integer</code> - Optional - The maximum number of concurrent uploads done by cURL. Gets passed to <code>CFBatchRequest</code>.</li>
+ * <li><code>meta</code> - <code>array</code> - Optional - An associative array of key-value pairs. Any header starting with <code>x-amz-meta-:</code> is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.</li>
+ * <li><code>partSize</code> - <code>integer</code> - Optional - The size of an individual part. The size may not be smaller than 5 MB or larger than 500 MB. The default value is 50 MB.</li>
+ * <li><code>seekTo</code> - <code>integer</code> - Optional - The starting position in bytes for the first piece of the file/stream to upload.</li>
+ * <li><code>storage</code> - <code>string</code> - Optional - Whether to use Standard or Reduced Redundancy storage. [Allowed values: <code>AmazonS3::STORAGE_STANDARD</code>, <code>AmazonS3::STORAGE_REDUCED</code>]. The default value is <code>STORAGE_STANDARD</code>.</li>
+ * <li><code>uploadId</code> - <code>string</code> - Optional - An upload ID identifying an existing multipart upload to use. If this option is not set, one will be created automatically.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
+ */
+ public function create_mpu_object($bucket, $filename, $opt = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ if (!$opt) $opt = array();
+
+ // Handle content length. Can also be passed as an HTTP header.
+ if (isset($opt['length']))
+ {
+ $opt['headers']['Content-Length'] = $opt['length'];
+ unset($opt['length']);
+ }
+
+ if (!isset($opt['fileUpload']))
+ {
+ throw new S3_Exception('The `fileUpload` option is required in ' . __FUNCTION__ . '().');
+ }
+ elseif (is_resource($opt['fileUpload']))
+ {
+ $opt['limit'] = 1; // We can only read from this one resource.
+ $upload_position = isset($opt['seekTo']) ? (integer) $opt['seekTo'] : ftell($opt['fileUpload']);
+ $upload_filesize = isset($opt['headers']['Content-Length']) ? (integer) $opt['headers']['Content-Length'] : null;
+
+ if (!isset($upload_filesize) && $upload_position !== false)
+ {
+ $stats = fstat($opt['fileUpload']);
+
+ if ($stats && $stats['size'] >= 0)
+ {
+ $upload_filesize = $stats['size'] - $upload_position;
+ }
+ }
+ }
+ else
+ {
+ $upload_position = isset($opt['seekTo']) ? (integer) $opt['seekTo'] : 0;
+
+ if (isset($opt['headers']['Content-Length']))
+ {
+ $upload_filesize = (integer) $opt['headers']['Content-Length'];
+ }
+ else
+ {
+ $upload_filesize = filesize($opt['fileUpload']);
+
+ if ($upload_filesize !== false)
+ {
+ $upload_filesize -= $upload_position;
+ }
+ }
+ }
+
+ if ($upload_position === false || !isset($upload_filesize) || $upload_filesize === false || $upload_filesize < 0)
+ {
+ throw new S3_Exception('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
+ }
+
+ // Handle part size
+ if (isset($opt['partSize']))
+ {
+ // If less that 5 MB...
+ if ((integer) $opt['partSize'] < 5242880)
+ {
+ $opt['partSize'] = 5242880; // 5 MB
+ }
+ // If more than 500 MB...
+ elseif ((integer) $opt['partSize'] > 524288000)
+ {
+ $opt['partSize'] = 524288000; // 500 MB
+ }
+ }
+ else
+ {
+ $opt['partSize'] = 52428800; // 50 MB
+ }
+
+ // If the upload size is smaller than the piece size, failover to create_object().
+ if ($upload_filesize < $opt['partSize'] && !isset($opt['uploadId']))
+ {
+ return $this->create_object($bucket, $filename, $opt);
+ }
+
+ // Initiate multipart upload
+ if (isset($opt['uploadId']))
+ {
+ $upload_id = $opt['uploadId'];
+ }
+ else
+ {
+ // Compose options for initiate_multipart_upload().
+ $_opt = array();
+ foreach (array('contentType', 'acl', 'storage', 'headers', 'meta') as $param)
+ {
+ if (isset($opt[$param]))
+ {
+ $_opt[$param] = $opt[$param];
+ }
+ }
+
+ $upload = $this->initiate_multipart_upload($bucket, $filename, $_opt);
+ if (!$upload->isOK())
+ {
+ return $upload;
+ }
+
+ // Fetch the UploadId
+ $upload_id = (string) $upload->body->UploadId;
+ }
+
+ // Get the list of pieces
+ $pieces = $this->get_multipart_counts($upload_filesize, (integer) $opt['partSize']);
+
+ // Queue batch requests
+ $batch = new CFBatchRequest(isset($opt['limit']) ? (integer) $opt['limit'] : null);
+ foreach ($pieces as $i => $piece)
+ {
+ $this->batch($batch)->upload_part($bucket, $filename, $upload_id, array(
+ 'expect' => '100-continue',
+ 'fileUpload' => $opt['fileUpload'],
+ 'partNumber' => ($i + 1),
+ 'seekTo' => $upload_position + (integer) $piece['seekTo'],
+ 'length' => (integer) $piece['length'],
+ ));
+ }
+
+ // Send batch requests
+ $batch_responses = $this->batch($batch)->send();
+ if (!$batch_responses->areOK())
+ {
+ return $batch_responses;
+ }
+
+ // Compose completion XML
+ $parts = array();
+ foreach ($batch_responses as $i => $response)
+ {
+ $parts[] = array('PartNumber' => ($i + 1), 'ETag' => $response->header['etag']);
+ }
+
+ return $this->complete_multipart_upload($bucket, $filename, $upload_id, $parts);
+ }
+
+ /**
+ * Aborts all multipart uploads initiated before the specified date. This operation cannot be reversed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param string|integer $when (Optional) The time and date to use for comparison. Accepts any value that <php:strtotime()> understands.
+ * @return CFArray A <CFArray> containing a series of 0 or more <CFResponse> objects, containing a parsed HTTP response.
+ */
+ public function abort_multipart_uploads_by_date($bucket, $when = null)
+ {
+ if ($this->use_batch_flow)
+ {
+ // @codeCoverageIgnoreStart
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ // @codeCoverageIgnoreEnd
+ }
+
+ $when = $when ? $when : time();
+ $handles = array();
+ $data = $this->list_multipart_uploads($bucket)->body;
+ $when = is_int($when) ? $when : strtotime($when);
+
+ if (!($data instanceof CFSimpleXML))
+ {
+ return false;
+ }
+
+ $list = $data->query('descendant-or-self::Upload/Initiated');
+
+ if (count($list) > 0)
+ {
+ foreach ($list as $node)
+ {
+ if (strtotime((string) $node) < $when)
+ {
+ $q = new CFBatchRequest();
+ $parent = $node->parent();
+
+ $upload_id = $parent
+ ->query('descendant-or-self::UploadId')
+ ->first()
+ ->to_string();
+
+ $filename = $parent
+ ->query('descendant-or-self::Key')
+ ->first()
+ ->to_string();
+
+ $handles[] = $this->abort_multipart_upload($bucket, $filename, $upload_id, array(
+ 'returnCurlHandle' => true
+ ));
+ }
+ }
+
+ $http = new CFRequest();
+ $responses = $http->send_multi_request($handles);
+
+ if (is_array($responses) && count($responses) > 0)
+ {
+ return new CFArray($responses);
+ }
+ }
+
+ return new CFArray();
+ }
+
+
+ /*%******************************************************************************************%*/
+ // WEBSITE CONFIGURATION
+
+ /**
+ * Enables and configures an Amazon S3 website using the corresponding bucket as the content source.
+ * The website will have one default domain name associated with it, which is the bucket name. If you
+ * attempt to configure an Amazon S3 website for a bucket whose name is not compatible with DNS,
+ * Amazon S3 returns an <code>InvalidBucketName</code> error. For more information on bucket names and DNS,
+ * refer to <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html">Bucket Restrictions and Limitations.</a>
+ *
+ * To visit the bucket as a website a new endpoint is created in the following pattern:
+ * <code>http://&lt;bucketName&gt;.s3-website-&lt;region&gt;.amazonaws.com</code>. This is a sample URL
+ * for a bucket called <code>example-bucket</code> in the <code>us-east-1</code> region.
+ * (e.g., <code>http://example-bucket.s3-website-us-east-1.amazonaws.com</code>)
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>indexDocument</code> - <code>string</code> - Optional - The file path to use as the root document. The default value is <code>index.html</code>.</li>
+ * <li><code>errorDocument</code> - <code>string</code> - Optional - The file path to use as the error document. The default value is <code>error.html</code>.</li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function create_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'website';
+
+ $xml = simplexml_load_string($this->website_config_xml);
+ if (isset($opt['indexDocument']))
+ {
+ $xml->IndexDocument->Suffix = $opt['indexDocument'];
+ }
+ if (isset($opt['errorDocument']))
+ {
+ $xml->ErrorDocument->Key = $opt['errorDocument'];
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Retrieves the website configuration for a bucket. The contents of this response are identical to the
+ * content submitted by the user during the website creation operation. If a website configuration has
+ * never been set, Amazon S3 will return a 404 error.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function get_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'website';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ /**
+ * Removes the website configuration for a bucket.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function delete_website_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'website';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // OBJECT EXPIRATION
+
+ /**
+ * Enables the ability to specify an expiry period for objects when an object should be deleted,
+ * measured as number of days from creation time. Amazon S3 guarantees that the object will be
+ * deleted when the expiration time is passed.
+ *
+ * @param string $bucket (Required) The name of the bucket to use.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>rules</code> - <code>string</code> - Required - The object expiration rule-sets to apply to the bucket. <ul>
+ * <li><code>x</code> - <code>array</code> - Required - This represents a simple array index. <ul>
+ * <li><code>id</code> - <code>string</code> - Optional - Unique identifier for the rule. The value cannot be longer than 255 characters.
+ * <li><code>prefix</code> - <code>string</code> - Required - The Amazon S3 object prefix which targets the file(s) for expiration.</li>
+ * <li><code>expiration</code> - <code>array</code> - Required - The container for the unit of measurement by which the expiration time is calculated. <ul>
+ * <li><code>days</code> - <code>integer</code> - Required - The number of days until the targetted objects expire from the bucket.</li>
+ * </ul></li>
+ * <li><code>enabled</code> - <code>boolean</code> - Optional - Whether or not to enable this rule-set. A value of <code>true</code> enables the rule-set. A value of <code>false</code> disables the rule-set. The default value is <code>true</code>.</li>
+ * </ul></li>
+ * </ul></li>
+ * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
+ * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
+ * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
+ */
+ public function create_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'PUT';
+ $opt['sub_resource'] = 'lifecycle';
+ $opt['headers'] = array(
+ 'Content-Type' => 'application/xml'
+ );
+
+ $xml = simplexml_load_string($this->object_expiration_xml, $this->parser_class);
+
+ if (isset($opt['rules']) && is_array($opt['rules']) && count($opt['rules']))
+ {
+ foreach ($opt['rules'] as $rule)
+ {
+ $xrule = $xml->addChild('Rule');
+
+ // ID
+ if (isset($rule['id']))
+ {
+ if (strlen($rule['id']) > 255)
+ {
+ throw new S3_Exception('The "id" for a rule must not be more than 255 characters in the ' . __FUNCTION__ . ' method.');
+ }
+
+ $xrule->addChild('ID', $rule['id']);
+ }
+
+ // Prefix
+ if (isset($rule['prefix']))
+ {
+ $xrule->addChild('Prefix', $rule['prefix']);
+ }
+ else
+ {
+ throw new S3_Exception('Each rule requires a "prefix" in the ' . __FUNCTION__ . ' method.');
+ }
+
+ // Status
+ $enabled = 'Enabled';
+ if (isset($rule['enabled']))
+ {
+ if (is_bool($rule['enabled'])) // Boolean
+ {
+ $enabled = $rule['enabled'] ? 'Enabled' : 'Disabled';
+ }
+ elseif (is_string($rule['enabled'])) // String
+ {
+ $enabled = (strtolower($rule['enabled']) === 'true') ? 'Enabled' : 'Disabled';
+ }
+
+ $xrule->addChild('Status', $enabled);
+ }
+ else
+ {
+ $xrule->addChild('Status', 'Enabled');
+ }
+
+ // Expiration
+ if (isset($rule['expiration']))
+ {
+ $xexpiration = $xrule->addChild('Expiration');
+
+ if (isset($rule['expiration']['days']))
+ {
+ $xexpiration->addChild('Days', $rule['expiration']['days']);
+ }
+ }
+ else
+ {
+ throw new S3_Exception('Each rule requires a "expiration" in the ' . __FUNCTION__ . ' method.');
+ }
+ }
+ }
+
+ $opt['body'] = $xml->asXML();
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ public function get_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'GET';
+ $opt['sub_resource'] = 'lifecycle';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+ public function delete_object_expiration_config($bucket, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $opt['verb'] = 'DELETE';
+ $opt['sub_resource'] = 'lifecycle';
+
+ // Authenticate to S3
+ return $this->authenticate($bucket, $opt);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // MISCELLANEOUS
+
+ /**
+ * Gets the canonical user ID and display name from the Amazon S3 server.
+ *
+ * @return array An associative array containing the `id` and `display_name` values.
+ */
+ public function get_canonical_user_id()
+ {
+ if ($this->use_batch_flow)
+ {
+ throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
+ }
+
+ $id = $this->list_buckets();
+
+ return array(
+ 'id' => (string) $id->body->Owner->ID,
+ 'display_name' => (string) $id->body->Owner->DisplayName
+ );
+ }
+
+ /**
+ * Loads and registers the S3StreamWrapper class as a stream wrapper.
+ *
+ * @param string $protocol (Optional) The name of the protocol to register.
+ * @return boolean Whether or not the registration succeeded.
+ */
+ public function register_stream_wrapper($protocol = 's3')
+ {
+ require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'extensions'
+ . DIRECTORY_SEPARATOR . 's3streamwrapper.class.php';
+
+ return S3StreamWrapper::register($this, $protocol);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/array.class.php b/3rdparty/aws-sdk/utilities/array.class.php
new file mode 100644
index 00000000000..dea673546f8
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/array.class.php
@@ -0,0 +1,312 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFArray> object extends PHP's built-in <php:ArrayObject> object by providing convenience methods for
+ * rapidly manipulating array data. Specifically, the `CFArray` object is intended for working with
+ * <CFResponse> and <CFSimpleXML> objects that are returned by AWS services.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://php.net/ArrayObject ArrayObject
+ */
+class CFArray extends ArrayObject
+{
+ /**
+ * Constructs a new instance of <CFArray>.
+ *
+ * @param mixed $input (Optional) The input parameter accepts an array or an Object. The default value is an empty array.
+ * @param integer $flags (Optional) Flags to control the behavior of the ArrayObject object. Defaults to <STD_PROP_LIST>.
+ * @param string $iterator_class (Optional) Specify the class that will be used for iteration of the <php:ArrayObject> object. <php:ArrayIterator> is the default class used.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iterator_class = 'ArrayIterator')
+ {
+ // Provide a default value
+ $input = $input ? $input : array();
+
+ try {
+ return parent::__construct($input, $flags, $iterator_class);
+ }
+ catch (InvalidArgumentException $e)
+ {
+ throw new CFArray_Exception($e->getMessage());
+ }
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param mixed $input (Optional) The input parameter accepts an array or an Object. The default value is an empty array.
+ * @param integer $flags (Optional) Flags to control the behavior of the ArrayObject object. Defaults to <STD_PROP_LIST>.
+ * @param string $iterator_class (Optional) Specify the class that will be used for iteration of the <php:ArrayObject> object. <php:ArrayIterator> is the default class used.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public static function init($input = array(), $flags = self::STD_PROP_LIST, $iterator_class = 'ArrayIterator')
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($input, $flags, $iterator_class);
+ }
+
+ /**
+ * Handles how the object is rendered when cast as a string.
+ *
+ * @return string The word "Array".
+ */
+ public function __toString()
+ {
+ return 'Array';
+ }
+
+
+ /*%******************************************************************************************%*/
+ // REFORMATTING
+
+ /**
+ * Maps each element in the <CFArray> object as an integer.
+ *
+ * @return array The contents of the <CFArray> object mapped as integers.
+ */
+ public function map_integer()
+ {
+ return array_map('intval', $this->getArrayCopy());
+ }
+
+ /**
+ * Maps each element in the CFArray object as a string.
+ *
+ * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against.
+ * @return array The contents of the <CFArray> object mapped as strings. If there are no results, the method will return an empty array.
+ */
+ public function map_string($pcre = null)
+ {
+ $list = array_map('strval', $this->getArrayCopy());
+ $dlist = array();
+
+ if ($pcre)
+ {
+ foreach ($list as $item)
+ {
+ $dlist[] = preg_match($pcre, $item) ? $item : null;
+ }
+
+ $list = array_values(array_filter($dlist));
+ }
+
+ return $list;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONFIRMATION
+
+ /**
+ * Verifies that _all_ responses were successful. A single failed request will cause <areOK()> to return false. Equivalent to <CFResponse::isOK()>, except it applies to all responses.
+ *
+ * @return boolean Whether _all_ requests were successful or not.
+ */
+ public function areOK()
+ {
+ $dlist = array();
+ $list = $this->getArrayCopy();
+
+ foreach ($list as $response)
+ {
+ if ($response instanceof CFResponse)
+ {
+ $dlist[] = $response->isOK();
+ }
+ }
+
+ return (array_search(false, $dlist, true) !== false) ? false : true;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ITERATING AND EXECUTING
+
+ /**
+ * Iterates over a <CFArray> object, and executes a function for each matched element.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray The original <CFArray> object.
+ */
+ public function each($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+
+ foreach ($items as $key => &$item)
+ {
+ $callback($item, $key, $bind);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Passes each element in the current <CFArray> object through a function, and produces a new <CFArray> object containing the return values.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function map($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+ $collect = array();
+
+ foreach ($items as $key => &$item)
+ {
+ $collect[] = $callback($item, $key, $bind);
+ }
+
+ return new CFArray($collect);
+ }
+
+ /**
+ * Filters the list of nodes by passing each value in the current <CFArray> object through a function. The node will be removed if the function returns `false`.
+ *
+ * The callback function takes three parameters: <ul>
+ * <li><code>$item</code> - <code>mixed</code> - Optional - The individual node in the array.</li>
+ * <li><code>$key</code> - <code>mixed</code> - Optional - The key for the array node.</li>
+ * <li><code>$bind</code> - <code>mixed</code> - Optional - The variable that was passed into the $bind parameter.</li></ul>
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function filter($callback, &$bind = null)
+ {
+ $items = $this->getArrayCopy();
+ $collect = array();
+
+ foreach ($items as $key => &$item)
+ {
+ if ($callback($item, $key, $bind) !== false)
+ {
+ $collect[] = $item;
+ }
+ }
+
+ return new CFArray($collect);
+ }
+
+ /**
+ * Alias for <filter()>. This functionality was incorrectly named _reduce_ in earlier versions of the SDK.
+ *
+ * @param string|function $callback (Required) The callback function to execute. PHP 5.3 or newer can use an anonymous function.
+ * @param mixed $bind (Optional) A variable from the calling scope to pass-by-reference into the local scope of the callback function.
+ * @return CFArray A new <CFArray> object containing the return values.
+ */
+ public function reduce($callback, &$bind = null)
+ {
+ return $this->filter($callback, $bind);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // TRAVERSAL
+
+ /**
+ * Gets the first result in the array.
+ *
+ * @return mixed The first result in the <CFArray> object. Returns `false` if there are no items in the array.
+ */
+ public function first()
+ {
+ $items = $this->getArrayCopy();
+ return count($items) ? $items[0] : false;
+ }
+
+ /**
+ * Gets the last result in the array.
+ *
+ * @return mixed The last result in the <CFArray> object. Returns `false` if there are no items in the array.
+ */
+ public function last()
+ {
+ $items = $this->getArrayCopy();
+ return count($items) ? end($items) : false;
+ }
+
+ /**
+ * Removes all `null` values from an array.
+ *
+ * @return CFArray A new <CFArray> object containing the non-null values.
+ */
+ public function compress()
+ {
+ return new CFArray(array_filter($this->getArrayCopy()));
+ }
+
+ /**
+ * Reindexes the array, starting from zero.
+ *
+ * @return CFArray A new <CFArray> object with indexes starting at zero.
+ */
+ public function reindex()
+ {
+ return new CFArray(array_values($this->getArrayCopy()));
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ALTERNATE FORMATS
+
+ /**
+ * Gets the current XML node as a JSON string.
+ *
+ * @return string The current XML node as a JSON string.
+ */
+ public function to_json()
+ {
+ return json_encode($this->getArrayCopy());
+ }
+
+ /**
+ * Gets the current XML node as a YAML string.
+ *
+ * @return string The current XML node as a YAML string.
+ */
+ public function to_yaml()
+ {
+ return sfYaml::dump($this->getArrayCopy(), 5);
+ }
+}
+
+class CFArray_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/batchrequest.class.php b/3rdparty/aws-sdk/utilities/batchrequest.class.php
new file mode 100644
index 00000000000..978283471a4
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/batchrequest.class.php
@@ -0,0 +1,126 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// EXCEPTIONS
+
+/**
+ * Default CFBatchRequest Exception.
+ */
+class CFBatchRequest_Exception extends Exception {}
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the flow involved with managing and executing a batch request queue. Batch requesting is the
+ * ability to queue up a series of requests and execute them all in parallel. This allows for faster
+ * application performance when a lot of requests are involved.
+ *
+ * @version 2011.12.02
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFBatchRequest extends CFRuntime
+{
+ /**
+ * Stores the cURL handles that are to be processed.
+ */
+ public $queue;
+
+ /**
+ * Stores the size of the request window.
+ */
+ public $limit;
+
+ /**
+ * The proxy to use for connecting.
+ */
+ public $proxy = null;
+
+ /**
+ * The helpers to use when connecting.
+ */
+ public $helpers = null;
+
+ /**
+ * The active credential set.
+ */
+ public $credentials;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param integer $limit (Optional) The size of the request window. Defaults to unlimited.
+ * @return boolean `false` if no valid values are set, otherwise `true`.
+ */
+ public function __construct($limit = null)
+ {
+ $this->queue = array();
+ $this->limit = $limit ? $limit : -1;
+ $this->credentials = new CFCredential(array());
+ return $this;
+ }
+
+ /**
+ * Sets the AWS credentials to use for the batch request.
+ *
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return $this A reference to the current instance.
+ */
+ public function use_credentials(CFCredential $credentials)
+ {
+ $this->credentials = $credentials;
+ return $this;
+ }
+
+ /**
+ * Adds a new cURL handle to the request queue.
+ *
+ * @param resource $handle (Required) A cURL resource to add to the queue.
+ * @return $this A reference to the current instance.
+ */
+ public function add($handle)
+ {
+ $this->queue[] = $handle;
+ return $this;
+ }
+
+ /**
+ * Executes the batch request queue.
+ *
+ * @param array $opt (DO NOT USE) Enabled for compatibility with the method this overrides, although any values passed will be ignored.
+ * @return array An indexed array of <CFResponse> objects.
+ */
+ public function send($opt = null)
+ {
+ $http = new $this->request_class(null, $this->proxy, null, $this->credentials);
+
+ // Make the request
+ $response = $http->send_multi_request($this->queue, array(
+ 'limit' => $this->limit
+ ));
+
+ return $response;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/complextype.class.php b/3rdparty/aws-sdk/utilities/complextype.class.php
new file mode 100644
index 00000000000..e0509b9e368
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/complextype.class.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains utility methods used for converting array, JSON, and YAML data types into query string keys.
+ *
+ * @version 2010.11.11
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFComplexType
+{
+ /**
+ * Takes a JSON object, as a string, to convert to query string keys.
+ *
+ * @param string $json (Required) A JSON object. The JSON string should use canonical rules (e.g., double quotes, quoted keys) as is required by PHP's <php:json_encode()> function.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function json($json, $member = '', $default_key = '')
+ {
+ return self::option_group(json_decode($json, true), $member, $default_key);
+ }
+
+ /**
+ * Takes a YAML object, as a string, to convert to query string keys.
+ *
+ * @param string $yaml (Required) A YAML object.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function yaml($yaml, $member = '', $default_key = '')
+ {
+ return self::option_group(sfYaml::load($yaml), $member, $default_key);
+ }
+
+ /**
+ * Takes an associative array to convert to query string keys.
+ *
+ * @param array $map (Required) An associative array.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $default_key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function map($map, $member = '', $default_key = '')
+ {
+ return self::option_group($map, $member, $default_key);
+ }
+
+ /**
+ * A protected method that is used by <json()>, <yaml()> and <map()>.
+ *
+ * @param string|array $data (Required) The data to iterate over.
+ * @param string $member (Optional) The name of the "member" property that AWS uses for lists in certain services. Defaults to an empty string.
+ * @param string $key (Optional) The default key to use when the value for `$data` is a string. Defaults to an empty string.
+ * @param array $out (Optional) INTERNAL ONLY. The array that contains the calculated values up to this point.
+ * @return array The option group parameters to merge into another method's `$opt` parameter.
+ */
+ public static function option_group($data, $member = '', $key = '', &$out = array())
+ {
+ $reset = $key;
+
+ if (is_array($data))
+ {
+ foreach ($data as $k => $v)
+ {
+ // Avoid 0-based indexes.
+ if (is_int($k))
+ {
+ $k = $k + 1;
+
+ if ($member !== '')
+ {
+ $key .= '.' . $member;
+ }
+ }
+
+ $key .= ($key === '' ? $k : '.' . $k);
+
+ if (is_array($v))
+ {
+ self::option_group($v, $member, $key, $out);
+ }
+ elseif ($v instanceof CFStepConfig)
+ {
+ self::option_group($v->get_config(), $member, $key, $out);
+ }
+ else
+ {
+ $out[$key] = $v;
+ }
+
+ $key = $reset;
+ }
+ }
+ else
+ {
+ $out[$key] = $data;
+ }
+
+ return $out;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/credential.class.php b/3rdparty/aws-sdk/utilities/credential.class.php
new file mode 100644
index 00000000000..05c0ffcf6d8
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/credential.class.php
@@ -0,0 +1,157 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFCredential> class represents an individual credential set.
+ *
+ * @version 2011.11.15
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFCredential implements ArrayAccess
+{
+ /**
+ * Stores the internal <php:ArrayObject> representation of the collection.
+ */
+ private $collection;
+
+ /**
+ * Default getter. Enables syntax such as $object->method->chained_method();. Also supports
+ * $object->key. Matching methods are prioritized over matching keys.
+ *
+ * @param string $name (Required) The name of the method to execute or key to retrieve.
+ * @return mixed The results of calling the function <code>$name()</code>, or the value of the key <code>$object[$name]</code>.
+ */
+ public function __get($name)
+ {
+ return $this[$name];
+ }
+
+ /**
+ * Default setter.
+ *
+ * @param string $name (Required) The name of the method to execute.
+ * @param string $value (Required) The value to pass to the method.
+ * @return mixed The results of calling the function, <code>$name</code>.
+ */
+ public function __set($name, $value)
+ {
+ $this[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Create a clone of the object.
+ *
+ * @return CFCredential A clone of the current instance.
+ */
+ public function __clone()
+ {
+ $this->collection = clone $this->collection;
+ }
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of the <CFCredential> class.
+ */
+ public function __construct($value = array())
+ {
+ $this->collection = new ArrayObject($value, ArrayObject::ARRAY_AS_PROPS);
+ }
+
+ /**
+ * Check whether or not a specific offset exists.
+ *
+ * @param integer $offset (Required) The location in the collection to verify the existence of.
+ * @return boolean A value of <code>true</code> indicates that the collection offset exists. A value of <code>false</code> indicates that it does not.
+ */
+ public function offsetExists($offset)
+ {
+ return $this->collection->offsetExists($offset);
+ }
+
+ /**
+ * Get the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to retrieve the value for.
+ * @return mixed The value of the collection offset. <code>NULL</code> is returned if the offset does not exist.
+ */
+ public function offsetGet($offset)
+ {
+ if ($this->collection->offsetExists($offset))
+ {
+ return $this->collection->offsetGet($offset);
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to set a new value for.
+ * @param mixed $value (Required) The new value for the collection location.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function offsetSet($offset, $value)
+ {
+ $this->collection->offsetSet($offset, $value);
+ return $this;
+ }
+
+ /**
+ * Unset the value for a specific offset.
+ *
+ * @param integer $offset (Required) The location in the collection to unset.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function offsetUnset($offset)
+ {
+ $this->collection->offsetUnset($offset);
+ return $this;
+ }
+
+ /**
+ * Merge another instance of <CFCredential> onto this one.
+ *
+ * @param CFCredential $credential (Required) Another instance of <CFCredential>.
+ * @return CFCredential A reference to the current collection.
+ */
+ public function merge(CFCredential $credential)
+ {
+ $merged = array_merge($this->to_array(), $credential->to_array());
+ $this->collection->exchangeArray($merged);
+ return $this;
+ }
+
+ /**
+ * Retrieves the data as a standard array.
+ *
+ * @return array The data as an array.
+ */
+ public function to_array()
+ {
+ return $this->collection->getArrayCopy();
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/credentials.class.php b/3rdparty/aws-sdk/utilities/credentials.class.php
new file mode 100644
index 00000000000..2504a081b23
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/credentials.class.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * The <CFCredentials> class enables developers to easily switch between multiple sets of credentials.
+ *
+ * @version 2011.11.15
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFCredentials
+{
+ /**
+ * The key used to specify the default credential set
+ */
+ const DEFAULT_KEY = '@default';
+
+ /**
+ * The key used to identify inherited credentials
+ */
+ const INHERIT_KEY = '@inherit';
+
+ /**
+ * Stores the credentials
+ */
+ protected static $credentials = array();
+
+ /**
+ * Prevents this class from being constructed
+ */
+ final private function __construct() {}
+
+ /**
+ * Stores the credentials for re-use.
+ *
+ * @param array $credential_sets (Required) The named credential sets that should be made available to the application.
+ * @return void
+ */
+ public static function set(array $credential_sets)
+ {
+ // Make sure a default credential set is specified or can be inferred
+ if (count($credential_sets) === 1)
+ {
+ $credential_sets[self::DEFAULT_KEY] = reset($credential_sets);
+ }
+ elseif (!isset($credential_sets[self::DEFAULT_KEY]))
+ {
+ throw new CFCredentials_Exception('If more than one credential set is provided, a default credential set (identified by the key "' . self::DEFAULT_KEY . '") must be specified.');
+ }
+
+ // Resolve any @inherit tags
+ foreach ($credential_sets as $credential_name => &$credential_set)
+ {
+ if (is_array($credential_set))
+ {
+ foreach ($credential_set as $credential_key => &$credential_value)
+ {
+ if ($credential_key === self::INHERIT_KEY)
+ {
+ if (!isset($credential_sets[$credential_value]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $credential_value . '", does not exist and cannot be inherited.');
+ }
+
+ $credential_set = array_merge($credential_sets[$credential_value], $credential_set);
+ unset($credential_set[self::INHERIT_KEY]);
+ }
+ }
+ }
+ }
+
+ // Normalize the value of the @default credential set
+ $default = $credential_sets[self::DEFAULT_KEY];
+ if (is_string($default))
+ {
+ if (!isset($credential_sets[$default]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $default . '", does not exist and cannot be used as the default credential set.');
+ }
+
+ $credential_sets[self::DEFAULT_KEY] = $credential_sets[$default];
+ }
+
+ // Store the credentials
+ self::$credentials = $credential_sets;
+ }
+
+ /**
+ * Retrieves the requested credentials from the internal credential store.
+ *
+ * @param string $credential_set (Optional) The name of the credential set to retrieve. The default value is set in DEFAULT_KEY.
+ * @return stdClass A stdClass object where the properties represent the keys that were provided.
+ */
+ public static function get($credential_name = self::DEFAULT_KEY)
+ {
+ // Make sure the credential set exists
+ if (!isset(self::$credentials[$credential_name]))
+ {
+ throw new CFCredentials_Exception('The credential set, "' . $credential_name . '", does not exist and cannot be retrieved.');
+ }
+
+ // Return the credential set as an object
+ return new CFCredential(self::$credentials[$credential_name]);
+ }
+}
+
+class CFCredentials_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/gzipdecode.class.php b/3rdparty/aws-sdk/utilities/gzipdecode.class.php
new file mode 100644
index 00000000000..f80822a7048
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/gzipdecode.class.php
@@ -0,0 +1,377 @@
+<?php
+/*
+ * Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/**
+ * SimplePie
+ *
+ * A PHP-Based RSS and Atom Feed Framework.
+ * Takes the hard work out of managing a complete RSS/Atom solution.
+ *
+ * Copyright (c) 2004-2010, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
+ * 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 SimplePie Team 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 HOLDERS
+ * AND 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.
+ *
+ * @package SimplePie
+ * @version 1.3-dev
+ * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
+ * @author Ryan Parman
+ * @author Geoffrey Sneddon
+ * @author Ryan McCue
+ * @link http://simplepie.org/ SimplePie
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @todo phpDoc comments
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Handles a variety of primary and edge cases around gzip/deflate decoding in PHP.
+ *
+ * @version 2011.02.21
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link https://github.com/simplepie/simplepie/blob/master/SimplePie/gzdecode.php SimplePie_gzdecode
+ */
+class CFGzipDecode
+{
+ /**
+ * Compressed data
+ *
+ * @access private
+ * @see gzdecode::$data
+ */
+ public $compressed_data;
+
+ /**
+ * Size of compressed data
+ *
+ * @access private
+ */
+ public $compressed_size;
+
+ /**
+ * Minimum size of a valid gzip string
+ *
+ * @access private
+ */
+ public $min_compressed_size = 18;
+
+ /**
+ * Current position of pointer
+ *
+ * @access private
+ */
+ public $position = 0;
+
+ /**
+ * Flags (FLG)
+ *
+ * @access private
+ */
+ public $flags;
+
+ /**
+ * Uncompressed data
+ *
+ * @access public
+ * @see gzdecode::$compressed_data
+ */
+ public $data;
+
+ /**
+ * Modified time
+ *
+ * @access public
+ */
+ public $MTIME;
+
+ /**
+ * Extra Flags
+ *
+ * @access public
+ */
+ public $XFL;
+
+ /**
+ * Operating System
+ *
+ * @access public
+ */
+ public $OS;
+
+ /**
+ * Subfield ID 1
+ *
+ * @access public
+ * @see gzdecode::$extra_field
+ * @see gzdecode::$SI2
+ */
+ public $SI1;
+
+ /**
+ * Subfield ID 2
+ *
+ * @access public
+ * @see gzdecode::$extra_field
+ * @see gzdecode::$SI1
+ */
+ public $SI2;
+
+ /**
+ * Extra field content
+ *
+ * @access public
+ * @see gzdecode::$SI1
+ * @see gzdecode::$SI2
+ */
+ public $extra_field;
+
+ /**
+ * Original filename
+ *
+ * @access public
+ */
+ public $filename;
+
+ /**
+ * Human readable comment
+ *
+ * @access public
+ */
+ public $comment;
+
+ /**
+ * Don't allow anything to be set
+ *
+ * @access public
+ */
+ public function __set($name, $value)
+ {
+ trigger_error("Cannot write property $name", E_USER_ERROR);
+ }
+
+ /**
+ * Set the compressed string and related properties
+ *
+ * @access public
+ */
+ public function __construct($data)
+ {
+ $this->compressed_data = $data;
+ $this->compressed_size = strlen($data);
+ }
+
+ /**
+ * Decode the GZIP stream
+ *
+ * @access public
+ */
+ public function parse()
+ {
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Check ID1, ID2, and CM
+ if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
+ {
+ return false;
+ }
+
+ // Get the FLG (FLaGs)
+ $this->flags = ord($this->compressed_data[3]);
+
+ // FLG bits above (1 << 4) are reserved
+ if ($this->flags > 0x1F)
+ {
+ return false;
+ }
+
+ // Advance the pointer after the above
+ $this->position += 4;
+
+ // MTIME
+ $mtime = substr($this->compressed_data, $this->position, 4);
+ // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
+ if (current(unpack('S', "\x00\x01")) === 1)
+ {
+ $mtime = strrev($mtime);
+ }
+ $this->MTIME = current(unpack('l', $mtime));
+ $this->position += 4;
+
+ // Get the XFL (eXtra FLags)
+ $this->XFL = ord($this->compressed_data[$this->position++]);
+
+ // Get the OS (Operating System)
+ $this->OS = ord($this->compressed_data[$this->position++]);
+
+ // Parse the FEXTRA
+ if ($this->flags & 4)
+ {
+ // Read subfield IDs
+ $this->SI1 = $this->compressed_data[$this->position++];
+ $this->SI2 = $this->compressed_data[$this->position++];
+
+ // SI2 set to zero is reserved for future use
+ if ($this->SI2 === "\x00")
+ {
+ return false;
+ }
+
+ // Get the length of the extra field
+ $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
+ $position += 2;
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 4;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the extra field to the given data
+ $this->extra_field = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FNAME
+ if ($this->flags & 8)
+ {
+ // Get the length of the filename
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 1;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the original filename to the given string
+ $this->filename = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len + 1;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FCOMMENT
+ if ($this->flags & 16)
+ {
+ // Get the length of the comment
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
+
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 1;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Set the original comment to the given string
+ $this->comment = substr($this->compressed_data, $this->position, $len);
+ $this->position += $len + 1;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Parse the FHCRC
+ if ($this->flags & 2)
+ {
+ // Check the length of the string is still valid
+ $this->min_compressed_size += $len + 2;
+ if ($this->compressed_size >= $this->min_compressed_size)
+ {
+ // Read the CRC
+ $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
+
+ // Check the CRC matches
+ if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
+ {
+ $this->position += 2;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Decompress the actual data
+ if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
+ {
+ return false;
+ }
+ else
+ {
+ $this->position = $this->compressed_size - 8;
+ }
+
+ // Check CRC of data
+ $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
+ $this->position += 4;
+ /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
+ {
+ return false;
+ }*/
+
+ // Check ISIZE of data
+ $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
+ $this->position += 4;
+ if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
+ {
+ return false;
+ }
+
+ // Wow, against all odds, we've actually got a valid gzip string
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopbase.class.php b/3rdparty/aws-sdk/utilities/hadoopbase.class.php
new file mode 100644
index 00000000000..eb8bc5c3a81
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopbase.class.php
@@ -0,0 +1,67 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains core functionality for Hadoop helpers.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopBase
+{
+ /**
+ * Runs a specified script on the master node of your cluster.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ */
+ public static function script_runner($script, $args = null)
+ {
+ if (!$args) $args = array();
+ array_unshift($args, $script);
+
+ return array(
+ 'Jar' => 's3://us-east-1.elasticmapreduce/libs/script-runner/script-runner.jar',
+ 'Args' => $args
+ );
+ }
+
+ /**
+ * Prepares a Hive or Pig script before passing it to the script runner.
+ *
+ * @param string $type (Required) The type of script to run. [Allowed values: `hive`, `pig`].
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function hive_pig_script($type, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--base-path', 's3://us-east-1.elasticmapreduce/libs/' . $type . '/'), $args);
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/libs/' . $type . '/' . $type . '-script', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php b/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php
new file mode 100644
index 00000000000..baaa0c08d4b
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopbootstrap.class.php
@@ -0,0 +1,127 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of pre-built Amazon EMR Hadoop Bootstrap Actions.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopBootstrap extends CFHadoopBase
+{
+ // Config file types
+ const CONFIG_SITE = 'S';
+ const CONFIG_DEFAULT = 'D';
+ const CONFIG_CORE = 'C';
+ const CONFIG_HDFS = 'H';
+ const CONFIG_MAPREDUCE = 'M';
+
+ // Daemon types
+ const DAEMON_NAME_NODE = 'namenode';
+ const DAEMON_DATA_NODE = 'datanode';
+ const DAEMON_JOB_TRACKER = 'jobtracker';
+ const DAEMON_TASK_TRACKER = 'tasktracker';
+ const DAEMON_CLIENT = 'client';
+
+ /**
+ * Create a new run-if bootstrap action which lets you conditionally run bootstrap actions.
+ *
+ * @param string $condition (Required) The condition to evaluate. If <code>true</code>, the bootstrap action executes.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function run_if($condition, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/run-if', $args);
+ }
+
+ /**
+ * Specify options to merge with Hadoop's default configuration.
+ *
+ * @param string $file (Required) The Hadoop configuration file to merge with. [Allowed values: <code>CFHadoopBootstrap::CONFIG_SITE</code>, <code>CFHadoopBootstrap::CONFIG_DEFAULT</code>, <code>CFHadoopBootstrap::CONFIG_CORE</code>, <code>CFHadoopBootstrap::CONFIG_HDFS</code>, <code>CFHadoopBootstrap::CONFIG_MAPREDUCE</code>]
+ * @param string|array $config (Required) This can either be an XML file in S3 (as <code>s3://bucket/path</code>), or an associative array of key-value pairs.
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function configure($file, $config)
+ {
+ $args = array();
+ $file_arg = '-' . $file;
+
+ if (is_string($config))
+ {
+ $args[] = $file_arg;
+ $args[] = $config;
+ }
+ elseif (is_array($config))
+ {
+ foreach ($config as $key => $value)
+ {
+ $args[] = $file_arg;
+ $args[] = $key . '=' . $value;
+ }
+ }
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/configure-hadoop', $args);
+ }
+
+ /**
+ * Create a new bootstrap action which lets you configure Hadoop's daemons. The options are written to
+ * the <code>hadoop-user-env.sh</code> file.
+ *
+ * @param string $daemon_type (Required) The Hadoop daemon to configure.
+ * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
+ * <li><code>HeapSize</code> - <code>integer</code> - Optional - The requested heap size of the daemon, in megabytes.</li>
+ * <li><code>CLIOptions</code> - <code>string</code> - Optional - Additional Java command line arguments to pass to the daemon.</li>
+ * <li><code>Replace</code> - <code>boolean</code> - Optional - Whether or not the file should be replaced. A value of <code>true</code> will replace the existing configuration file. A value of <code>false</code> will append the options to the configuration file.</li></ul>
+ * @return array A configuration set to be provided when running a job flow.
+ */
+ public static function daemon($daemon_type, $opt = null)
+ {
+ if (!$opt) $opt = array();
+ $args = array();
+
+ foreach ($opt as $key => $value)
+ {
+ switch ($key)
+ {
+ case 'HeapSize':
+ $args[] = '--' . $daemon_type . '-heap-size=' . $value;
+ break;
+ case 'CLIOptions':
+ $args[] = '--' . $daemon_type . '-opts="' . $value . '"';
+ break;
+ case 'Replace':
+ if ((is_string($value) && $value === 'true') || (is_bool($value) && $value === true))
+ {
+ $args[] = '--replace';
+ }
+ break;
+ }
+ }
+
+ return self::script_runner('s3://us-east-1.elasticmapreduce/bootstrap-actions/configure-daemons', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/hadoopstep.class.php b/3rdparty/aws-sdk/utilities/hadoopstep.class.php
new file mode 100644
index 00000000000..2371e007489
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/hadoopstep.class.php
@@ -0,0 +1,98 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of pre-built Amazon EMR Hadoop steps.
+ *
+ * @version 2011.05.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://hadoop.apache.org Apache Hadoop
+ */
+class CFHadoopStep extends CFHadoopBase
+{
+ /**
+ * When ran as the first step in your job flow, enables the Hadoop debugging UI in the AWS
+ * Management Console.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ */
+ public static function enable_debugging()
+ {
+ return self::script_runner('s3://us-east-1.elasticmapreduce/libs/state-pusher/0.1/fetch');
+ }
+
+ /**
+ * Step that installs Hive on your job flow.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ */
+ public static function install_hive()
+ {
+ return self::hive_pig_script('hive', '--install-hive');
+ }
+
+ /**
+ * Step that runs a Hive script on your job flow.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://hive.apache.org Apache Hive
+ */
+ public static function run_hive_script($script, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--run-hive-script', '--args', '-f', $script), $args);
+
+ return self::hive_pig_script('hive', $args);
+ }
+
+ /**
+ * Step that installs Pig on your job flow.
+ *
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function install_pig()
+ {
+ return self::hive_pig_script('pig', '--install-pig');
+ }
+
+ /**
+ * Step that runs a Pig script on your job flow.
+ *
+ * @param string $script (Required) The script to run with `script-runner.jar`.
+ * @param array $args (Optional) An indexed array of arguments to pass to the script.
+ * @return array A standard array that is intended to be passed into a <CFStepConfig> object.
+ * @link http://pig.apache.org Apache Pig
+ */
+ public static function run_pig_script($script, $args = null)
+ {
+ if (!$args) $args = array();
+ $args = is_array($args) ? $args : array($args);
+ $args = array_merge(array('--run-pig-script', '--args', '-f', $script), $args);
+
+ return self::hive_pig_script('pig', $args);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/info.class.php b/3rdparty/aws-sdk/utilities/info.class.php
new file mode 100644
index 00000000000..2ba289a5f01
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/info.class.php
@@ -0,0 +1,69 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a series of methods that provide information about the SDK.
+ *
+ * @version 2010.10.01
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFInfo
+{
+ /**
+ * Gets information about the web service APIs that the SDK supports.
+ *
+ * @return array An associative array containing service classes and API versions.
+ */
+ public static function api_support()
+ {
+ $existing_classes = get_declared_classes();
+
+ foreach (glob(dirname(dirname(__FILE__)) . '/services/*.class.php') as $file)
+ {
+ include $file;
+ }
+
+ $with_sdk_classes = get_declared_classes();
+ $new_classes = array_diff($with_sdk_classes, $existing_classes);
+ $filtered_classes = array();
+ $collect = array();
+
+ foreach ($new_classes as $class)
+ {
+ if (strpos($class, 'Amazon') !== false)
+ {
+ $filtered_classes[] = $class;
+ }
+ }
+
+ $filtered_classes = array_values($filtered_classes);
+
+ foreach ($filtered_classes as $class)
+ {
+ $obj = new $class();
+ $collect[get_class($obj)] = $obj->api_version;
+ unset($obj);
+ }
+
+ return $collect;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/json.class.php b/3rdparty/aws-sdk/utilities/json.class.php
new file mode 100644
index 00000000000..dfa83839863
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/json.class.php
@@ -0,0 +1,89 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Handles the conversion of data from JSON to other formats.
+ *
+ * @version 2012.01.27
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFJSON
+{
+ /**
+ * Converts a JSON string to a CFSimpleXML object.
+ *
+ * @param string|array $json (Required) Pass either a valid JSON-formatted string, or an associative array.
+ * @param string $parser (Optional) The name of the class to use to parse the XML. This class should extend <code>SimpleXMLElement</code>. Has a default value of <code>CFSimpleXML</code>.
+ * @return CFSimpleXML An XML representation of the data.
+ */
+ public static function to_xml($json, $parser = 'CFSimpleXML')
+ {
+ // If we haven't parsed the JSON, do it
+ if (!is_array($json))
+ {
+ // Handle the case of JSON-encoded NULL value
+ if ($json === 'null')
+ {
+ $json = null;
+ }
+ else
+ {
+ $json = json_decode($json, true);
+
+ if (function_exists('json_last_error'))
+ {
+ // Did we encounter an error?
+ switch (json_last_error())
+ {
+ case JSON_ERROR_DEPTH:
+ throw new JSON_Exception('Maximum stack depth exceeded.');
+
+ case JSON_ERROR_CTRL_CHAR:
+ throw new JSON_Exception('Unexpected control character found.');
+
+ case JSON_ERROR_SYNTAX:
+ throw new JSON_Exception('Syntax error; Malformed JSON.');
+
+ case JSON_ERROR_STATE_MISMATCH:
+ throw new JSON_Exception('Invalid or malformed JSON.');
+ }
+ }
+ // json_last_error() not available?
+ elseif ($json === null)
+ {
+ throw new JSON_Exception('Unknown JSON error. Be sure to validate your JSON and read the notes on http://php.net/json_decode.');
+ }
+ }
+ }
+
+ // Hand off for the recursive work
+ $string = Array2DOM::arrayToXMLString($json, 'rootElement', true);
+
+ return simplexml_load_string($string, $parser, LIBXML_NOCDATA);
+ }
+}
+
+
+/**
+ * Default JSON Exception.
+ */
+class JSON_Exception extends Exception {}
diff --git a/3rdparty/aws-sdk/utilities/manifest.class.php b/3rdparty/aws-sdk/utilities/manifest.class.php
new file mode 100644
index 00000000000..82410a328db
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/manifest.class.php
@@ -0,0 +1,54 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of generating manifests for the AWS Import/Export service.
+ *
+ * @version 2010.11.22
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFManifest
+{
+
+ /**
+ * Takes a JSON object as a string to convert to a YAML manifest.
+ *
+ * @param string $json (Required) A JSON object. The JSON string should use canonical rules (e.g., double quotes, quoted keys) as is required by PHP's <php:json_encode()> function.
+ * @return string A YAML manifest document.
+ */
+ public static function json($json)
+ {
+ $map = json_decode($json, true);
+ return sfYaml::dump($map);
+ }
+
+ /**
+ * Takes an associative array to convert to a YAML manifest.
+ *
+ * @param array $map (Required) An associative array.
+ * @return string A YAML manifest document.
+ */
+ public static function map($map)
+ {
+ return sfYaml::dump($map);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/mimetypes.class.php b/3rdparty/aws-sdk/utilities/mimetypes.class.php
new file mode 100644
index 00000000000..5fa23d3942a
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/mimetypes.class.php
@@ -0,0 +1,223 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of looking up the content-types for a variety of file extensions.
+ *
+ * @version 2010.07.20
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFMimeTypes
+{
+ /**
+ * Map of the extension-to-mime-types that we support.
+ */
+ public static $mime_types = array(
+ '3gp' => 'video/3gpp',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'asc' => 'text/plain',
+ 'atom' => 'application/atom+xml',
+ 'au' => 'audio/basic',
+ 'avi' => 'video/x-msvideo',
+ 'bcpio' => 'application/x-bcpio',
+ 'bin' => 'application/octet-stream',
+ 'bmp' => 'image/bmp',
+ 'cdf' => 'application/x-netcdf',
+ 'cgm' => 'image/cgm',
+ 'class' => 'application/octet-stream',
+ 'cpio' => 'application/x-cpio',
+ 'cpt' => 'application/mac-compactpro',
+ 'csh' => 'application/x-csh',
+ 'css' => 'text/css',
+ 'dcr' => 'application/x-director',
+ 'dif' => 'video/x-dv',
+ 'dir' => 'application/x-director',
+ 'djv' => 'image/vnd.djvu',
+ 'djvu' => 'image/vnd.djvu',
+ 'dll' => 'application/octet-stream',
+ 'dmg' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'doc' => 'application/msword',
+ 'dtd' => 'application/xml-dtd',
+ 'dv' => 'video/x-dv',
+ 'dvi' => 'application/x-dvi',
+ 'dxr' => 'application/x-director',
+ 'eps' => 'application/postscript',
+ 'etx' => 'text/x-setext',
+ 'exe' => 'application/octet-stream',
+ 'ez' => 'application/andrew-inset',
+ 'flv' => 'video/x-flv',
+ 'gif' => 'image/gif',
+ 'gram' => 'application/srgs',
+ 'grxml' => 'application/srgs+xml',
+ 'gtar' => 'application/x-gtar',
+ 'gz' => 'application/x-gzip',
+ 'hdf' => 'application/x-hdf',
+ 'hqx' => 'application/mac-binhex40',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'ice' => 'x-conference/x-cooltalk',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ief' => 'image/ief',
+ 'ifb' => 'text/calendar',
+ 'iges' => 'model/iges',
+ 'igs' => 'model/iges',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'jp2' => 'image/jp2',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'js' => 'application/x-javascript',
+ 'kar' => 'audio/midi',
+ 'latex' => 'application/x-latex',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'm3u' => 'audio/x-mpegurl',
+ 'm4a' => 'audio/mp4a-latm',
+ 'm4p' => 'audio/mp4a-latm',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'm4v' => 'video/x-m4v',
+ 'mac' => 'image/x-macpaint',
+ 'man' => 'application/x-troff-man',
+ 'mathml' => 'application/mathml+xml',
+ 'me' => 'application/x-troff-me',
+ 'mesh' => 'model/mesh',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mif' => 'application/vnd.mif',
+ 'mov' => 'video/quicktime',
+ 'movie' => 'video/x-sgi-movie',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpga' => 'audio/mpeg',
+ 'ms' => 'application/x-troff-ms',
+ 'msh' => 'model/mesh',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'nc' => 'application/x-netcdf',
+ 'oda' => 'application/oda',
+ 'ogg' => 'application/ogg',
+ 'ogv' => 'video/ogv',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pct' => 'image/pict',
+ 'pdb' => 'chemical/x-pdb',
+ 'pdf' => 'application/pdf',
+ 'pgm' => 'image/x-portable-graymap',
+ 'pgn' => 'application/x-chess-pgn',
+ 'pic' => 'image/pict',
+ 'pict' => 'image/pict',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'pnt' => 'image/x-macpaint',
+ 'pntg' => 'image/x-macpaint',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'ps' => 'application/postscript',
+ 'qt' => 'video/quicktime',
+ 'qti' => 'image/x-quicktime',
+ 'qtif' => 'image/x-quicktime',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'ras' => 'image/x-cmu-raster',
+ 'rdf' => 'application/rdf+xml',
+ 'rgb' => 'image/x-rgb',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'roff' => 'application/x-troff',
+ 'rtf' => 'text/rtf',
+ 'rtx' => 'text/richtext',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'silo' => 'model/mesh',
+ 'sit' => 'application/x-stuffit',
+ 'skd' => 'application/x-koan',
+ 'skm' => 'application/x-koan',
+ 'skp' => 'application/x-koan',
+ 'skt' => 'application/x-koan',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'snd' => 'audio/basic',
+ 'so' => 'application/octet-stream',
+ 'spl' => 'application/x-futuresplash',
+ 'src' => 'application/x-wais-source',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'svg' => 'image/svg+xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 't' => 'application/x-troff',
+ 'tar' => 'application/x-tar',
+ 'tcl' => 'application/x-tcl',
+ 'tex' => 'application/x-tex',
+ 'texi' => 'application/x-texinfo',
+ 'texinfo' => 'application/x-texinfo',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'tr' => 'application/x-troff',
+ 'tsv' => 'text/tab-separated-values',
+ 'txt' => 'text/plain',
+ 'ustar' => 'application/x-ustar',
+ 'vcd' => 'application/x-cdlink',
+ 'vrml' => 'model/vrml',
+ 'vxml' => 'application/voicexml+xml',
+ 'wav' => 'audio/x-wav',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'webm' => 'video/webm',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wrl' => 'model/vrml',
+ 'xbm' => 'image/x-xbitmap',
+ 'xht' => 'application/xhtml+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xml' => 'application/xml',
+ 'xpm' => 'image/x-xpixmap',
+ 'xsl' => 'application/xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'xwd' => 'image/x-xwindowdump',
+ 'xyz' => 'chemical/x-xyz',
+ 'zip' => 'application/zip',
+ );
+
+ /**
+ * Attempt to match the file extension to a known mime-type.
+ *
+ * @param string $ext (Required) The file extension to attempt to map.
+ * @return string The mime-type to use for the file extension.
+ */
+ public static function get_mimetype($ext)
+ {
+ return (isset(self::$mime_types[$ext]) ? self::$mime_types[$ext] : 'application/octet-stream');
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/policy.class.php b/3rdparty/aws-sdk/utilities/policy.class.php
new file mode 100644
index 00000000000..9c53fee0d72
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/policy.class.php
@@ -0,0 +1,134 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of signing JSON policy documents.
+ *
+ * @version 2011.04.25
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFPolicy
+{
+ /**
+ * Stores the object that contains the authentication credentials.
+ */
+ public $auth;
+
+ /**
+ * Stores the policy object that we're working with.
+ */
+ public $json_policy;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param CFRuntime $auth (Required) An instance of any authenticated AWS object that is an instance of <CFRuntime> (e.g. <AmazonEC2>, <AmazonS3>).
+ * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
+ * @return $this A reference to the current instance.
+ * @link http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?HTTPPOSTForms.html S3 Policies
+ * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?AccessPolicyLanguage.html Access Policy Language
+ */
+ public function __construct($auth, $policy)
+ {
+ $this->auth = $auth;
+
+ if (is_array($policy)) // We received an associative array...
+ {
+ $this->json_policy = json_encode($policy);
+ }
+ else // We received a valid, parseable JSON string...
+ {
+ $this->json_policy = json_encode(json_decode($policy, true));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param CFRuntime $auth (Required) An instance of any authenticated AWS object that is an instance of <CFRuntime> (e.g. <AmazonEC2>, <AmazonS3>).
+ * @param string|array $policy (Required) The associative array representing the S3 policy to use, or a string of JSON content.
+ * @return $this A reference to the current instance.
+ */
+ public static function init($auth, $policy)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($auth, $policy);
+ }
+
+ /**
+ * Get the key from the authenticated instance.
+ *
+ * @return string The key from the authenticated instance.
+ */
+ public function get_key()
+ {
+ return $this->auth->key;
+ }
+
+ /**
+ * Base64-encodes the JSON string.
+ *
+ * @return string The Base64-encoded version of the JSON string.
+ */
+ public function get_policy()
+ {
+ return base64_encode($this->json_policy);
+ }
+
+ /**
+ * Gets the JSON string with the whitespace removed.
+ *
+ * @return string The JSON string without extraneous whitespace.
+ */
+ public function get_json()
+ {
+ return $this->json_policy;
+ }
+
+ /**
+ * Gets the JSON string with the whitespace removed.
+ *
+ * @return string The Base64-encoded, signed JSON string.
+ */
+ public function get_policy_signature()
+ {
+ return base64_encode(hash_hmac('sha1', $this->get_policy(), $this->auth->secret_key));
+ }
+
+ /**
+ * Decode a policy that was returned from the service.
+ *
+ * @param string $response (Required) The policy returned by AWS that you want to decode into an object.
+ * @return string The Base64-encoded, signed JSON string.
+ */
+ public static function decode_policy($response)
+ {
+ return json_decode(urldecode($response), true);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/request.class.php b/3rdparty/aws-sdk/utilities/request.class.php
new file mode 100644
index 00000000000..8e049fb5169
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/request.class.php
@@ -0,0 +1,70 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `RequestCore` class with some AWS-specific customizations.
+ *
+ * @version 2011.12.02
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFRequest extends RequestCore
+{
+ /**
+ * The default class to use for HTTP Requests (defaults to <CFRequest>).
+ */
+ public $request_class = 'CFRequest';
+
+ /**
+ * The default class to use for HTTP Responses (defaults to <CFResponse>).
+ */
+ public $response_class = 'CFResponse';
+
+ /**
+ * The active credential set.
+ */
+ public $credentials;
+
+
+ /*%******************************************************************************************%*/
+ // CONSTRUCTOR
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param string $url (Optional) The URL to request or service endpoint to query.
+ * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+ * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+ * @param CFCredential $credentials (Required) The credentials to use for signing and making requests.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($url = null, $proxy = null, $helpers = null, CFCredential $credentials = null)
+ {
+ parent::__construct($url, $proxy, $helpers);
+
+ // Standard settings for all requests
+ $this->set_useragent(CFRUNTIME_USERAGENT);
+ $this->credentials = $credentials;
+ $this->cacert_location = ($this->credentials['certificate_authority'] ? $this->credentials['certificate_authority'] : false);
+
+ return $this;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/response.class.php b/3rdparty/aws-sdk/utilities/response.class.php
new file mode 100644
index 00000000000..740d55d5d94
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/response.class.php
@@ -0,0 +1,29 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `ResponseCore` class with some AWS-specific customizations.
+ *
+ * @version 2010.10.11
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFResponse extends ResponseCore {}
diff --git a/3rdparty/aws-sdk/utilities/simplexml.class.php b/3rdparty/aws-sdk/utilities/simplexml.class.php
new file mode 100644
index 00000000000..ba93b9ea3c0
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/simplexml.class.php
@@ -0,0 +1,248 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Wraps the underlying `SimpleXMLIterator` class with enhancements for rapidly traversing the DOM tree,
+ * converting types, and comparisons.
+ *
+ * @version 2012.01.17
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ * @link http://php.net/SimpleXML SimpleXML
+ */
+class CFSimpleXML extends SimpleXMLIterator
+{
+ /**
+ * Stores the namespace name to use in XPath queries.
+ */
+ public $xml_ns;
+
+ /**
+ * Stores the namespace URI to use in XPath queries.
+ */
+ public $xml_ns_url;
+
+ /**
+ * Catches requests made to methods that don't exist. Specifically, looks for child nodes via XPath.
+ *
+ * @param string $name (Required) The name of the method.
+ * @param array $arguments (Required) The arguments passed to the method.
+ * @return mixed Either an array of matches, or a single <CFSimpleXML> element.
+ */
+ public function __call($name, $arguments)
+ {
+ // Remap $this
+ $self = $this;
+
+ // Re-base the XML
+ $self = new CFSimpleXML($self->asXML());
+
+ // Determine XPath query
+ $self->xpath_expression = 'descendant-or-self::' . $name;
+
+ // Get the results and augment with CFArray
+ $results = $self->xpath($self->xpath_expression);
+ if (!count($results)) return false;
+ $results = new CFArray($results);
+
+ // If an integer was passed, return only that result
+ if (isset($arguments[0]) && is_int($arguments[0]))
+ {
+ if (isset($results[$arguments[0]]))
+ {
+ return $results[$arguments[0]];
+ }
+
+ return false;
+ }
+
+ return $results;
+ }
+
+ /**
+ * Alternate approach to constructing a new instance. Supports chaining.
+ *
+ * @param string $data (Required) A well-formed XML string or the path or URL to an XML document if $data_is_url is <code>true</code>.
+ * @param integer $options (Optional) Used to specify additional LibXML parameters. The default value is <code>0</code>.
+ * @param boolean $data_is_url (Optional) Specify a value of <code>true</code> to specify that data is a path or URL to an XML document instead of string data. The default value is <code>false</code>.
+ * @param string $ns (Optional) The XML namespace to return values for.
+ * @param boolean $is_prefix (Optional) (No description provided by PHP.net.)
+ * @return CFSimpleXML Creates a new <CFSimpleXML> element.
+ */
+ public static function init($data, $options = 0, $data_is_url, $ns, $is_prefix = false)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($data, $options, $data_is_url, $ns, $is_prefix);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // TRAVERSAL
+
+ /**
+ * Wraps the results of an XPath query in a <CFArray> object.
+ *
+ * @param string $expr (Required) The XPath expression to use to query the XML response.
+ * @return CFArray A <CFArray> object containing the results of the XPath query.
+ */
+ public function query($expr)
+ {
+ return new CFArray($this->xpath($expr));
+ }
+
+ /**
+ * Gets the parent or a preferred ancestor of the current element.
+ *
+ * @param string $node (Optional) Name of the ancestor element to match and return.
+ * @return CFSimpleXML A <CFSimpleXML> object containing the requested node.
+ */
+ public function parent($node = null)
+ {
+ if ($node)
+ {
+ $parents = $this->xpath('ancestor-or-self::' . $node);
+ }
+ else
+ {
+ $parents = $this->xpath('parent::*');
+ }
+
+ return $parents[0];
+ }
+
+
+ /*%******************************************************************************************%*/
+ // ALTERNATE FORMATS
+
+ /**
+ * Gets the current XML node as a true string.
+ *
+ * @return string The current XML node as a true string.
+ */
+ public function to_string()
+ {
+ return (string) $this;
+ }
+
+ /**
+ * Gets the current XML node as <CFArray>, a child class of PHP's <php:ArrayObject> class.
+ *
+ * @return CFArray The current XML node as a <CFArray> object.
+ */
+ public function to_array()
+ {
+ return new CFArray(json_decode(json_encode($this), true));
+ }
+
+ /**
+ * Gets the current XML node as a stdClass object.
+ *
+ * @return array The current XML node as a stdClass object.
+ */
+ public function to_stdClass()
+ {
+ return json_decode(json_encode($this));
+ }
+
+ /**
+ * Gets the current XML node as a JSON string.
+ *
+ * @return string The current XML node as a JSON string.
+ */
+ public function to_json()
+ {
+ return json_encode($this);
+ }
+
+ /**
+ * Gets the current XML node as a YAML string.
+ *
+ * @return string The current XML node as a YAML string.
+ */
+ public function to_yaml()
+ {
+ return sfYaml::dump(json_decode(json_encode($this), true), 5);
+ }
+
+
+ /*%******************************************************************************************%*/
+ // COMPARISONS
+
+ /**
+ * Whether or not the current node exactly matches the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node exactly matches the compared value.
+ */
+ public function is($value)
+ {
+ return ((string) $this === $value);
+ }
+
+ /**
+ * Whether or not the current node contains the compared value.
+ *
+ * @param string $value (Required) The value to use to determine whether it is contained within the node.
+ * @return boolean Whether or not the current node contains the compared value.
+ */
+ public function contains($value)
+ {
+ return (stripos((string) $this, $value) !== false);
+ }
+
+ /**
+ * Whether or not the current node matches the regular expression pattern.
+ *
+ * @param string $pattern (Required) The pattern to match the current node against.
+ * @return boolean Whether or not the current node matches the pattern.
+ */
+ public function matches($pattern)
+ {
+ return (bool) preg_match($pattern, (string) $this);
+ }
+
+ /**
+ * Whether or not the current node starts with the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node starts with the compared value.
+ */
+ public function starts_with($value)
+ {
+ return $this->matches("@^$value@u");
+ }
+
+ /**
+ * Whether or not the current node ends with the compared value.
+ *
+ * @param string $value (Required) The value to compare the current node to.
+ * @return boolean Whether or not the current node ends with the compared value.
+ */
+ public function ends_with($value)
+ {
+ return $this->matches("@$value$@u");
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/stacktemplate.class.php b/3rdparty/aws-sdk/utilities/stacktemplate.class.php
new file mode 100644
index 00000000000..1e29ef34036
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/stacktemplate.class.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Simplifies the process of preparing JSON stack templates.
+ *
+ * @version 2011.02.03
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFStackTemplate
+{
+ /**
+ * Removes whitespace from a JSON template.
+ *
+ * @param string $template (Required) A JSON representation of the stack template. Must have <a href="http://docs.php.net/manual/en/function.json-decode.php#refsect1-function.json-decode-examples">strict JSON-specific formatting</a>.
+ * @return string A JSON representation of the template.
+ */
+ public static function json($template)
+ {
+ return json_encode(json_decode($template, true));
+ }
+
+ /**
+ * Converts an associative array (map) of the template into a JSON string.
+ *
+ * @param array $template (Required) An associative array that maps directly to its JSON counterpart.
+ * @return string A JSON representation of the template.
+ */
+ public static function map($template)
+ {
+ return json_encode($template);
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/stepconfig.class.php b/3rdparty/aws-sdk/utilities/stepconfig.class.php
new file mode 100644
index 00000000000..71492995f44
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/stepconfig.class.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains functionality for simplifying Amazon EMR Hadoop steps.
+ *
+ * @version 2010.11.16
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFStepConfig
+{
+
+ /**
+ * Stores the configuration map.
+ */
+ public $config;
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @param array $config (Required) An associative array representing the Hadoop step configuration.
+ * @return $this A reference to the current instance.
+ */
+ public function __construct($config)
+ {
+ // Handle Hadoop jar arguments
+ if (isset($config['HadoopJarStep']['Args']) && $args = $config['HadoopJarStep']['Args'])
+ {
+ $config['HadoopJarStep']['Args'] = is_array($args) ? $args : array($args);
+ }
+
+ $this->config = $config;
+ }
+
+ /**
+ * Constructs a new instance of this class, and allows chaining.
+ *
+ * @param array $config (Required) An associative array representing the Hadoop step configuration.
+ * @return $this A reference to the current instance.
+ */
+ public static function init($config)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<'))
+ {
+ throw new Exception('PHP 5.3 or newer is required to instantiate a new class with CLASS::init().');
+ }
+
+ $self = get_called_class();
+ return new $self($config);
+ }
+
+ /**
+ * Returns a JSON representation of the object when typecast as a string.
+ *
+ * @return string A JSON representation of the object.
+ * @link http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring PHP Magic Methods
+ */
+ public function __toString()
+ {
+ return json_encode($this->config);
+ }
+
+ /**
+ * Returns the configuration data.
+ *
+ * @return array The configuration data.
+ */
+ public function get_config()
+ {
+ return $this->config;
+ }
+}
diff --git a/3rdparty/aws-sdk/utilities/utilities.class.php b/3rdparty/aws-sdk/utilities/utilities.class.php
new file mode 100755
index 00000000000..d4d1120abff
--- /dev/null
+++ b/3rdparty/aws-sdk/utilities/utilities.class.php
@@ -0,0 +1,399 @@
+<?php
+/*
+ * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+
+/*%******************************************************************************************%*/
+// CLASS
+
+/**
+ * Contains a set of utility methods for connecting to, and working with, AWS.
+ *
+ * @version 2010.09.30
+ * @license See the included NOTICE.md file for more information.
+ * @copyright See the included NOTICE.md file for more information.
+ * @link http://aws.amazon.com/php/ PHP Developer Center
+ */
+class CFUtilities
+{
+
+ /*%******************************************************************************************%*/
+ // CONSTANTS
+
+ /**
+ * Define the RFC 2616-compliant date format.
+ */
+ const DATE_FORMAT_RFC2616 = 'D, d M Y H:i:s \G\M\T';
+
+ /**
+ * Define the ISO-8601-compliant date format.
+ */
+ const DATE_FORMAT_ISO8601 = 'Y-m-d\TH:i:s\Z';
+
+ /**
+ * Define the MySQL-compliant date format.
+ */
+ const DATE_FORMAT_MYSQL = 'Y-m-d H:i:s';
+
+ /**
+ * Define the Signature v4 date format.
+ */
+ const DATE_FORMAT_SIGV4 = 'Ymd\THis\Z';
+
+
+ /*%******************************************************************************************%*/
+ // METHODS
+
+ /**
+ * Constructs a new instance of this class.
+ *
+ * @return $this A reference to the current instance.
+ */
+ public function __construct()
+ {
+ return $this;
+ }
+
+ /**
+ * Retrieves the value of a class constant, while avoiding the `T_PAAMAYIM_NEKUDOTAYIM` error. Misspelled because `const` is a reserved word.
+ *
+ * @param object $class (Required) An instance of the class containing the constant.
+ * @param string $const (Required) The name of the constant to retrieve.
+ * @return mixed The value of the class constant.
+ */
+ public function konst($class, $const)
+ {
+ if (is_string($class))
+ {
+ $ref = new ReflectionClass($class);
+ }
+ else
+ {
+ $ref = new ReflectionObject($class);
+ }
+
+ return $ref->getConstant($const);
+ }
+
+ /**
+ * Convert a HEX value to Base64.
+ *
+ * @param string $str (Required) Value to convert.
+ * @return string Base64-encoded string.
+ */
+ public function hex_to_base64($str)
+ {
+ $raw = '';
+
+ for ($i = 0; $i < strlen($str); $i += 2)
+ {
+ $raw .= chr(hexdec(substr($str, $i, 2)));
+ }
+
+ return base64_encode($raw);
+ }
+
+ /**
+ * Convert an associative array into a query string.
+ *
+ * @param array $array (Required) Array to convert.
+ * @return string URL-friendly query string.
+ */
+ public function to_query_string($array)
+ {
+ $temp = array();
+
+ foreach ($array as $key => $value)
+ {
+ if (is_string($key) && !is_array($value))
+ {
+ $temp[] = rawurlencode($key) . '=' . rawurlencode($value);
+ }
+ }
+
+ return implode('&', $temp);
+ }
+
+ /**
+ * Convert an associative array into a sign-able string.
+ *
+ * @param array $array (Required) Array to convert.
+ * @return string URL-friendly sign-able string.
+ */
+ public function to_signable_string($array)
+ {
+ $t = array();
+
+ foreach ($array as $k => $v)
+ {
+ $t[] = $this->encode_signature2($k) . '=' . $this->encode_signature2($v);
+ }
+
+ return implode('&', $t);
+ }
+
+ /**
+ * Encode the value according to RFC 3986.
+ *
+ * @param string $string (Required) String to convert.
+ * @return string URL-friendly sign-able string.
+ */
+ public function encode_signature2($string)
+ {
+ $string = rawurlencode($string);
+ return str_replace('%7E', '~', $string);
+ }
+
+ /**
+ * Convert a query string into an associative array. Multiple, identical keys will become an indexed array.
+ *
+ * @param string $qs (Required) Query string to convert.
+ * @return array Associative array of keys and values.
+ */
+ public function query_to_array($qs)
+ {
+ $query = explode('&', $qs);
+ $data = array();
+
+ foreach ($query as $q)
+ {
+ $q = explode('=', $q);
+
+ if (isset($data[$q[0]]) && is_array($data[$q[0]]))
+ {
+ $data[$q[0]][] = urldecode($q[1]);
+ }
+ else if (isset($data[$q[0]]) && !is_array($data[$q[0]]))
+ {
+ $data[$q[0]] = array($data[$q[0]]);
+ $data[$q[0]][] = urldecode($q[1]);
+ }
+ else
+ {
+ $data[urldecode($q[0])] = urldecode($q[1]);
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * Return human readable file sizes.
+ *
+ * @author Aidan Lister <aidan@php.net>
+ * @author Ryan Parman <ryan@getcloudfusion.com>
+ * @license http://www.php.net/license/3_01.txt PHP License
+ * @param integer $size (Required) Filesize in bytes.
+ * @param string $unit (Optional) The maximum unit to use. Defaults to the largest appropriate unit.
+ * @param string $default (Optional) The format for the return string. Defaults to `%01.2f %s`.
+ * @return string The human-readable file size.
+ * @link http://aidanlister.com/repos/v/function.size_readable.php Original Function
+ */
+ public function size_readable($size, $unit = null, $default = null)
+ {
+ // Units
+ $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB');
+ $mod = 1024;
+ $ii = count($sizes) - 1;
+
+ // Max unit
+ $unit = array_search((string) $unit, $sizes);
+ if ($unit === null || $unit === false)
+ {
+ $unit = $ii;
+ }
+
+ // Return string
+ if ($default === null)
+ {
+ $default = '%01.2f %s';
+ }
+
+ // Loop
+ $i = 0;
+ while ($unit != $i && $size >= 1024 && $i < $ii)
+ {
+ $size /= $mod;
+ $i++;
+ }
+
+ return sprintf($default, $size, $sizes[$i]);
+ }
+
+ /**
+ * Convert a number of seconds into Hours:Minutes:Seconds.
+ *
+ * @param integer $seconds (Required) The number of seconds to convert.
+ * @return string The formatted time.
+ */
+ public function time_hms($seconds)
+ {
+ $time = '';
+
+ // First pass
+ $hours = (int) ($seconds / 3600);
+ $seconds = $seconds % 3600;
+ $minutes = (int) ($seconds / 60);
+ $seconds = $seconds % 60;
+
+ // Cleanup
+ $time .= ($hours) ? $hours . ':' : '';
+ $time .= ($minutes < 10 && $hours > 0) ? '0' . $minutes : $minutes;
+ $time .= ':';
+ $time .= ($seconds < 10) ? '0' . $seconds : $seconds;
+
+ return $time;
+ }
+
+ /**
+ * Returns the first value that is set. Based on [Try.these()](http://api.prototypejs.org/language/Try/these/) from [Prototype](http://prototypejs.org).
+ *
+ * @param array $attrs (Required) The attributes to test, as strings. Intended for testing properties of the $base object, but also works with variables if you place an @ symbol at the beginning of the command.
+ * @param object $base (Optional) The base object to use, if any.
+ * @param mixed $default (Optional) What to return if there are no matches. Defaults to `null`.
+ * @return mixed Either a matching property of a given object, boolean `false`, or any other data type you might choose.
+ */
+ public function try_these($attrs, $base = null, $default = null)
+ {
+ if ($base)
+ {
+ foreach ($attrs as $attr)
+ {
+ if (isset($base->$attr))
+ {
+ return $base->$attr;
+ }
+ }
+ }
+ else
+ {
+ foreach ($attrs as $attr)
+ {
+ if (isset($attr))
+ {
+ return $attr;
+ }
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Can be removed once all calls are updated.
+ *
+ * @deprecated Use <php:json_encode()> instead.
+ * @param mixed $obj (Required) The PHP object to convert into a JSON string.
+ * @return string A JSON string.
+ */
+ public function json_encode($obj)
+ {
+ return json_encode($obj);
+ }
+
+ /**
+ * Converts a SimpleXML response to an array structure.
+ *
+ * @param ResponseCore $response (Required) A response value.
+ * @return array The response value as a standard, multi-dimensional array.
+ */
+ public function convert_response_to_array(ResponseCore $response)
+ {
+ return json_decode(json_encode($response), true);
+ }
+
+ /**
+ * Checks to see if a date stamp is ISO-8601 formatted, and if not, makes it so.
+ *
+ * @param string $datestamp (Required) A date stamp, or a string that can be parsed into a date stamp.
+ * @return string An ISO-8601 formatted date stamp.
+ */
+ public function convert_date_to_iso8601($datestamp)
+ {
+ if (!preg_match('/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}((\+|-)\d{2}:\d{2}|Z)/m', $datestamp))
+ {
+ return gmdate(self::DATE_FORMAT_ISO8601, strtotime($datestamp));
+ }
+
+ return $datestamp;
+ }
+
+ /**
+ * Determines whether the data is Base64 encoded or not.
+ *
+ * @license http://us.php.net/manual/en/function.base64-decode.php#81425 PHP License
+ * @param string $s (Required) The string to test.
+ * @return boolean Whether the string is Base64 encoded or not.
+ */
+ public function is_base64($s)
+ {
+ return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
+ }
+
+ /**
+ * Determines whether the data is a JSON string or not.
+ *
+ * @param string $s (Required) The string to test.
+ * @return boolean Whether the string is a valid JSON object or not.
+ */
+ public function is_json($s)
+ {
+ return !!(json_decode($s) instanceof stdClass);
+ }
+
+ /**
+ * Decodes `\uXXXX` entities into their real unicode character equivalents.
+ *
+ * @param string $s (Required) The string to decode.
+ * @return string The decoded string.
+ */
+ public function decode_uhex($s)
+ {
+ preg_match_all('/\\\u([0-9a-f]{4})/i', $s, $matches);
+ $matches = $matches[count($matches) - 1];
+ $map = array();
+
+ foreach ($matches as $match)
+ {
+ if (!isset($map[$match]))
+ {
+ $map['\u' . $match] = html_entity_decode('&#' . hexdec($match) . ';', ENT_NOQUOTES, 'UTF-8');
+ }
+ }
+
+ return str_replace(array_keys($map), $map, $s);
+ }
+
+ /**
+ * Generates a random GUID.
+ *
+ * @author Alix Axel <http://www.php.net/manual/en/function.com-create-guid.php#99425>
+ * @license http://www.php.net/license/3_01.txt PHP License
+ * @return string A random GUID.
+ */
+ public function generate_guid()
+ {
+ return sprintf(
+ '%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(16384, 20479),
+ mt_rand(32768, 49151),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535),
+ mt_rand(0, 65535)
+ );
+ }
+}
diff --git a/3rdparty/mediawiki/CSSMin.php b/3rdparty/mediawiki/CSSMin.php
index 1ee2919140f..e9c2badf62b 100644
--- a/3rdparty/mediawiki/CSSMin.php
+++ b/3rdparty/mediawiki/CSSMin.php
@@ -172,7 +172,6 @@ class CSSMin {
$type = self::getMimeType( $file );
// Detect when URLs were preceeded with embed tags, and also verify file size is
// below the limit
- var_dump($match['embed'], $file, filesize($file));
if (
$type
&& $match['embed'][1] > 0
diff --git a/3rdparty/phpass/PasswordHash.php b/3rdparty/phpass/PasswordHash.php
index 12958c7f19e..84447b277df 100644
--- a/3rdparty/phpass/PasswordHash.php
+++ b/3rdparty/phpass/PasswordHash.php
@@ -48,7 +48,7 @@ class PasswordHash {
function get_random_bytes($count)
{
$output = '';
- if (is_readable('/dev/urandom') &&
+ if (@is_readable('/dev/urandom') &&
($fh = @fopen('/dev/urandom', 'rb'))) {
$output = fread($fh, $count);
fclose($fh);
diff --git a/3rdparty/when/When.php b/3rdparty/when/When.php
index 5f97f0eb9bf..185836bf0c5 100644
--- a/3rdparty/when/When.php
+++ b/3rdparty/when/When.php
@@ -586,7 +586,7 @@ class When
}
}
}
- elseif($this->gobyday || $interval == "month")
+ elseif($this->gobyday && $interval == "month")
{
$_mdays = range(1, date('t',mktime(0,0,0,$month,1,$year)));
foreach($_mdays as $_mday)
@@ -621,7 +621,13 @@ class When
if($interval == "month")
{
- $this->try_date->modify('last day of ' . $this->interval . ' ' . $interval);
+
+ $this->try_date->modify('first day of next month');
+ if((int) date('t', $this->try_date->format('U')) > (int) $this->start_date->format('j')){
+ $this->try_date->modify('+' . (int) $this->start_date->format('j') - 1 . ' day');
+ }else{
+ $this->try_date->modify('+' . (int) date('t', $this->try_date->format('U')) - 1 . ' day');
+ }
}
else
{
@@ -722,4 +728,4 @@ class When
}
}
}
-}
+} \ No newline at end of file
diff --git a/apps/bookmarks/addBm.php b/apps/bookmarks/addBm.php
index 313489d22fb..866fa1e7b1e 100644
--- a/apps/bookmarks/addBm.php
+++ b/apps/bookmarks/addBm.php
@@ -28,6 +28,6 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('bookmarks');
require_once('bookmarksHelper.php');
-addBookmark($_GET['url'], '', 'Read-Later');
+addBookmark($_POST['url'], '', 'Read-Later');
include 'templates/addBm.php';
diff --git a/apps/bookmarks/ajax/delBookmark.php b/apps/bookmarks/ajax/delBookmark.php
index 0b5689811ae..5a067701c9f 100644
--- a/apps/bookmarks/ajax/delBookmark.php
+++ b/apps/bookmarks/ajax/delBookmark.php
@@ -30,7 +30,7 @@ $RUNTIME_NOSETUPFS=true;
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('bookmarks');
-$id = $_GET['id'];
+$id = $_POST['id'];
if (!OC_Bookmarks_Bookmarks::deleteUrl($id)){
OC_JSON::error();
exit();
diff --git a/apps/bookmarks/ajax/editBookmark.php b/apps/bookmarks/ajax/editBookmark.php
index db349af35c1..fcec2e1cedb 100644
--- a/apps/bookmarks/ajax/editBookmark.php
+++ b/apps/bookmarks/ajax/editBookmark.php
@@ -39,7 +39,7 @@ if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
$_ut = "UNIX_TIMESTAMP()";
}
-$bookmark_id = (int)$_GET["id"];
+$bookmark_id = (int)$_POST["id"];
$query = OCP\DB::prepare("
UPDATE *PREFIX*bookmarks
@@ -48,8 +48,8 @@ $query = OCP\DB::prepare("
");
$params=array(
- htmlspecialchars_decode($_GET["url"]),
- htmlspecialchars_decode($_GET["title"]),
+ htmlspecialchars_decode($_POST["url"]),
+ htmlspecialchars_decode($_POST["title"]),
);
$query->execute($params);
@@ -67,7 +67,7 @@ $query = OCP\DB::prepare("
VALUES (?, ?)
");
-$tags = explode(' ', urldecode($_GET["tags"]));
+$tags = explode(' ', urldecode($_POST["tags"]));
foreach ($tags as $tag) {
if(empty($tag)) {
//avoid saving blankspaces
diff --git a/apps/bookmarks/ajax/recordClick.php b/apps/bookmarks/ajax/recordClick.php
index 2bd91f232a4..1eee1718d13 100644
--- a/apps/bookmarks/ajax/recordClick.php
+++ b/apps/bookmarks/ajax/recordClick.php
@@ -37,7 +37,7 @@ $query = OCP\DB::prepare("
AND url LIKE ?
");
-$params=array(OCP\USER::getUser(), htmlspecialchars_decode($_GET["url"]));
+$params=array(OCP\USER::getUser(), htmlspecialchars_decode($_POST["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
index c919a5fc439..4de2475d067 100644
--- a/apps/bookmarks/ajax/updateList.php
+++ b/apps/bookmarks/ajax/updateList.php
@@ -33,11 +33,11 @@ OCP\JSON::checkAppEnabled('bookmarks');
//Filter for tag?
-$filterTag = isset($_GET['tag']) ? htmlspecialchars_decode($_GET['tag']) : false;
+$filterTag = isset($_POST['tag']) ? htmlspecialchars_decode($_POST['tag']) : false;
-$offset = isset($_GET['page']) ? intval($_GET['page']) * 10 : 0;
+$offset = isset($_POST['page']) ? intval($_POST['page']) * 10 : 0;
-$sort = isset($_GET['sort']) ? ($_GET['sort']) : 'bookmarks_sorting_recent';
+$sort = isset($_POST['sort']) ? ($_POST['sort']) : 'bookmarks_sorting_recent';
if($sort == 'bookmarks_sorting_clicks') {
$sqlSortColumn = 'clickcount';
} else {
diff --git a/apps/bookmarks/appinfo/database.xml b/apps/bookmarks/appinfo/database.xml
index f2fc68e4b58..b03c1fb2c89 100644
--- a/apps/bookmarks/appinfo/database.xml
+++ b/apps/bookmarks/appinfo/database.xml
@@ -3,7 +3,7 @@
<name>*dbname*</name>
<create>true</create>
<overwrite>false</overwrite>
- <charset>latin1</charset>
+ <charset>utf8</charset>
<table>
<name>*dbprefix*bookmarks</name>
<declaration>
diff --git a/apps/bookmarks/js/addBm.js b/apps/bookmarks/js/addBm.js
index d64e55e8920..625ac8420a8 100644
--- a/apps/bookmarks/js/addBm.js
+++ b/apps/bookmarks/js/addBm.js
@@ -6,6 +6,7 @@ function addBookmark(event) {
var url = $('#bookmark_add_url').val();
var tags = $('#bookmark_add_tags').val();
$.ajax({
+ type: 'POST',
url: 'ajax/addBookmark.php',
data: 'url=' + encodeURI(url) + '&tags=' + encodeURI(tags),
success: function(data){
diff --git a/apps/bookmarks/js/bookmarks.js b/apps/bookmarks/js/bookmarks.js
index a746cf437bf..7f3104e812f 100644
--- a/apps/bookmarks/js/bookmarks.js
+++ b/apps/bookmarks/js/bookmarks.js
@@ -20,6 +20,7 @@ function getBookmarks() {
}
$.ajax({
+ type: 'POST',
url: OC.filePath('bookmarks', 'ajax', 'updateList.php'),
data: 'tag=' + encodeURIComponent($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting,
success: function(bookmarks){
@@ -70,6 +71,7 @@ function addOrEditBookmark(event) {
}
if (id == 0) {
$.ajax({
+ type: 'POST',
url: OC.filePath('bookmarks', 'ajax', 'addBookmark.php'),
data: 'url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
success: function(response){
@@ -82,6 +84,7 @@ function addOrEditBookmark(event) {
}
else {
$.ajax({
+ type: 'POST',
url: OC.filePath('bookmarks', 'ajax', 'editBookmark.php'),
data: 'id=' + id + '&url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
success: function(){
@@ -99,6 +102,7 @@ function addOrEditBookmark(event) {
function delBookmark(event) {
var record = $(this).parent().parent();
$.ajax({
+ type: 'POST',
url: OC.filePath('bookmarks', 'ajax', 'delBookmark.php'),
data: 'id=' + record.data('id'),
success: function(data){
@@ -177,6 +181,7 @@ function updateOnBottom() {
function recordClick(event) {
$.ajax({
+ type: 'POST',
url: OC.filePath('bookmarks', 'ajax', 'recordClick.php'),
data: 'url=' + encodeURIComponent($(this).attr('href')),
});
diff --git a/apps/bookmarks/js/bookmarksearch.js b/apps/bookmarks/js/bookmarksearch.js
index e7a4fb18393..e8f5363c935 100644
--- a/apps/bookmarks/js/bookmarksearch.js
+++ b/apps/bookmarks/js/bookmarksearch.js
@@ -16,6 +16,7 @@ function recordClick(event) {
var jsFileLocation = $('script[src*=bookmarksearch]').attr('src');
jsFileLocation = jsFileLocation.replace('js/bookmarksearch.js', '');
$.ajax({
+ type: 'POST',
url: jsFileLocation + 'ajax/recordClick.php',
data: 'url=' + encodeURI($(this).attr('href')),
});
diff --git a/apps/calendar/ajax/calendar/edit.form.php b/apps/calendar/ajax/calendar/edit.form.php
index 77366809311..036ed12bb74 100644
--- a/apps/calendar/ajax/calendar/edit.form.php
+++ b/apps/calendar/ajax/calendar/edit.form.php
@@ -11,7 +11,7 @@ OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('calendar');
$calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
-$calendar = OC_Calendar_App::getCalendar($_GET['calendarid']);
+$calendar = OC_Calendar_App::getCalendar($_POST['calendarid']);
$tmpl = new OCP\Template("calendar", "part.editcalendar");
$tmpl->assign('new', false);
$tmpl->assign('calendarcolor_options', $calendarcolor_options);
diff --git a/apps/calendar/ajax/changeview.php b/apps/calendar/ajax/changeview.php
index 2c2d09ccb12..0099fd5ec21 100644
--- a/apps/calendar/ajax/changeview.php
+++ b/apps/calendar/ajax/changeview.php
@@ -7,7 +7,7 @@
*/
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('calendar');
-$view = $_GET['v'];
+$view = $_POST['v'];
switch($view){
case 'agendaWeek':
case 'month';
diff --git a/apps/calendar/ajax/event/edit.form.php b/apps/calendar/ajax/event/edit.form.php
index f2ea84dd205..dbb78edb798 100644
--- a/apps/calendar/ajax/event/edit.form.php
+++ b/apps/calendar/ajax/event/edit.form.php
@@ -13,7 +13,7 @@ if(!OCP\User::isLoggedIn()) {
}
OCP\JSON::checkAppEnabled('calendar');
-$id = $_GET['id'];
+$id = $_POST['id'];
$data = OC_Calendar_App::getEventObject($id, true, true);
if(!$data){
diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php
index 56fa51aaff2..b0c5587633f 100644
--- a/apps/calendar/ajax/events.php
+++ b/apps/calendar/ajax/events.php
@@ -27,7 +27,6 @@ else {
$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']);
$events = OC_Calendar_App::getrequestedEvents($calendar_id, $start, $end);
-
$output = array();
foreach($events as $event){
$output = array_merge($output, OC_Calendar_App::generateEventOutput($event, $start, $end));
diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php
index a3eaed844a1..6fdad12c085 100644
--- a/apps/calendar/ajax/import/import.php
+++ b/apps/calendar/ajax/import/import.php
@@ -16,9 +16,9 @@ $nl="\r\n";
$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true);
global $progresskey;
-$progresskey = 'calendar.import-' . $_GET['progresskey'];
+$progresskey = 'calendar.import-' . $_POST['progresskey'];
-if (isset($_GET['progress']) && $_GET['progress']) {
+if (isset($_POST['progress']) && $_POST['progress']) {
echo OC_Cache::get($progresskey);
die;
}
diff --git a/apps/calendar/ajax/settings/guesstimezone.php b/apps/calendar/ajax/settings/guesstimezone.php
index 13092777b78..f36f3bf061f 100644
--- a/apps/calendar/ajax/settings/guesstimezone.php
+++ b/apps/calendar/ajax/settings/guesstimezone.php
@@ -12,8 +12,8 @@ OCP\JSON::checkAppEnabled('calendar');
$l = OC_L10N::get('calendar');
-$lat = $_GET['lat'];
-$lng = $_GET['long'];
+$lat = $_POST['lat'];
+$lng = $_POST['lng'];
$timezone = OC_Geo::timezone($lat, $lng);
diff --git a/apps/calendar/ajax/share/activation.php b/apps/calendar/ajax/share/activation.php
index 7d6b8fcb16e..bce8693577b 100644
--- a/apps/calendar/ajax/share/activation.php
+++ b/apps/calendar/ajax/share/activation.php
@@ -5,7 +5,7 @@
* later.
* See the COPYING-README file.
*/
-$id = strip_tags($_GET['id']);
-$activation = strip_tags($_GET['activation']);
+$id = strip_tags($_POST['id']);
+$activation = strip_tags($_POST['activation']);
OC_Calendar_Share::set_active(OCP\USER::getUser(), $id, $activation);
OCP\JSON::success();
diff --git a/apps/calendar/ajax/share/changepermission.php b/apps/calendar/ajax/share/changepermission.php
index 2737420c94e..e807c164a23 100644
--- a/apps/calendar/ajax/share/changepermission.php
+++ b/apps/calendar/ajax/share/changepermission.php
@@ -6,9 +6,9 @@
* See the COPYING-README file.
*/
-$id = strip_tags($_GET['id']);
-$idtype = strip_tags($_GET['idtype']);
-$permission = (int) strip_tags($_GET['permission']);
+$id = strip_tags($_POST['id']);
+$idtype = strip_tags($_POST['idtype']);
+$permission = (int) strip_tags($_POST['permission']);
switch($idtype){
case 'calendar':
case 'event':
@@ -25,8 +25,8 @@ if($idtype == 'event' && !OC_Calendar_App::getEventObject($id)){
OCP\JSON::error(array('message'=>'permission denied'));
exit;
}
-$sharewith = $_GET['sharewith'];
-$sharetype = strip_tags($_GET['sharetype']);
+$sharewith = $_POST['sharewith'];
+$sharetype = strip_tags($_POST['sharetype']);
switch($sharetype){
case 'user':
case 'group':
diff --git a/apps/calendar/ajax/share/dropdown.php b/apps/calendar/ajax/share/dropdown.php
index a3b0faca4bf..86cf4ac090e 100644
--- a/apps/calendar/ajax/share/dropdown.php
+++ b/apps/calendar/ajax/share/dropdown.php
@@ -7,7 +7,7 @@
*/
$user = OCP\USER::getUser();
-$calid = $_GET['calid'];
+$calid = $_POST['calid'];
$calendar = OC_Calendar_Calendar::find($calid);
if($calendar['userid'] != $user){
OCP\JSON::error();
diff --git a/apps/calendar/ajax/share/share.php b/apps/calendar/ajax/share/share.php
index 629a7b6b79f..838db619f62 100644
--- a/apps/calendar/ajax/share/share.php
+++ b/apps/calendar/ajax/share/share.php
@@ -6,8 +6,8 @@
* See the COPYING-README file.
*/
-$id = strip_tags($_GET['id']);
-$idtype = strip_tags($_GET['idtype']);
+$id = strip_tags($_POST['id']);
+$idtype = strip_tags($_POST['idtype']);
switch($idtype){
case 'calendar':
case 'event':
@@ -24,8 +24,8 @@ if($idtype == 'event' && !OC_Calendar_App::getEventObject($id)){
OCP\JSON::error(array('message'=>'permission denied'));
exit;
}
-$sharewith = $_GET['sharewith'];
-$sharetype = strip_tags($_GET['sharetype']);
+$sharewith = $_POST['sharewith'];
+$sharetype = strip_tags($_POST['sharetype']);
switch($sharetype){
case 'user':
case 'group':
diff --git a/apps/calendar/ajax/share/unshare.php b/apps/calendar/ajax/share/unshare.php
index fe7c98452d7..1ce04677fb1 100644
--- a/apps/calendar/ajax/share/unshare.php
+++ b/apps/calendar/ajax/share/unshare.php
@@ -6,8 +6,8 @@
* See the COPYING-README file.
*/
-$id = strip_tags($_GET['id']);
-$idtype = strip_tags($_GET['idtype']);
+$id = strip_tags($_POST['id']);
+$idtype = strip_tags($_POST['idtype']);
switch($idtype){
case 'calendar':
case 'event':
@@ -24,8 +24,8 @@ if($idtype == 'event' && !OC_Calendar_App::getEventObject($id)){
OCP\JSON::error(array('message'=>'permission denied'));
exit;
}
-$sharewith = $_GET['sharewith'];
-$sharetype = strip_tags($_GET['sharetype']);
+$sharewith = $_POST['sharewith'];
+$sharetype = strip_tags($_POST['sharetype']);
switch($sharetype){
case 'user':
case 'group':
diff --git a/apps/calendar/appinfo/database.xml b/apps/calendar/appinfo/database.xml
index b065ab3f94a..5a3ad32dc24 100644
--- a/apps/calendar/appinfo/database.xml
+++ b/apps/calendar/appinfo/database.xml
@@ -81,7 +81,7 @@
<type>text</type>
<default></default>
<notnull>false</notnull>
- <length>100</length>
+ <length>255</length>
</field>
<field>
@@ -133,7 +133,7 @@
<type>text</type>
<default></default>
<notnull>false</notnull>
- <length>100</length>
+ <length>255</length>
</field>
<field>
diff --git a/apps/calendar/appinfo/version b/apps/calendar/appinfo/version
index e6adf3fc7bb..267577d47e4 100644
--- a/apps/calendar/appinfo/version
+++ b/apps/calendar/appinfo/version
@@ -1 +1 @@
-0.4 \ No newline at end of file
+0.4.1
diff --git a/apps/calendar/index.php b/apps/calendar/index.php
index cf03a7a3cd3..05a808a5ae0 100644
--- a/apps/calendar/index.php
+++ b/apps/calendar/index.php
@@ -54,9 +54,9 @@ OCP\Util::addscript('contacts','jquery.multi-autocomplete');
OCP\Util::addscript('','oc-vcategories');
OCP\App::setActiveNavigationEntry('calendar_index');
$tmpl = new OCP\Template('calendar', 'calendar', 'user');
-$tmpl->assign('eventSources', $eventSources);
+$tmpl->assign('eventSources', $eventSources,false);
$tmpl->assign('categories', $categories);
if(array_key_exists('showevent', $_GET)){
- $tmpl->assign('showevent', $_GET['showevent']);
+ $tmpl->assign('showevent', $_GET['showevent'], false);
}
$tmpl->printPage();
diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js
index b5411d3fd95..1cbe5c67646 100644
--- a/apps/calendar/js/calendar.js
+++ b/apps/calendar/js/calendar.js
@@ -49,6 +49,7 @@ Calendar={
$( "#event" ).tabs({ selected: 0});
$('#event').dialog({
width : 500,
+ height: 600,
close : function(event, ui) {
$(this).dialog('destroy').remove();
}
@@ -77,7 +78,7 @@ Calendar={
$('#event').dialog('destroy').remove();
}else{
Calendar.UI.loading(true);
- $('#dialog_holder').load(OC.filePath('calendar', 'ajax/event', 'edit.form.php') + '?id=' + id, Calendar.UI.startEventDialog);
+ $('#dialog_holder').load(OC.filePath('calendar', 'ajax/event', 'edit.form.php'), {id: id}, Calendar.UI.startEventDialog);
}
},
submitDeleteEventForm:function(url){
@@ -413,7 +414,7 @@ Calendar={
},
edit:function(object, calendarid){
var tr = $(document.createElement('tr'))
- .load(OC.filePath('calendar', 'ajax/calendar', 'edit.form.php') + "?calendarid="+calendarid,
+ .load(OC.filePath('calendar', 'ajax/calendar', 'edit.form.php'), {calendarid: calendarid},
function(){Calendar.UI.Calendar.colorPicker(this)});
$(object).closest('tr').after(tr).hide();
},
@@ -502,14 +503,14 @@ Calendar={
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});
+ $.post(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();
var element = document.getElementById(userid+'_'+calid);
$('<div class="calendar_share_dropdown"></div>').appendTo(element);
- $.get(OC.filePath('calendar', 'ajax/share', 'dropdown.php') + '?calid=' + calid, function(data){
+ $.post(OC.filePath('calendar', 'ajax/share', 'dropdown.php'), {calid: calid}, function(data){
$('.calendar_share_dropdown').html(data);
$('.calendar_share_dropdown').show('blind');
$('#share_user').chosen();
@@ -519,7 +520,7 @@ Calendar={
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){
+ $.post(OC.filePath('calendar', 'ajax/share', 'share.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(data){
if(sharetype == 'public'){
$('#public_token').val(parent.location.protocol+'//'+location.host+OC.linkTo('', 'public.php')+'?service=calendar&t='+data.message);
$('#public_token').css('display', 'block');
@@ -527,7 +528,7 @@ Calendar={
});
},
unshare:function(id, idtype, sharewith, sharetype){
- $.getJSON(OC.filePath('calendar', 'ajax/share', 'unshare.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(){
+ $.post(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');
@@ -535,7 +536,7 @@ Calendar={
});
},
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)});
+ $.post(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(){
@@ -844,9 +845,9 @@ $(document).ready(function(){
dayNamesShort: dayNamesShort,
allDayText: allDayText,
viewDisplay: function(view) {
- $('#datecontrol_date').html(view.title);
+ $('#datecontrol_date').val($('<p>').html(view.title).text());
if (view.name != defaultView) {
- $.get(OC.filePath('calendar', 'ajax', 'changeview.php') + "?v="+view.name);
+ $.post(OC.filePath('calendar', 'ajax', 'changeview.php'), {v:view.name});
defaultView = view.name;
}
Calendar.UI.setViewActive(view.name);
@@ -883,6 +884,22 @@ $(document).ready(function(){
loading: Calendar.UI.loading,
eventSources: eventSources
});
+ $('#datecontrol_date').datepicker({
+ changeMonth: true,
+ changeYear: true,
+ showButtonPanel: true,
+ beforeShow: function(input, inst) {
+ var calendar_holder = $('#calendar_holder');
+ var date = calendar_holder.fullCalendar('getDate');
+ inst.input.datepicker('setDate', date);
+ inst.input.val(calendar_holder.fullCalendar('getView').title);
+ return inst;
+ },
+ onSelect: function(value, inst) {
+ var date = inst.input.datepicker('getDate');
+ $('#calendar_holder').fullCalendar('gotoDate', date);
+ }
+ });
fillWindow($('#content'));
OCCategories.changed = Calendar.UI.categoriesChanged;
OCCategories.app = 'calendar';
diff --git a/apps/calendar/js/geo.js b/apps/calendar/js/geo.js
index 092d8547469..99290d940e3 100644
--- 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,
+ $.post(OC.filePath('calendar', 'ajax/settings', 'guesstimezone.php'), {lat: position.coords.latitude, lng: 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 838521ec7f5..0fc5018e89c 100644
--- a/apps/calendar/js/loader.js
+++ b/apps/calendar/js/loader.js
@@ -63,7 +63,7 @@ Calendar_Import={
});
},
getimportstatus: function(progresskey){
- $.get(OC.filePath('calendar', 'ajax/import', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
+ $.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {progress:1,progresskey: progresskey}, function(percent){
$('#progressbar').progressbar('option', 'value', parseInt(percent));
if(percent < 100){
window.setTimeout('Calendar_Import.getimportstatus(\'' + progresskey + '\')', 500);
diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php
index 2cd28c0f782..e04f2ed0cdf 100644
--- a/apps/calendar/lib/app.php
+++ b/apps/calendar/lib/app.php
@@ -331,26 +331,29 @@ class OC_Calendar_App{
*/
public static function getrequestedEvents($calendarid, $start, $end){
$events = array();
- if($calendarid == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){
+ if($calendarid == 'shared_rw' || $calendarid == '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);
+ foreach($calendarevents as $event){
+ $event['summary'] .= ' (' . self::$l10n->t('by') . ' ' . OC_Calendar_Object::getowner($event['id']) . ')';
+ }
$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']);
+ $event['summary'] .= ' (' . self::$l10n->t('by') . ' ' . OC_Calendar_Object::getowner($event['id']) . ')';
$events[] = $event;
}
}else{
- $calendar_id = $_GET['calendar_id'];
- if (is_numeric($calendar_id)) {
- $calendar = self::getCalendar($calendar_id);
+ if (is_numeric($calendarid)) {
+ $calendar = self::getCalendar($calendarid);
OCP\Response::enableCaching(0);
OCP\Response::setETagHeader($calendar['ctag']);
- $events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end);
+ $events = OC_Calendar_Object::allInPeriod($calendarid, $start, $end);
} else {
- OCP\Util::emitHook('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events));
+ OCP\Util::emitHook('OC_Calendar', 'getEvents', array('calendar_id' => $calendarid, 'events' => &$events));
}
}
return $events;
@@ -377,8 +380,8 @@ class OC_Calendar_App{
$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):'',
+ 'title' => ($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: self::$l10n->t('unnamed'),
+ 'description' => isset($vevent->DESCRIPTION)?$vevent->DESCRIPTION->value:'',
'lastmodified'=>$lastmodified);
$dtstart = $vevent->DTSTART;
diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php
index cc80a0bb708..9e4806227b0 100644
--- a/apps/calendar/lib/object.php
+++ b/apps/calendar/lib/object.php
@@ -665,6 +665,9 @@ class OC_Calendar_Object{
$byday .= ',' . $weekofmonth . $days[$day];
}
}
+ if($byday == ''){
+ $byday = 'MO,TU,WE,TH,FR,SA,SU';
+ }
$rrule .= ';BYDAY=' . $byday;
}
break;
diff --git a/apps/calendar/templates/calendar.php b/apps/calendar/templates/calendar.php
index 832194f0fe1..2246a0178e3 100644
--- a/apps/calendar/templates/calendar.php
+++ b/apps/calendar/templates/calendar.php
@@ -34,29 +34,21 @@
});
</script>
<div id="controls">
- <div>
- <form>
- <div id="view">
- <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 OCP\Util::imagePath('core', 'loading.gif'); ?>" />
- </div>
- </form>
- <form>
- <div id="choosecalendar">
- <input type="button" id="today_input" value="<?php echo $l->t("Today");?>"/>
- <input type="button" id="choosecalendar_input" value="<?php echo $l->t("Calendars");?>" onclick="Calendar.UI.Calendar.overview();" />
- </div>
- </form>
- <form>
- <div id="datecontrol">
- <input type="button" value="&nbsp;&lt;&nbsp;" id="datecontrol_left"/>
- <span class="button" id="datecontrol_date"></span>
- <input type="button" value="&nbsp;&gt;&nbsp;" id="datecontrol_right"/>
- </div>
- </form>
- </div>
+ <form id="view">
+ <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 OCP\Util::imagePath('core', 'loading.gif'); ?>" />
+ </form>
+ <form id="choosecalendar">
+ <input type="button" id="today_input" value="<?php echo $l->t("Today");?>"/>
+ <input type="button" id="choosecalendar_input" value="<?php echo $l->t("Calendars");?>" onclick="Calendar.UI.Calendar.overview();" />
+ </form>
+ <form id="datecontrol">
+ <input type="button" value="&nbsp;&lt;&nbsp;" id="datecontrol_left"/>
+ <input type="button" value="" id="datecontrol_date"/>
+ <input type="button" value="&nbsp;&gt;&nbsp;" id="datecontrol_right"/>
+ </form>
</div>
<div id="notification" style="display:none;"></div>
<div id="calendar_holder">
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.php b/apps/calendar/templates/part.choosecalendar.rowfields.php
index bad268897bf..965523f847a 100644
--- a/apps/calendar/templates/part.choosecalendar.rowfields.php
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.php
@@ -1,6 +1,6 @@
<?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 id="' . OCP\USER::getUser() . '_' . $_['calendar']['id'] . '"><label for="active_' . $_['calendar']['id'] . '">' . htmlspecialchars($_['calendar']['displayname']) . '</label></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']) ? OCP\Util::imagePath('core', 'actions/share.svg') : OCP\Util::imagePath('core', '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="'.OCP\Util::imagePath('core', 'actions/public.svg').'"></a></td>';
echo '<td width="20px"><a href="?app=calendar&getfile=export.php?calid=' . $_['calendar']['id'] . '" title="' . $l->t('Download') . '" class="action"><img class="svg action" src="'.OCP\Util::imagePath('core', 'actions/download.svg').'"></a></td>';
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.shared.php b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
index 6a212858a21..a23266da0c3 100644
--- a/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
@@ -1,4 +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'] . '">' . htmlspecialchars($_['share']['calendar']['displayname']) . '</label></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.eventform.php b/apps/calendar/templates/part.eventform.php
index 2d86ce4d318..95eecf26223 100644
--- a/apps/calendar/templates/part.eventform.php
+++ b/apps/calendar/templates/part.eventform.php
@@ -18,7 +18,7 @@ echo 'Calendar.UI.Share.idtype = "event";' . "\n" . 'Calendar.UI.Share.currentid
<tr>
<th width="75px"><?php echo $l->t("Title");?>:</th>
<td>
- <input type="text" style="width:350px;" size="100" placeholder="<?php echo $l->t("Title of the Event");?>" value="<?php echo isset($_['title']) ? htmlspecialchars($_['title']) : '' ?>" maxlength="100" name="title"/>
+ <input type="text" style="width:350px;" size="100" placeholder="<?php echo $l->t("Title of the Event");?>" value="<?php echo isset($_['title']) ? $_['title'] : '' ?>" maxlength="100" name="title"/>
</td>
</tr>
</table>
@@ -26,7 +26,7 @@ echo 'Calendar.UI.Share.idtype = "event";' . "\n" . 'Calendar.UI.Share.currentid
<tr>
<th width="75px"><?php echo $l->t("Category");?>:</th>
<td>
- <input id="category" name="categories" type="text" placeholder="<?php echo $l->t('Separate categories with commas'); ?>" value="<?php echo isset($_['categories']) ? htmlspecialchars($_['categories']) : '' ?>">
+ <input id="category" name="categories" type="text" placeholder="<?php echo $l->t('Separate categories with commas'); ?>" value="<?php echo isset($_['categories']) ? $_['categories'] : '' ?>">
<a class="action edit" onclick="$(this).tipsy('hide');OCCategories.edit();" title="<?php echo $l->t('Edit categories'); ?>"><img alt="<?php echo $l->t('Edit categories'); ?>" src="<?php echo OCP\image_path('core','actions/rename.svg')?>" class="svg action" style="width: 16px; height: 16px;"></a>
</td>
<?php if(count($_['calendar_options']) > 1) { ?>
@@ -80,7 +80,7 @@ echo 'Calendar.UI.Share.idtype = "event";' . "\n" . 'Calendar.UI.Share.currentid
<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" />
+ <input type="text" style="width:350px;" size="100" placeholder="<?php echo $l->t("Location of the Event");?>" value="<?php echo isset($_['location']) ? $_['location'] : '' ?>" maxlength="100" name="location" />
</td>
</tr>
</table>
@@ -88,7 +88,7 @@ echo 'Calendar.UI.Share.idtype = "event";' . "\n" . 'Calendar.UI.Share.currentid
<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>
+ <textarea style="width:350px;height: 150px;" placeholder="<?php echo $l->t("Description of the Event");?>" name="description"><?php echo isset($_['description']) ? $_['description'] : '' ?></textarea>
</td>
</tr>
</table>
diff --git a/apps/calendar/templates/part.import.php b/apps/calendar/templates/part.import.php
index 39cda29c20d..70ff9612157 100644
--- a/apps/calendar/templates/part.import.php
+++ b/apps/calendar/templates/part.import.php
@@ -8,6 +8,9 @@
<?php
$calendar_options = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
$calendar_options[] = array('id'=>'newcal', 'displayname'=>$l->t('create a new calendar'));
+for($i = 0;$i<count($calendar_options);$i++){
+ $calendar_options[$i]['displayname'] = $calendar_options[$i]['displayname'];
+}
echo OCP\html_select_options($calendar_options, $calendar_options[0]['id'], array('value'=>'id', 'label'=>'displayname'));
?>
</select>
diff --git a/apps/calendar/templates/part.showevent.php b/apps/calendar/templates/part.showevent.php
index 3646baf5bb7..59684d831e5 100644
--- a/apps/calendar/templates/part.showevent.php
+++ b/apps/calendar/templates/part.showevent.php
@@ -10,7 +10,7 @@
<tr>
<th width="75px"><?php echo $l->t("Title");?>:</th>
<td>
- <?php echo isset($_['title']) ? htmlspecialchars($_['title']) : '' ?>
+ <?php echo isset($_['title']) ? $_['title'] : '' ?>
</td>
</tr>
</table>
@@ -19,26 +19,23 @@
<th width="75px"><?php echo $l->t("Category");?>:</th>
<td>
<?php
- if(count($_['categories']) == 0){
+ if(count($_['categories']) == 0 || $_['categories'] == ''){
echo $l->t('No categories selected');
}else{
- echo '<select id="category" name="categories[]" multiple="multiple" title="' . $l->t("Select category") . '">';
- echo OCP\html_select_options($_['categories'], $_['categories'], array('combine'=>true));
- echo '</select>';
+ echo '<ul>';
+ foreach($_['categories'] as $categorie){
+ echo '<li>' . $categorie . '</li>';
+ }
+ echo '</ul>';
}
?>
</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>
+ <?php
+ $calendar = OC_Calendar_App::getCalendar($_['calendar'], false, false);
+ echo $calendar['displayname'] . ' ' . $l->t('of') . ' ' . $calendar['userid'];
+ ?>
</td>
<th width="75px">&nbsp;</th>
<td>
@@ -79,7 +76,7 @@
<tr>
<th width="85px"><?php echo $l->t("Location");?>:</th>
<td>
- <?php echo isset($_['location']) ? htmlspecialchars($_['location']) : '' ?>
+ <?php echo isset($_['location']) ? $_['location'] : '' ?>
</td>
</tr>
</table>
@@ -87,7 +84,7 @@
<tr>
<th width="85px" style="vertical-align: top;"><?php echo $l->t("Description");?>:</th>
<td>
- <?php echo isset($_['description']) ? htmlspecialchars($_['description']) : '' ?></textarea>
+ <?php echo isset($_['description']) ? $_['description'] : '' ?></textarea>
</tr>
</table>
</div>
diff --git a/apps/contacts/ajax/activation.php b/apps/contacts/ajax/activation.php
index 388a3b5438c..74cb738ab8f 100644
--- a/apps/contacts/ajax/activation.php
+++ b/apps/contacts/ajax/activation.php
@@ -10,6 +10,7 @@
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
$bookid = $_POST['bookid'];
$book = OC_Contacts_App::getAddressbook($bookid);// is owner access check
diff --git a/apps/contacts/ajax/addcontact.php b/apps/contacts/ajax/addcontact.php
index af9b2bbcc0e..e45072c9542 100644
--- a/apps/contacts/ajax/addcontact.php
+++ b/apps/contacts/ajax/addcontact.php
@@ -23,6 +23,7 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
$aid = isset($_POST['aid'])?$_POST['aid']:null;
if(!$aid) {
diff --git a/apps/contacts/ajax/addproperty.php b/apps/contacts/ajax/addproperty.php
index 2f932d752a7..f888b94e386 100644
--- a/apps/contacts/ajax/addproperty.php
+++ b/apps/contacts/ajax/addproperty.php
@@ -23,6 +23,13 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
+
+function bailOut($msg) {
+ OCP\JSON::error(array('data' => array('message' => $msg)));
+ OCP\Util::writeLog('contacts','ajax/addproperty.php: '.$msg, OCP\Util::DEBUG);
+ exit();
+}
$id = isset($_POST['id'])?$_POST['id']:null;
$name = isset($_POST['name'])?$_POST['name']:null;
@@ -31,11 +38,21 @@ $parameters = isset($_POST['parameters'])?$_POST['parameters']:array();
$vcard = OC_Contacts_App::getContactVCard($id);
+if(!$name) {
+ bailOut(OC_Contacts_App::$l10n->t('element name is not set.'));
+}
+if(!$id) {
+ bailOut(OC_Contacts_App::$l10n->t('id is not set.'));
+}
+
+if(!$vcard) {
+ bailOut(OC_Contacts_App::$l10n->t('Could not parse contact: ').$id);
+}
+
if(!is_array($value)){
$value = trim($value);
if(!$value && in_array($name, array('TEL', 'EMAIL', 'ORG', 'BDAY', 'URL', 'NICKNAME', 'NOTE'))) {
- OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot add empty property.'))));
- exit();
+ bailOut(OC_Contacts_App::$l10n->t('Cannot add empty property.'));
}
} elseif($name === 'ADR') { // only add if non-empty elements.
$empty = true;
@@ -46,8 +63,7 @@ if(!is_array($value)){
}
}
if($empty) {
- 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();
+ bailOut(OC_Contacts_App::$l10n->t('At least one of the address fields has to be filled out.'));
}
}
@@ -56,9 +72,7 @@ $current = $vcard->select($name);
foreach($current as $item) {
$tmpvalue = (is_array($value)?implode(';', $value):$value);
if($tmpvalue == $item->value) {
- 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();
+ bailOut(OC_Contacts_App::$l10n->t('Trying to add duplicate property: '.$name.': '.$tmpvalue));
}
}
@@ -69,6 +83,7 @@ if(is_array($value)) {
$value = strip_tags($value);
}
+/* preprocessing value */
switch($name) {
case 'BDAY':
$date = New DateTime($value);
@@ -81,6 +96,8 @@ switch($name) {
case 'N':
case 'ORG':
case 'NOTE':
+ $value = str_replace('\n', ' \\n', $value);
+ break;
case 'NICKNAME':
// TODO: Escape commas and semicolons.
break;
@@ -92,8 +109,14 @@ switch($name) {
break;
}
-
-$property = $vcard->addProperty($name, $value); //, $parameters);
+switch($name) {
+ case 'NOTE':
+ $vcard->setString('NOTE', $value);
+ break;
+ default:
+ $property = $vcard->addProperty($name, $value); //, $parameters);
+ break;
+}
$line = count($vcard->children) - 1;
@@ -114,9 +137,7 @@ foreach ($parameters as $key=>$element) {
$checksum = md5($vcard->children[$line]->serialize());
if(!OC_Contacts_VCard::edit($id,$vcard)) {
- 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();
+ bailOut(OC_Contacts_App::$l10n->t('Error adding contact property: '.$name));
}
OCP\JSON::success(array('data' => array( 'checksum' => $checksum )));
diff --git a/apps/contacts/ajax/createaddressbook.php b/apps/contacts/ajax/createaddressbook.php
index af7c19eef51..616766bb1a0 100644
--- a/apps/contacts/ajax/createaddressbook.php
+++ b/apps/contacts/ajax/createaddressbook.php
@@ -11,6 +11,7 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
$userid = OCP\USER::getUser();
$name = trim(strip_tags($_POST['name']));
diff --git a/apps/contacts/ajax/cropphoto.php b/apps/contacts/ajax/cropphoto.php
index caba7c8c4ef..eb9f1fcdb5d 100644
--- a/apps/contacts/ajax/cropphoto.php
+++ b/apps/contacts/ajax/cropphoto.php
@@ -25,10 +25,12 @@ OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
$tmpkey = $_GET['tmpkey'];
+$requesttoken = $_GET['requesttoken'];
$id = $_GET['id'];
$tmpl = new OCP\Template("contacts", "part.cropphoto");
$tmpl->assign('tmpkey', $tmpkey);
$tmpl->assign('id', $id);
+$tmpl->assign('requesttoken', $requesttoken);
$page = $tmpl->fetchPage();
OCP\JSON::success(array('data' => array( 'page' => $page )));
diff --git a/apps/contacts/ajax/deletebook.php b/apps/contacts/ajax/deletebook.php
index fe582daa00f..1b86ecf223e 100644
--- a/apps/contacts/ajax/deletebook.php
+++ b/apps/contacts/ajax/deletebook.php
@@ -23,6 +23,7 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
//$id = $_GET['id'];
$id = $_POST['id'];
diff --git a/apps/contacts/ajax/deletecard.php b/apps/contacts/ajax/deletecard.php
index 6414fda93cb..2a6bd277d19 100644
--- a/apps/contacts/ajax/deletecard.php
+++ b/apps/contacts/ajax/deletecard.php
@@ -28,8 +28,19 @@ function bailOut($msg) {
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
-$id = isset($_GET['id'])?$_GET['id']:null;
+// foreach($_SERVER as $key=>$value) {
+// OCP\Util::writeLog('contacts','ajax/saveproperty.php: _SERVER: '.$key.'=>'.$value, OCP\Util::DEBUG);
+// }
+foreach($_POST as $key=>$value) {
+ OCP\Util::writeLog('contacts','ajax/saveproperty.php: _POST: '.$key.'=>'.print_r($value, true), OCP\Util::DEBUG);
+}
+foreach($_GET as $key=>$value) {
+ OCP\Util::writeLog('contacts','ajax/saveproperty.php: _GET: '.$key.'=>'.print_r($value, true), OCP\Util::DEBUG);
+}
+
+$id = isset($_POST['id'])?$_POST['id']:null;
if(!$id) {
bailOut(OC_Contacts_App::$l10n->t('id is not set.'));
}
diff --git a/apps/contacts/ajax/deleteproperty.php b/apps/contacts/ajax/deleteproperty.php
index b0746d18a79..55f7e323083 100644
--- a/apps/contacts/ajax/deleteproperty.php
+++ b/apps/contacts/ajax/deleteproperty.php
@@ -23,9 +23,10 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
-$id = $_GET['id'];
-$checksum = $_GET['checksum'];
+$id = $_POST['id'];
+$checksum = $_POST['checksum'];
$vcard = OC_Contacts_App::getContactVCard( $id );
$line = OC_Contacts_App::getPropertyLineByChecksum($vcard, $checksum);
diff --git a/apps/contacts/ajax/savecrop.php b/apps/contacts/ajax/savecrop.php
index b3aab6a8810..6faf6a173d5 100644
--- a/apps/contacts/ajax/savecrop.php
+++ b/apps/contacts/ajax/savecrop.php
@@ -22,6 +22,7 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
// Firefox and Konqueror tries to download application/json for me. --Arthur
OCP\JSON::setContentTypeHeader('text/plain');
diff --git a/apps/contacts/ajax/saveproperty.php b/apps/contacts/ajax/saveproperty.php
index d8400734710..6ee9ec90b56 100644
--- a/apps/contacts/ajax/saveproperty.php
+++ b/apps/contacts/ajax/saveproperty.php
@@ -20,10 +20,6 @@
*
*/
-// 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/saveproperty.php: '.$msg, OCP\Util::DEBUG);
@@ -33,6 +29,11 @@ function debug($msg) {
OCP\Util::writeLog('contacts','ajax/saveproperty.php: '.$msg, OCP\Util::DEBUG);
}
+// Check if we are a user
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
+
$id = isset($_POST['id'])?$_POST['id']:null;
$name = isset($_POST['name'])?$_POST['name']:null;
$value = isset($_POST['value'])?$_POST['value']:null;
diff --git a/apps/contacts/ajax/uploadphoto.php b/apps/contacts/ajax/uploadphoto.php
index 09c4e55d4a9..889de6a1f8b 100644
--- a/apps/contacts/ajax/uploadphoto.php
+++ b/apps/contacts/ajax/uploadphoto.php
@@ -23,6 +23,8 @@
// Check if we are a user
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('contacts');
+OCP\JSON::callCheck();
+
// Firefox and Konqueror tries to download application/json for me. --Arthur
OCP\JSON::setContentTypeHeader('text/plain');
function bailOut($msg) {
@@ -59,7 +61,7 @@ if ($fn) {
bailOut(OC_Contacts_App::$l10n->t('Couldn\'t save temporary image: ').$tmpkey);
}
} else {
- bailOut(OC_Contacts_App::$l10n->t('Couldn\'t load temporary image: ').$tmpkey.$data);
+ bailOut(OC_Contacts_App::$l10n->t('Couldn\'t load temporary image: ').$tmpkey);
}
}
diff --git a/apps/contacts/import.php b/apps/contacts/import.php
index 0ee35f9fd81..c95fd970fe1 100644
--- a/apps/contacts/import.php
+++ b/apps/contacts/import.php
@@ -15,7 +15,7 @@ session_write_close();
$nl = "\n";
global $progresskey;
-$progresskey = 'contacts.import-' . $_GET['progresskey'];
+$progresskey = 'contacts.import-' . (isset($_GET['progresskey'])?$_GET['progresskey']:'');
if (isset($_GET['progress']) && $_GET['progress']) {
echo OC_Cache::get($progresskey);
diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js
index 35d4a4a216d..a1b9976006d 100644
--- a/apps/contacts/js/contacts.js
+++ b/apps/contacts/js/contacts.js
@@ -368,7 +368,7 @@ 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(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':Contacts.UI.Card.id},function(jsondata){
+ $.post(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+'"]');
@@ -622,7 +622,7 @@ Contacts={
q = q + '&id=' + this.id + '&name=' + name;
if(checksum != undefined && checksum != '') { // save
q = q + '&checksum=' + checksum;
- //console.log('Saving: ' + q);
+ console.log('Saving: ' + q);
$(obj).attr('disabled', 'disabled');
$.post(OC.filePath('contacts', 'ajax', 'saveproperty.php'),q,function(jsondata){
if(jsondata.status == 'success'){
@@ -640,7 +640,7 @@ Contacts={
}
},'json');
} else { // add
- //console.log('Adding: ' + q);
+ console.log('Adding: ' + q);
$(obj).attr('disabled', 'disabled');
$.post(OC.filePath('contacts', 'ajax', 'addproperty.php'),q,function(jsondata){
if(jsondata.status == 'success'){
@@ -707,7 +707,7 @@ Contacts={
Contacts.UI.loading(obj, true);
var checksum = Contacts.UI.checksumFor(obj);
if(checksum) {
- $.getJSON(OC.filePath('contacts', 'ajax', 'deleteproperty.php'),{'id': this.id, 'checksum': checksum },function(jsondata){
+ $.post(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();
@@ -839,22 +839,22 @@ Contacts={
$('#addressdisplay dl').last().data('checksum', this.data.ADR[adr]['checksum']);
var adrarray = this.data.ADR[adr]['value'];
var adrtxt = '';
- if(adrarray[0].length > 0) {
+ if(adrarray[0] && adrarray[0].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[0].strip_tags() + '</li>';
}
- if(adrarray[1].length > 0) {
+ if(adrarray[1] && adrarray[1].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[1].strip_tags() + '</li>';
}
- if(adrarray[2].length > 0) {
+ if(adrarray[2] && adrarray[2].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[2].strip_tags() + '</li>';
}
- if(adrarray[3].length > 0 || adrarray[5].length > 0) {
+ if((adrarray[3] && adrarray[5]) && adrarray[3].length > 0 || adrarray[5].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[5].strip_tags() + ' ' + adrarray[3].strip_tags() + '</li>';
}
- if(adrarray[4].length > 0) {
+ if(adrarray[4] && adrarray[4].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[4].strip_tags() + '</li>';
}
- if(adrarray[6].length > 0) {
+ if(adrarray[6] && adrarray[6].length > 0) {
adrtxt = adrtxt + '<li>' + adrarray[6].strip_tags() + '</li>';
}
$('#addressdisplay dl').last().find('.addresslist').html(adrtxt);
@@ -1152,7 +1152,7 @@ Contacts={
},
editPhoto:function(id, tmpkey){
//alert('editPhoto: ' + tmpkey);
- $.getJSON(OC.filePath('contacts', 'ajax', 'cropphoto.php'),{'tmpkey':tmpkey,'id':this.id},function(jsondata){
+ $.getJSON(OC.filePath('contacts', 'ajax', 'cropphoto.php'),{'tmpkey':tmpkey,'id':this.id, 'requesttoken':requesttoken},function(jsondata){
if(jsondata.status == 'success'){
//alert(jsondata.data.page);
$('#edit_photo_dialog_img').html(jsondata.data.page);
@@ -1645,7 +1645,7 @@ $(document).ready(function(){
//}
}
};
- xhr.open('POST', OC.filePath('contacts', '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+'&requesttoken='+requesttoken+'&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));
diff --git a/apps/contacts/js/loader.js b/apps/contacts/js/loader.js
index 961e0f425c9..577ad103064 100644
--- a/apps/contacts/js/loader.js
+++ b/apps/contacts/js/loader.js
@@ -42,20 +42,20 @@ Contacts_Import={
}
$('#newaddressbook').attr('readonly', 'readonly');
$('#contacts').attr('disabled', 'disabled');
- var progresskey = $('#progresskey').val();
- $.post(OC.filePath('contacts', '', 'import.php') + '?progresskey='+progresskey, {method: String (method), addressbookname: String (addressbookname), path: String (path), file: String (filename), id: String (addressbookid)}, function(jsondata){
+ var progresskey = $('#progresskey').val();
+ $.post(OC.filePath('contacts', '', 'import.php') + '?progresskey='+progresskey, {method: String (method), addressbookname: String (addressbookname), path: String (path), file: String (filename), id: String (addressbookid)}, function(jsondata){
if(jsondata.status == 'success'){
$('#progressbar').progressbar('option', 'value', 100);
$('#import_done').find('p').html(t('contacts', 'Result: ') + jsondata.data.imported + t('contacts', ' imported, ') + jsondata.data.failed + t('contacts', ' failed.'));
} else {
- $('#import_done').find('p').html(jsondata.data.message);
+ $('#import_done').find('p').html(jsondata.message);
}
$('#import_done').show().find('p').addClass('bold');
$('#progressbar').fadeOut('slow');
});
$('#form_container').css('display', 'none');
$('#progressbar_container').css('display', 'block');
- window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
+ window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
});
$('#contacts').change(function(){
if($('#contacts option:selected').val() == 'newaddressbook'){
@@ -65,11 +65,11 @@ Contacts_Import={
}
});
},
- getimportstatus: function(progresskey){
- $.get(OC.filePath('contacts', '', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
+ getimportstatus: function(progresskey){
+ $.get(OC.filePath('contacts', '', 'import.php') + '?progress=1&progresskey=' + progresskey, function(percent){
$('#progressbar').progressbar('option', 'value', parseInt(percent));
if(percent < 100){
- window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
+ window.setTimeout('Contacts_Import.getimportstatus(\'' + progresskey + '\')', 500);
}else{
$('#import_done').css('display', 'block');
}
diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php
index a8ad695f620..71a874d783b 100644
--- a/apps/contacts/lib/vcard.php
+++ b/apps/contacts/lib/vcard.php
@@ -188,6 +188,7 @@ class OC_Contacts_VCard{
if($upgrade && in_array($property->name, $stringprops)) {
self::decodeProperty($property);
}
+ $property->value = str_replace("\r\n", "\n", iconv(mb_detect_encoding($property->value, 'UTF-8, ISO-8859-1'), 'utf-8', $property->value));
if(in_array($property->name, $stringprops)) {
$property->value = strip_tags($property->value);
}
@@ -373,6 +374,10 @@ class OC_Contacts_VCard{
public static function editFromDAVData($aid,$uri,$data){
$oldcard = self::findWhereDAVDataIs($aid,$uri);
$card = OC_VObject::parse($data);
+ if(!$card) {
+ OCP\Util::writeLog('contacts','OC_Contacts_VCard::editFromDAVData. Unable to parse VCARD, uri: '.$uri,OCP\Util::ERROR);
+ return false;
+ }
return self::edit($oldcard['id'], $card);
}
diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php
index fee5be08004..ca682baaf80 100644
--- a/apps/contacts/templates/part.contact.php
+++ b/apps/contacts/templates/part.contact.php
@@ -3,6 +3,7 @@ $id = isset($_['id']) ? $_['id'] : '';
?>
<div id="card">
<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">
+ <input type="hidden" name="requesttoken" value="<?php echo $_['requesttoken'] ?>">
<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']; ?>)">
@@ -23,6 +24,7 @@ $id = isset($_['id']) ? $_['id'] : '';
<div id="contact_identity" class="contactsection">
<form method="post">
<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
+ <input type="hidden" name="requesttoken" value="<?php echo $_['requesttoken'] ?>">
<fieldset id="ident" class="contactpart">
<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">
@@ -34,7 +36,7 @@ $id = isset($_['id']) ? $_['id'] : '';
<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="url_label" data-element="URL"><label for="nickname"><?php echo $l->t('Web site'); ?></label></dt>
+ <dt class="hidden" id="url_label" data-element="URL"><label for="url"><?php echo $l->t('Web site'); ?></label></dt>
<dd class="propertycontainer hidden" id="url_value" data-element="URL"><input id="url" required="required" name="value[URL]" type="text" class="contacts_property big" name="value" value="" placeholder="<?php echo $l->t('http://www.somesite.com'); ?>" /><a role="button" class="action globe" title="<?php echo $l->t('Go to web site'); ?>"><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>
diff --git a/apps/contacts/templates/part.contacts.php b/apps/contacts/templates/part.contacts.php
index 57517505405..00a61f72fdd 100644
--- a/apps/contacts/templates/part.contacts.php
+++ b/apps/contacts/templates/part.contacts.php
@@ -8,5 +8,5 @@
}
}
?>
- <li role="button" book-id="<?php echo $contact['addressbookid']; ?>" data-id="<?php echo $contact['id']; ?>"><a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo htmlspecialchars($display); ?></a></li>
+ <li role="button" book-id="<?php echo $contact['addressbookid']; ?>" data-id="<?php echo $contact['id']; ?>"><a href="index.php?id=<?php echo $contact['id']; ?>"><?php echo $display; ?></a></li>
<?php endforeach; ?>
diff --git a/apps/contacts/templates/part.cropphoto.php b/apps/contacts/templates/part.cropphoto.php
index d7f0efc57d7..1079afc808a 100644
--- a/apps/contacts/templates/part.cropphoto.php
+++ b/apps/contacts/templates/part.cropphoto.php
@@ -1,6 +1,7 @@
<?php
$id = $_['id'];
$tmpkey = $_['tmpkey'];
+$requesttoken = $_['requesttoken'];
OCP\Util::writeLog('contacts','templates/part.cropphoto.php: tmpkey: '.$tmpkey, OCP\Util::DEBUG);
?>
<script language="Javascript">
@@ -48,6 +49,7 @@ OCP\Util::writeLog('contacts','templates/part.cropphoto.php: tmpkey: '.$tmpkey,
action="<?php echo OCP\Util::linkToAbsolute('contacts', 'ajax/savecrop.php'); ?>">
<input type="hidden" id="id" name="id" value="<?php echo $id; ?>" />
+ <input type="hidden" name="requesttoken" value="<?php echo $requesttoken; ?>">
<input type="hidden" id="tmpkey" name="tmpkey" value="<?php echo $tmpkey; ?>" />
<fieldset id="coords">
<input type="hidden" id="x1" name="x1" value="" />
diff --git a/apps/contacts/templates/part.importaddressbook.php b/apps/contacts/templates/part.importaddressbook.php
index 0e2956ddaf4..01f8dd77d0a 100644
--- a/apps/contacts/templates/part.importaddressbook.php
+++ b/apps/contacts/templates/part.importaddressbook.php
@@ -7,10 +7,6 @@
*/
?>
<td id="importaddressbook_dialog" colspan="6">
-<?php
-if(OCP\App::isEnabled('files_encryption')) {
- echo '<strong>'.$l->t('Currently this import function doesn\'t work while encryption is enabled.<br />Please upload your VCF file with the file manager and click on it to import.').'</strong>';
-} else { ?>
<table>
<tr>
<th><?php echo $l->t('Select address book to import to:') ?></th>
@@ -33,7 +29,6 @@ if(OCP\App::isEnabled('files_encryption')) {
<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>
-<?php } ?>
</td>
<script type="text/javascript">
$(document).ready(function(){
diff --git a/apps/external/ajax/setsites.php b/apps/external/ajax/setsites.php
index c758a3508c5..772863974ae 100644
--- a/apps/external/ajax/setsites.php
+++ b/apps/external/ajax/setsites.php
@@ -12,7 +12,7 @@ OCP\User::checkAdminUser();
$sites = array();
for ($i = 0; $i < sizeof($_POST['site_name']); $i++) {
if (!empty($_POST['site_name'][$i]) && !empty($_POST['site_url'][$i])) {
- array_push($sites, array($_POST['site_name'][$i], $_POST['site_url'][$i]));
+ array_push($sites, array(strip_tags($_POST['site_name'][$i]), strip_tags($_POST['site_url'][$i])));
}
}
diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php
index ceb8d158580..f0600a179d0 100644
--- a/apps/files/ajax/list.php
+++ b/apps/files/ajax/list.php
@@ -38,7 +38,7 @@ foreach( OC_Files::getdirectorycontent( $dir ) as $i ){
}
$list = new OCP\Template( "files", "part.list", "" );
-$list->assign( "files", $files );
+$list->assign( "files", $files, false );
$data = array('files' => $list->fetchPage());
OCP\JSON::success(array('data' => $data));
diff --git a/apps/files/index.php b/apps/files/index.php
index 60a3836cb59..ed36c5edab0 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -73,12 +73,12 @@ foreach( explode( '/', $dir ) as $i ){
// make breadcrumb und filelist markup
$list = new OCP\Template( 'files', 'part.list', '' );
-$list->assign( 'files', $files );
-$list->assign( 'baseURL', OCP\Util::linkTo('files', 'index.php').'&dir=');
-$list->assign( 'downloadURL', OCP\Util::linkTo('files', 'download.php').'?file=');
+$list->assign( 'files', $files, false );
+$list->assign( 'baseURL', OCP\Util::linkTo('files', 'index.php').'&dir=', false);
+$list->assign( 'downloadURL', OCP\Util::linkTo('files', 'download.php').'?file=', false);
$breadcrumbNav = new OCP\Template( 'files', 'part.breadcrumb', '' );
-$breadcrumbNav->assign( 'breadcrumb', $breadcrumb );
-$breadcrumbNav->assign( 'baseURL', OCP\Util::linkTo('files', 'index.php').'&dir=');
+$breadcrumbNav->assign( 'breadcrumb', $breadcrumb, false );
+$breadcrumbNav->assign( 'baseURL', OCP\Util::linkTo('files', 'index.php').'&dir=', false);
$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
@@ -89,8 +89,8 @@ $freeSpace=max($freeSpace,0);
$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
$tmpl = new OCP\Template( 'files', 'index', 'user' );
-$tmpl->assign( 'fileList', $list->fetchPage() );
-$tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage() );
+$tmpl->assign( 'fileList', $list->fetchPage(), false );
+$tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage(), false );
$tmpl->assign( 'dir', $dir);
$tmpl->assign( 'readonly', !OC_Filesystem::is_writable($dir.'/'));
$tmpl->assign( 'files', $files );
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 0c672cd6708..deec640bc12 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -71,7 +71,7 @@ FileActions={
}
var html='<a href="#" class="action" style="display:none">';
if(img) { html+='<img src="'+img+'"/> '; }
- html += name+'</a>';
+ html += t('files', name) +'</a>';
var element=$(html);
element.data('action',name);
element.click(function(event){
@@ -91,7 +91,11 @@ FileActions={
if(img.call){
img=img(file);
}
- var html='<a href="#" original-title="Delete" class="action delete" style="display:none" />';
+ if ($('#dir').val().indexOf('Shared') != -1) {
+ var html='<a href="#" original-title="' + t('files', 'Unshare') + '" class="action delete" style="display:none" />';
+ } else {
+ var html='<a href="#" original-title="' + t('files', 'Delete') + '" class="action delete" style="display:none" />';
+ }
var element=$(html);
if(img){
element.append($('<img src="'+img+'"/>'));
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index a079deb9539..3ba473e023d 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -452,7 +452,7 @@ $(document).ready(function() {
input.focus();
input.change(function(){
var name=$(this).val();
- if(name.indexOf('/')!=-1){
+ if(type != 'web' && name.indexOf('/')!=-1){
$('#notification').text(t('files','Invalid name, \'/\' is not allowed.'));
$('#notification').fadeIn();
return;
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index 3bd5a1ceef4..44000171a17 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -15,7 +15,7 @@
<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 htmlentities($_['dir'],ENT_COMPAT,'utf-8') ?>" id="dir">
+ <input type="hidden" name="dir" value="<?php echo $_['dir'] ?>" id="dir">
<button class="file_upload_filename">&nbsp;<img class='svg action' alt="Upload" src="<?php echo OCP\image_path("core", "actions/upload-white.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>
diff --git a/apps/files_archive/lib/storage.php b/apps/files_archive/lib/storage.php
index b8f7d468385..86761663611 100644
--- a/apps/files_archive/lib/storage.php
+++ b/apps/files_archive/lib/storage.php
@@ -18,7 +18,7 @@ class OC_Filestorage_Archive extends OC_Filestorage_Common{
private static $rootView;
private function stripPath($path){//files should never start with /
- if(substr($path,0,1)=='/'){
+ if(!$path || $path[0]=='/'){
$path=substr($path,1);
}
return $path;
diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php
index d6643f32689..a698ee00335 100644
--- a/apps/files_encryption/lib/cryptstream.php
+++ b/apps/files_encryption/lib/cryptstream.php
@@ -35,8 +35,12 @@ class OC_CryptStream{
private $meta=array();//header/meta for source stream
private $count;
private $writeCache;
+ private static $rootView;
public function stream_open($path, $mode, $options, &$opened_path){
+ if(!self::$rootView){
+ self::$rootView=new OC_FilesystemView('');
+ }
$path=str_replace('crypt://','',$path);
if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])){
$this->source=self::$sourceStreams[basename($path)]['stream'];
@@ -45,7 +49,7 @@ class OC_CryptStream{
$this->path=$path;
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);
+ $this->source=self::$rootView->fopen($path,$mode);
OC_FileProxy::$enabled=true;
if(!is_resource($this->source)){
OCP\Util::writeLog('files_encryption','failed to open '.$path,OCP\Util::ERROR);
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index 06f963fc981..9fd57c0f02b 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -59,7 +59,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
* @return bool
*/
private static function isEncrypted($path){
- $metadata=OC_FileCache::getCached($path);
+ $metadata=OC_FileCache::getCached($path,'');
return isset($metadata['encrypted']) and (bool)$metadata['encrypted'];
}
diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php
index 0450de82acb..f36b2193430 100644
--- a/apps/files_encryption/tests/proxy.php
+++ b/apps/files_encryption/tests/proxy.php
@@ -30,6 +30,9 @@ class Test_CryptProxy extends UnitTestCase {
}
public function testSimple(){
+ $oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true');
+ OCP\Config::setAppValue('files_encryption','enable_encryption','true');
+
$file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
$original=file_get_contents($file);
@@ -42,5 +45,17 @@ class Test_CryptProxy extends UnitTestCase {
$fromFile=OC_Filesystem::file_get_contents('/file');
$this->assertNotEqual($original,$stored);
$this->assertEqual($original,$fromFile);
+
+ $rootView=new OC_FilesystemView('');
+ $view=new OC_FilesystemView('/'.OC_User::getUser());
+ $userDir='/'.OC_User::getUser().'/files';
+
+ $fromFile=$rootView->file_get_contents($userDir.'/file');
+ $this->assertEqual($original,$fromFile);
+
+ $fromFile=$view->file_get_contents('files/file');
+ $this->assertEqual($original,$fromFile);
+
+ OCP\Config::setAppValue('files_encryption','enable_encryption',$oldConfig);
}
}
diff --git a/apps/files_external/ajax/addMountPoint.php b/apps/files_external/ajax/addMountPoint.php
new file mode 100644
index 00000000000..549cb6a3427
--- /dev/null
+++ b/apps/files_external/ajax/addMountPoint.php
@@ -0,0 +1,13 @@
+<?php
+
+OCP\JSON::checkAppEnabled('files_external');
+if ($_POST['isPersonal'] == 'true') {
+ OCP\JSON::checkLoggedIn();
+ $isPersonal = true;
+} else {
+ OCP\JSON::checkAdminUser();
+ $isPersonal = false;
+}
+OC_Mount_Config::addMountPoint($_POST['mountPoint'], $_POST['class'], $_POST['classOptions'], $_POST['mountType'], $_POST['applicable'], $isPersonal);
+
+?>
diff --git a/apps/files_external/ajax/dropbox.php b/apps/files_external/ajax/dropbox.php
new file mode 100644
index 00000000000..5f2ff17e625
--- /dev/null
+++ b/apps/files_external/ajax/dropbox.php
@@ -0,0 +1,41 @@
+<?php
+
+require_once 'Dropbox/autoload.php';
+
+OCP\JSON::checkAppEnabled('files_external');
+OCP\JSON::checkLoggedIn();
+if (isset($_POST['app_key']) && isset($_POST['app_secret'])) {
+ $oauth = new Dropbox_OAuth_Curl($_POST['app_key'], $_POST['app_secret']);
+ if (isset($_POST['step'])) {
+ switch ($_POST['step']) {
+ case 1:
+ try {
+ if (isset($_POST['callback'])) {
+ $callback = $_POST['callback'];
+ } else {
+ $callback = null;
+ }
+ $token = $oauth->getRequestToken();
+ OCP\JSON::success(array('data' => array('url' => $oauth->getAuthorizeUrl($callback), 'request_token' => $token['token'], 'request_token_secret' => $token['token_secret'])));
+ } catch (Exception $exception) {
+ OCP\JSON::error(array('data' => array('message' => 'Fetching request tokens failed. Verify that your Dropbox app key and secret are correct.')));
+ }
+ break;
+ case 2:
+ if (isset($_POST['request_token']) && isset($_POST['request_token_secret'])) {
+ try {
+ $oauth->setToken($_POST['request_token'], $_POST['request_token_secret']);
+ $token = $oauth->getAccessToken();
+ OCP\JSON::success(array('access_token' => $token['token'], 'access_token_secret' => $token['token_secret']));
+ } catch (Exception $exception) {
+ OCP\JSON::error(array('data' => array('message' => 'Fetching access tokens failed. Verify that your Dropbox app key and secret are correct.')));
+ }
+ }
+ break;
+ }
+ }
+} else {
+ OCP\JSON::error(array('data' => array('message' => 'Please provide a valid Dropbox app key and secret.')));
+}
+
+?> \ No newline at end of file
diff --git a/apps/files_external/ajax/google.php b/apps/files_external/ajax/google.php
new file mode 100644
index 00000000000..23ecfc3708d
--- /dev/null
+++ b/apps/files_external/ajax/google.php
@@ -0,0 +1,51 @@
+<?php
+
+require_once 'Google/common.inc.php';
+
+OCP\JSON::checkAppEnabled('files_external');
+OCP\JSON::checkLoggedIn();
+$consumer = new OAuthConsumer('anonymous', 'anonymous');
+$sigMethod = new OAuthSignatureMethod_HMAC_SHA1();
+if (isset($_POST['step'])) {
+ switch ($_POST['step']) {
+ case 1:
+ if (isset($_POST['callback'])) {
+ $callback = $_POST['callback'];
+ } else {
+ $callback = null;
+ }
+ $scope = 'https://docs.google.com/feeds/ https://docs.googleusercontent.com/ https://spreadsheets.google.com/feeds/';
+ $url = 'https://www.google.com/accounts/OAuthGetRequestToken?scope='.urlencode($scope);
+ $params = array('scope' => $scope, 'oauth_callback' => $callback);
+ $request = OAuthRequest::from_consumer_and_token($consumer, null, 'GET', $url, $params);
+ $request->sign_request($sigMethod, $consumer, null);
+ $response = send_signed_request('GET', $url, array($request->to_header()), null, false);
+ $token = array();
+ parse_str($response, $token);
+ if (isset($token['oauth_token']) && isset($token['oauth_token_secret'])) {
+ $authUrl = 'https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token='.$token['oauth_token'];
+ OCP\JSON::success(array('data' => array('url' => $authUrl, 'request_token' => $token['oauth_token'], 'request_token_secret' => $token['oauth_token_secret'])));
+ } else {
+ OCP\JSON::error(array('data' => array('message' => 'Fetching request tokens failed. Error: '.$response)));
+ }
+ break;
+ case 2:
+ if (isset($_POST['oauth_verifier']) && isset($_POST['request_token']) && isset($_POST['request_token_secret'])) {
+ $token = new OAuthToken($_POST['request_token'], $_POST['request_token_secret']);
+ $url = 'https://www.google.com/accounts/OAuthGetAccessToken';
+ $request = OAuthRequest::from_consumer_and_token($consumer, $token, 'GET', $url, array('oauth_verifier' => $_POST['oauth_verifier']));
+ $request->sign_request($sigMethod, $consumer, $token);
+ $response = send_signed_request('GET', $url, array($request->to_header()), null, false);
+ $token = array();
+ parse_str($response, $token);
+ if (isset($token['oauth_token']) && isset($token['oauth_token_secret'])) {
+ OCP\JSON::success(array('access_token' => $token['oauth_token'], 'access_token_secret' => $token['oauth_token_secret']));
+ } else {
+ OCP\JSON::error(array('data' => array('message' => 'Fetching access tokens failed. Error: '.$response)));
+ }
+ }
+ break;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/apps/files_external/ajax/removeMountPoint.php b/apps/files_external/ajax/removeMountPoint.php
new file mode 100644
index 00000000000..b77b306bcb5
--- /dev/null
+++ b/apps/files_external/ajax/removeMountPoint.php
@@ -0,0 +1,13 @@
+<?php
+
+OCP\JSON::checkAppEnabled('files_external');
+if ($_POST['isPersonal'] == 'true') {
+ OCP\JSON::checkLoggedIn();
+ $isPersonal = true;
+} else {
+ OCP\JSON::checkAdminUser();
+ $isPersonal = false;
+}
+OC_Mount_Config::removeMountPoint($_POST['mountPoint'], $_POST['mountType'], $_POST['applicable'], $isPersonal);
+
+?>
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index 9fd87e39346..837d35c9c63 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -6,11 +6,17 @@
* See the COPYING-README file.
*/
- OC::$CLASSPATH['OC_FileStorage_StreamWrapper']='apps/files_external/lib/streamwrapper.php';
+OC::$CLASSPATH['OC_FileStorage_StreamWrapper']='apps/files_external/lib/streamwrapper.php';
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';
OC::$CLASSPATH['OC_Filestorage_SMB']='apps/files_external/lib/smb.php';
+OC::$CLASSPATH['OC_Filestorage_AmazonS3']='apps/files_external/lib/amazons3.php';
+OC::$CLASSPATH['OC_Filestorage_Dropbox']='apps/files_external/lib/dropbox.php';
+OC::$CLASSPATH['OC_Mount_Config']='apps/files_external/lib/config.php';
OCP\App::registerAdmin('files_external', 'settings');
+if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == 'yes') {
+ OCP\App::registerPersonal('files_external', 'personal');
+}
diff --git a/apps/files_external/css/settings.css b/apps/files_external/css/settings.css
index b11af752ec8..d8575c49e34 100644
--- a/apps/files_external/css/settings.css
+++ b/apps/files_external/css/settings.css
@@ -1,6 +1,5 @@
.error { color: #FF3B3B; }
-td.type { width:8em; }
-td.mount, td.options, td.applicable { width:10em; }
-#addStorage>td { border:none; }
-#addStorage>td:not(.selectStorage) { visibility:hidden; }
-#selectStorage { margin-left:-10px; } \ No newline at end of file
+td.mountPoint, td.backend { width:10em; }
+#addMountPoint>td { border:none; }
+#addMountPoint>td.applicable { visibility:hidden; }
+#selectBackend { margin-left:-10px; } \ No newline at end of file
diff --git a/apps/files_external/js/dropbox.js b/apps/files_external/js/dropbox.js
new file mode 100644
index 00000000000..67f3c46a6ed
--- /dev/null
+++ b/apps/files_external/js/dropbox.js
@@ -0,0 +1,53 @@
+$(document).ready(function() {
+
+ $('#externalStorage tbody tr').each(function() {
+ if ($(this).find('.backend').data('class') == 'OC_Filestorage_Dropbox') {
+ var app_key = $(this).find('.configuration [data-parameter="app_key"]').val();
+ var app_secret = $(this).find('.configuration [data-parameter="app_secret"]').val();
+ if (app_key == '' && app_secret == '') {
+ $(this).find('.configuration').append('<a class="button dropbox">Grant access</a>');
+ } else {
+ var pos = window.location.search.indexOf('oauth_token') + 12
+ var token = $(this).find('.configuration [data-parameter="token"]');
+ if (pos != -1 && window.location.search.substr(pos, $(token).val().length) == $(token).val()) {
+ var token_secret = $(this).find('.configuration [data-parameter="token_secret"]');
+ var tr = $(this);
+ $.post(OC.filePath('files_external', 'ajax', 'dropbox.php'), { step: 2, app_key: app_key, app_secret: app_secret, request_token: $(token).val(), request_token_secret: $(token_secret).val() }, function(result) {
+ if (result && result.status == 'success') {
+ $(token).val(result.access_token);
+ $(token_secret).val(result.access_token_secret);
+ OC.MountConfig.saveStorage(tr);
+ } else {
+ OC.dialogs.alert(result.data.message, 'Error configuring Dropbox storage');
+ }
+ });
+ }
+ }
+ return false;
+ }
+ });
+
+ $('.dropbox').live('click', function(event) {
+ event.preventDefault();
+ var app_key = $(this).parent().find('[data-parameter="app_key"]').val();
+ var app_secret = $(this).parent().find('[data-parameter="app_secret"]').val();
+ if (app_key != '' && app_secret != '') {
+ var tr = $(this).parent().parent();
+ var token = $(this).parent().find('[data-parameter="token"]');
+ var token_secret = $(this).parent().find('[data-parameter="token_secret"]');
+ $.post(OC.filePath('files_external', 'ajax', 'dropbox.php'), { step: 1, app_key: app_key, app_secret: app_secret, callback: window.location.href }, function(result) {
+ if (result && result.status == 'success') {
+ $(token).val(result.data.request_token);
+ $(token_secret).val(result.data.request_token_secret);
+ OC.MountConfig.saveStorage(tr);
+ window.location = result.data.url;
+ } else {
+ OC.dialogs.alert(result.data.message, 'Error configuring Dropbox storage');
+ }
+ });
+ } else {
+ OC.dialogs.alert('Please provide a valid Dropbox app key and secret.', 'Error configuring Dropbox storage')
+ }
+ });
+
+});
diff --git a/apps/files_external/js/google.js b/apps/files_external/js/google.js
new file mode 100644
index 00000000000..0d65cfda011
--- /dev/null
+++ b/apps/files_external/js/google.js
@@ -0,0 +1,48 @@
+$(document).ready(function() {
+
+ $('#externalStorage tbody tr').each(function() {
+ if ($(this).find('.backend').data('class') == 'OC_Filestorage_Google') {
+ var token = $(this).find('[data-parameter="token"]');
+ var token_secret = $(this).find('[data-parameter="token_secret"]');
+ if ($(token).val() == '' && $(token).val() == '') {
+ $(this).find('.configuration').append('<a class="button google">Grant access</a>');
+ } else {
+ var params = {};
+ window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m, key, value) {
+ params[key] = value;
+ });
+ if (params['oauth_token'].length > 1 && decodeURIComponent(params['oauth_token']) == $(token).val() && params['oauth_verifier'].length > 1) {
+ var tr = $(this);
+ $.post(OC.filePath('files_external', 'ajax', 'google.php'), { step: 2, oauth_verifier: params['oauth_verifier'], request_token: $(token).val(), request_token_secret: $(token_secret).val() }, function(result) {
+ if (result && result.status == 'success') {
+ $(token).val(result.access_token);
+ $(token_secret).val(result.access_token_secret);
+ OC.MountConfig.saveStorage(tr);
+ } else {
+ OC.dialogs.alert(result.data.message, 'Error configuring Google Drive storage');
+ }
+ });
+ }
+ }
+ return false;
+ }
+ });
+
+ $('.google').live('click', function(event) {
+ event.preventDefault();
+ var tr = $(this).parent().parent();
+ var token = $(this).parent().find('[data-parameter="token"]');
+ var token_secret = $(this).parent().find('[data-parameter="token_secret"]');
+ $.post(OC.filePath('files_external', 'ajax', 'google.php'), { step: 1, callback: window.location.href }, function(result) {
+ if (result && result.status == 'success') {
+ $(token).val(result.data.request_token);
+ $(token_secret).val(result.data.request_token_secret);
+ OC.MountConfig.saveStorage(tr);
+ window.location = result.data.url;
+ } else {
+ OC.dialogs.alert(result.data.message, 'Error configuring Google Drive storage');
+ }
+ });
+ });
+
+});
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 9a558ad6e43..57188a6a266 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -1,59 +1,151 @@
-$(document).ready(function(){
-
- function applicableChange(applicable) {
- if (applicable == 'Global') {
-
+OC.MountConfig={
+ saveStorage:function(tr) {
+ var mountPoint = $(tr).find('.mountPoint input').val();
+ if (mountPoint == '') {
+ return false;
+ }
+ var backendClass = $(tr).find('.backend').data('class');
+ var configuration = $(tr).find('.configuration input');
+ var addMountPoint = true;
+ if (configuration.length < 1) {
+ return false;
+ }
+ var classOptions = {};
+ $.each(configuration, function(index, input) {
+ if ($(input).val() == '' && !$(input).hasClass('optional')) {
+ addMountPoint = false;
+ return false;
+ }
+ if ($(input).is(':checkbox')) {
+ if ($(input).is(':checked')) {
+ classOptions[$(input).data('parameter')] = true;
+ } else {
+ classOptions[$(input).data('parameter')] = false;
+ }
+ } else {
+ classOptions[$(input).data('parameter')] = $(input).val();
+ }
+ });
+ if (addMountPoint) {
+ if ($('#externalStorage').data('admin')) {
+ var isPersonal = false;
+ var multiselect = $(tr).find('.chzn-select').val();
+ var oldGroups = $(tr).find('.applicable').data('applicable-groups');
+ var oldUsers = $(tr).find('.applicable').data('applicable-users');
+ $.each(multiselect, function(index, value) {
+ var pos = value.indexOf('(group)');
+ if (pos != -1) {
+ var mountType = 'group';
+ var applicable = value.substr(0, pos);
+ if ($.inArray(applicable, oldGroups) != -1) {
+ oldGroups.splice($.inArray(applicable, oldGroups), 1);
+ }
+ } else {
+ var mountType = 'user';
+ var applicable = value;
+ if ($.inArray(applicable, oldUsers) != -1) {
+ oldUsers.splice($.inArray(applicable, oldUsers), 1);
+ }
+ }
+ $.post(OC.filePath('files_external', 'ajax', 'addMountPoint.php'), { mountPoint: mountPoint, class: backendClass, classOptions: classOptions, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ });
+ var mountType = 'group';
+ $.each(oldGroups, function(index, applicable) {
+ $.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ });
+ var mountType = 'user';
+ $.each(oldUsers, function(index, applicable) {
+ $.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ });
+ } else {
+ var isPersonal = true;
+ var mountType = 'user';
+ var applicable = OC.currentUser;
+ $.post(OC.filePath('files_external', 'ajax', 'addMountPoint.php'), { mountPoint: mountPoint, class: backendClass, classOptions: classOptions, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ }
}
- console.log(applicable);
}
+}
- $('#selectStorage').live('change', function() {
+$(document).ready(function() {
+
+ $('.chzn-select').chosen();
+
+ $('#selectBackend').live('change', function() {
var tr = $(this).parent().parent();
$('#externalStorage tbody').last().append($(tr).clone());
- var selected = $(this).val();
+ var selected = $(this).find('option:selected').text();
+ var backendClass = $(this).val();
$(this).parent().text(selected);
- var backends = $(this).data('configurations').split(';');
- var configuration = [];
- // Find selected backend configuration parameters
- $.each(backends, function(index, backend) {
- if (backend.split(':')[0] == selected) {
- configuration = backend.split(':')[1].split(',');
- // break;
- }
- });
+ $(tr).find('.backend').data('class', backendClass);
+ var configurations = $(this).data('configurations');
var td = $(tr).find('td.configuration');
- $.each(configuration, function(index, config) {
- if (config.indexOf('*') != -1) {
- td.append('<input type="password" placeholder="'+config.substring(1)+'" />');
- } else {
- td.append('<input type="text" placeholder="'+config+'" />');
+ $.each(configurations, function(backend, parameters) {
+ if (backend == backendClass) {
+ $.each(parameters['configuration'], function(parameter, placeholder) {
+ if (placeholder.indexOf('*') != -1) {
+ td.append('<input type="password" data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
+ } else if (placeholder.indexOf('!') != -1) {
+ td.append('<label><input type="checkbox" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'</label>');
+ } else if (placeholder.indexOf('&') != -1) {
+ td.append('<input type="text" class="optional" data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
+ } else if (placeholder.indexOf('#') != -1) {
+ td.append('<input type="hidden" data-parameter="'+parameter+'" />');
+ } else {
+ td.append('<input type="text" data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
+ }
+ });
+ if (parameters['custom']) {
+ OC.addScript('files_external', parameters['custom']);
+ }
+ return false;
}
});
+ $('.chz-select').chosen();
$(tr).find('td').last().attr('class', 'remove');
$(tr).removeAttr('id');
$(this).remove();
});
- $('td.remove>img').live('click', function() {
- $(this).parent().parent().remove();
- // TODO remove storage
+ $('#externalStorage td').live('change', function() {
+ OC.MountConfig.saveStorage($(this).parent());
});
- $('#externalStorage select[multiple]').each(function(index,element){
- applyMultiplySelect($(element));
+ $('td.remove>img').live('click', function() {
+ var tr = $(this).parent().parent();
+ var mountPoint = $(tr).find('.mountPoint input').val();
+ if (mountPoint == '') {
+ return false;
+ }
+ if ($('#externalStorage').data('admin')) {
+ var isPersonal = false;
+ var multiselect = $(tr).find('.chzn-select').val();
+ $.each(multiselect, function(index, value) {
+ var pos = value.indexOf('(group)');
+ if (pos != -1) {
+ var mountType = 'group';
+ var applicable = value.substr(0, pos);
+ } else {
+ var mountType = 'user';
+ var applicable = value;
+ }
+ $.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ });
+ } else {
+ var mountType = 'user';
+ var applicable = OC.currentUser;
+ var isPersonal = true;
+ }
+ $.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
+ $(tr).remove();
});
- function applyMultiplySelect(element) {
- var checkHandeler=false;
- element.multiSelect({
- oncheck:applicableChange,
- onuncheck:applicableChange,
- minWidth: 120,
- });
- }
-
$('#allowUserMounting').bind('change', function() {
- // TODO save setting
+ if (this.checked) {
+ OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes');
+ } else {
+ OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
+ }
});
}); \ No newline at end of file
diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php
index e847ef143c3..b8e5b9b079b 100644
--- a/apps/files_external/lib/amazons3.php
+++ b/apps/files_external/lib/amazons3.php
@@ -20,7 +20,7 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-require_once 'aws-sdk-1.5.5/sdk.class.php';
+require_once 'aws-sdk/sdk.class.php';
class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common {
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
new file mode 100755
index 00000000000..870c13b5aed
--- /dev/null
+++ b/apps/files_external/lib/config.php
@@ -0,0 +1,238 @@
+<?php
+/**
+* ownCloud
+*
+* @author Michael Gapczynski
+* @copyright 2012 Michael Gapczynski mtgap@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 to configure the config/mount.php and data/$user/mount.php files
+*/
+class OC_Mount_Config {
+
+ const MOUNT_TYPE_GLOBAL = 'global';
+ const MOUNT_TYPE_GROUP = 'group';
+ const MOUNT_TYPE_USER = 'user';
+
+ /**
+ * Get details on each of the external storage backends, used for the mount config UI
+ * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded
+ * If the configuration parameter should be secret, add a '*' to the beginning of the value
+ * If the configuration parameter is a boolean, add a '!' to the beginning of the value
+ * If the configuration parameter is optional, add a '&' to the beginning of the value
+ * If the configuration parameter is hidden, add a '#' to the begining of the value
+ * @return array
+ */
+ public static function getBackends() {
+ return array(
+ 'OC_Filestorage_Local' => array('backend' => 'Local', 'configuration' => array('datadir' => 'Location')),
+ 'OC_Filestorage_AmazonS3' => array('backend' => 'Amazon S3', 'configuration' => array('key' => 'Key', 'secret' => '*Secret', 'bucket' => 'Bucket')),
+ 'OC_Filestorage_Dropbox' => array('backend' => 'Dropbox', 'configuration' => array('app_key' => 'App key', 'app_secret' => 'App secret', 'token' => '#token', 'token_secret' => '#token_secret'), 'custom' => 'dropbox'),
+ 'OC_Filestorage_FTP' => array('backend' => 'FTP', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure ftps://')),
+ 'OC_Filestorage_Google' => array('backend' => 'Google Drive', 'configuration' => array('token' => '#token', 'token_secret' => '#token secret'), 'custom' => 'google'),
+ 'OC_Filestorage_SWIFT' => array('backend' => 'OpenStack Swift', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'token' => '*Token', 'root' => '&Root', 'secure' => '!Secure ftps://')),
+ 'OC_Filestorage_SMB' => array('backend' => 'SMB', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root')),
+ 'OC_Filestorage_DAV' => array('backend' => 'WebDAV', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure https://'))
+ );
+ }
+
+ /**
+ * Get the system mount points
+ * The returned array is not in the same format as getUserMountPoints()
+ * @return array
+ */
+ public static function getSystemMountPoints() {
+ $mountPoints = self::readData(false);
+ $backends = self::getBackends();
+ $system = array();
+ if (isset($mountPoints[self::MOUNT_TYPE_GROUP])) {
+ foreach ($mountPoints[self::MOUNT_TYPE_GROUP] as $group => $mounts) {
+ foreach ($mounts as $mountPoint => $mount) {
+ // Remove '/$user/files/' from mount point
+ $mountPoint = substr($mountPoint, 13);
+ // Merge the mount point into the current mount points
+ if (isset($system[$mountPoint]) && $system[$mountPoint]['configuration'] == $mount['options']) {
+ $system[$mountPoint]['applicable']['groups'] = array_merge($system[$mountPoint]['applicable']['groups'], array($group));
+ } else {
+ $system[$mountPoint] = array('class' => $mount['class'], 'backend' => $backends[$mount['class']]['backend'], 'configuration' => $mount['options'], 'applicable' => array('groups' => array($group), 'users' => array()));
+ }
+ }
+ }
+ }
+ if (isset($mountPoints[self::MOUNT_TYPE_USER])) {
+ foreach ($mountPoints[self::MOUNT_TYPE_USER] as $user => $mounts) {
+ foreach ($mounts as $mountPoint => $mount) {
+ // Remove '/$user/files/' from mount point
+ $mountPoint = substr($mountPoint, 13);
+ // Merge the mount point into the current mount points
+ if (isset($system[$mountPoint]) && $system[$mountPoint]['configuration'] == $mount['options']) {
+ $system[$mountPoint]['applicable']['users'] = array_merge($system[$mountPoint]['applicable']['users'], array($user));
+ } else {
+ $system[$mountPoint] = array('class' => $mount['class'], 'backend' => $backends[$mount['class']]['backend'], 'configuration' => $mount['options'], 'applicable' => array('groups' => array(), 'users' => array($user)));
+ }
+ }
+ }
+ }
+ return $system;
+ }
+
+ /**
+ * Get the personal mount points of the current user
+ * The returned array is not in the same format as getUserMountPoints()
+ * @return array
+ */
+ public static function getPersonalMountPoints() {
+ $mountPoints = self::readData(true);
+ $backends = self::getBackends();
+ $uid = OCP\User::getUser();
+ $personal = array();
+ if (isset($mountPoints[self::MOUNT_TYPE_USER][$uid])) {
+ foreach ($mountPoints[self::MOUNT_TYPE_USER][$uid] as $mountPoint => $mount) {
+ // Remove '/uid/files/' from mount point
+ $personal[substr($mountPoint, strlen($uid) + 8)] = array('class' => $mount['class'], 'backend' => $backends[$mount['class']]['backend'], 'configuration' => $mount['options']);
+ }
+ }
+ return $personal;
+ }
+
+
+ /**
+ * Add a mount point to the filesystem
+ * @param string Mount point
+ * @param string Backend class
+ * @param array Backend parameters for the class
+ * @param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
+ * @param string User or group to apply mount to
+ * @param bool Personal or system mount point i.e. is this being called from the personal or admin page
+ * @return bool
+ */
+ public static function addMountPoint($mountPoint, $class, $classOptions, $mountType, $applicable, $isPersonal = false) {
+ if ($isPersonal) {
+ // Verify that the mount point applies for the current user
+ // Prevent non-admin users from mounting local storage
+ if ($applicable != OCP\User::getUser() || $class == 'OC_Filestorage_Local') {
+ return false;
+ }
+ $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/');
+ } else {
+ $mountPoint = '/$user/files/'.ltrim($mountPoint, '/');
+ }
+ $mount = array($applicable => array($mountPoint => array('class' => $class, 'options' => $classOptions)));
+ $mountPoints = self::readData($isPersonal);
+ // Merge the new mount point into the current mount points
+ if (isset($mountPoints[$mountType])) {
+ if (isset($mountPoints[$mountType][$applicable])) {
+ $mountPoints[$mountType][$applicable] = array_merge($mountPoints[$mountType][$applicable], $mount[$applicable]);
+ } else {
+ $mountPoints[$mountType] = array_merge($mountPoints[$mountType], $mount);
+ }
+ } else {
+ $mountPoints[$mountType] = $mount;
+ }
+ self::writeData($isPersonal, $mountPoints);
+ return true;
+ }
+
+ /**
+ *
+ * @param string Mount point
+ * @param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER
+ * @param string User or group to remove mount from
+ * @param bool Personal or system mount point
+ * @return bool
+ */
+ public static function removeMountPoint($mountPoint, $mountType, $applicable, $isPersonal = false) {
+ // Verify that the mount point applies for the current user
+ if ($isPersonal && $applicable != OCP\User::getUser()) {
+ return false;
+ }
+ $mountPoints = self::readData($isPersonal);
+ // Remove mount point
+ unset($mountPoints[$mountType][$applicable]['/$user/files/'.$mountPoint]);
+ // Unset parent arrays if empty
+ if (empty($mountPoints[$mountType][$applicable])) {
+ unset($mountPoints[$mountType][$applicable]);
+ if (empty($mountPoints[$mountType])) {
+ unset($mountPoints[$mountType]);
+ }
+ }
+ self::writeData($isPersonal, $mountPoints);
+ return true;
+ }
+
+ /**
+ * Read the mount points in the config file into an array
+ * @param bool Personal or system config file
+ * @return array
+ */
+ private static function readData($isPersonal) {
+ if ($isPersonal) {
+ $file = OC::$SERVERROOT.'/data/'.OCP\User::getUser().'/mount.php';
+ } else {
+ $file = OC::$SERVERROOT.'/config/mount.php';
+ }
+ if (is_file($file)) {
+ $mountPoints = include($file);
+ if (is_array($mountPoints)) {
+ return $mountPoints;
+ }
+ }
+ return array();
+ }
+
+ /**
+ * Write the mount points to the config file
+ * @param bool Personal or system config file
+ * @param array Mount points
+ */
+ private static function writeData($isPersonal, $data) {
+ if ($isPersonal) {
+ $file = OC::$SERVERROOT.'/data/'.OCP\User::getUser().'/mount.php';
+ } else {
+ $file = OC::$SERVERROOT.'/config/mount.php';
+ }
+ $content = "<?php return array (\n";
+ if (isset($data[self::MOUNT_TYPE_GROUP])) {
+ $content .= "\t'group' => array (\n";
+ foreach ($data[self::MOUNT_TYPE_GROUP] as $group => $mounts) {
+ $content .= "\t\t'".$group."' => array (\n";
+ foreach ($mounts as $mountPoint => $mount) {
+ $content .= "\t\t\t'".$mountPoint."' => ".str_replace("\n", '', var_export($mount, true)).",\n";
+
+ }
+ $content .= "\t\t),\n";
+ }
+ $content .= "\t),\n";
+ }
+ if (isset($data[self::MOUNT_TYPE_USER])) {
+ $content .= "\t'user' => array (\n";
+ foreach ($data[self::MOUNT_TYPE_USER] as $user => $mounts) {
+ $content .= "\t\t'".$user."' => array (\n";
+ foreach ($mounts as $mountPoint => $mount) {
+ $content .= "\t\t\t'".$mountPoint."' => ".str_replace("\n", '', var_export($mount, true)).",\n";
+ }
+ $content .= "\t\t),\n";
+ }
+ $content .= "\t),\n";
+ }
+ $content .= ");\n?>";
+ @file_put_contents($file, $content);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php
new file mode 100755
index 00000000000..5e94277c6d4
--- /dev/null
+++ b/apps/files_external/lib/dropbox.php
@@ -0,0 +1,203 @@
+<?php
+
+/**
+* ownCloud
+*
+* @author Michael Gapczynski
+* @copyright 2012 Michael Gapczynski mtgap@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/>.
+*/
+
+require_once 'Dropbox/autoload.php';
+
+class OC_Filestorage_Dropbox extends OC_Filestorage_Common {
+
+ private $dropbox;
+ private $metaData = array();
+
+ private static $tempFiles = array();
+
+ public function __construct($params) {
+ $oauth = new Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']);
+ $oauth->setToken($params['token'], $params['token_secret']);
+ $this->dropbox = new Dropbox_API($oauth, 'dropbox');
+
+ }
+
+ private function getMetaData($path, $list = false) {
+ if (!$list && isset($this->metaData[$path])) {
+ return $this->metaData[$path];
+ } else {
+ if ($list) {
+ $response = $this->dropbox->getMetaData($path);
+ if ($response && isset($response['contents'])) {
+ $contents = $response['contents'];
+ // Cache folder's contents
+ foreach ($contents as $file) {
+ $this->metaData[$path.'/'.basename($file['path'])] = $file;
+ }
+ unset($response['contents']);
+ $this->metaData[$path] = $response;
+ }
+ $this->metaData[$path] = $response;
+ // Return contents of folder only
+ return $contents;
+ } else {
+ try {
+ $response = $this->dropbox->getMetaData($path, 'false');
+ $this->metaData[$path] = $response;
+ return $response;
+ } catch (Exception $exception) {
+ return false;
+ }
+ }
+ }
+ }
+
+ public function mkdir($path) {
+ return $this->dropbox->createFolder($path);
+ }
+
+ public function rmdir($path) {
+ return $this->dropbox->delete($path);
+ }
+
+ public function opendir($path) {
+ if ($contents = $this->getMetaData($path, true)) {
+ $files = array();
+ foreach ($contents as $file) {
+ $files[] = basename($file['path']);
+ }
+ OC_FakeDirStream::$dirs['dropbox'] = $files;
+ return opendir('fakedir://dropbox');
+ }
+ return false;
+ }
+
+ public function stat($path) {
+ if ($metaData = $this->getMetaData($path)) {
+ $stat['size'] = $metaData['bytes'];
+ $stat['atime'] = time();
+ $stat['mtime'] = strtotime($metaData['modified']);
+ $stat['ctime'] = $stat['mtime'];
+ return $stat;
+ }
+ return false;
+ }
+
+ public function filetype($path) {
+ if ($path == '' || $path == '/') {
+ return 'dir';
+ } else if ($metaData = $this->getMetaData($path)) {
+ if ($metaData['is_dir'] == 'true') {
+ return 'dir';
+ } else {
+ return 'file';
+ }
+ }
+ return false;
+ }
+
+ public function is_readable($path) {
+ return true;
+ }
+
+ public function is_writable($path) {
+ return true;
+ }
+
+ public function file_exists($path) {
+ if ($path == '' || $path == '/') {
+ return true;
+ }
+ if ($this->getMetaData($path)) {
+ return true;
+ }
+ return false;
+ }
+
+ public function unlink($path) {
+ return $this->dropbox->delete($path);
+ }
+
+ public function fopen($path, $mode) {
+ switch ($mode) {
+ case 'r':
+ case 'rb':
+ $tmpFile = OC_Helper::tmpFile();
+ file_put_contents($tmpFile, $this->dropbox->getFile($path));
+ 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+':
+ 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])) {
+ $handle = fopen($tmpFile, 'r');
+ $response = $this->dropbox->putFile(self::$tempFiles[$tmpFile], $handle);
+ if ($response) {
+ unlink($tmpFile);
+ }
+ }
+ }
+
+ public function getMimeType($path) {
+ if ($this->filetype($path) == 'dir') {
+ return 'httpd/unix-directory';
+ } else if ($metaData = $this->getMetaData($path)) {
+ return $metaData['mime_type'];
+ }
+ return false;
+ }
+
+ public function free_space($path) {
+ if ($info = $this->dropbox->getAccountInfo()) {
+ return $info['quota_info']['quota'] - $info['quota_info']['normal'];
+ }
+ return false;
+ }
+
+ public function touch($path, $mtime = null) {
+ return false;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php
index e9655ebf3a5..4d5ae670de5 100644
--- a/apps/files_external/lib/ftp.php
+++ b/apps/files_external/lib/ftp.php
@@ -21,7 +21,7 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
$this->password=$params['password'];
$this->secure=isset($params['secure'])?(bool)$params['secure']:false;
$this->root=isset($params['root'])?$params['root']:'/';
- if(substr($this->root,0,1)!='/'){
+ if(!$this->root || $this->root[0]!='/'){
$this->root='/'.$this->root;
}
diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php
index d2285a6d82c..c2a4af0ff8a 100644
--- a/apps/files_external/lib/google.php
+++ b/apps/files_external/lib/google.php
@@ -20,7 +20,7 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-require_once 'common.inc.php';
+require_once 'Google/common.inc.php';
class OC_Filestorage_Google extends OC_Filestorage_Common {
diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php
index f5e6d78e776..9112655194a 100644
--- a/apps/files_external/lib/smb.php
+++ b/apps/files_external/lib/smb.php
@@ -13,6 +13,7 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
private $user;
private $host;
private $root;
+ private $share;
private static $tempFiles=array();
@@ -20,17 +21,32 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
$this->host=$params['host'];
$this->user=$params['user'];
$this->password=$params['password'];
+ $this->share=$params['share'];
$this->root=isset($params['root'])?$params['root']:'/';
+ if(!$this->root || $this->root[0]!='/'){
+ $this->root='/'.$this->root;
+ }
+ if(substr($this->root,-1,1)!='/'){
+ $this->root.='/';
+ }
+ if(!$this->share || $this->share[0]!='/'){
+ $this->share='/'.$this->share;
+ }
+ if(substr($this->share,-1,1)=='/'){
+ $this->share=substr($this->share,0,-1);
+ }
//create the root folder if necesary
- $this->mkdir('');
+ if(!$this->is_dir('')){
+ $this->mkdir('');
+ }
}
public function constructUrl($path){
if(substr($path,-1)=='/'){
$path=substr($path,0,-1);
}
- return 'smb://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path;
+ return 'smb://'.$this->user.':'.$this->password.'@'.$this->host.$this->share.$this->root.$path;
}
}
diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php
index e3ba9c240cf..58b95a6ae01 100644
--- a/apps/files_external/lib/swift.php
+++ b/apps/files_external/lib/swift.php
@@ -269,7 +269,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
$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)!='/'){
+ if(!$this->root || $this->root[0]!='/'){
$this->root='/'.$this->root;
}
$this->auth = new CF_Authentication($this->user, $this->token, null, $this->host);
diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php
index 07c90d4878e..d136f04f3eb 100644
--- a/apps/files_external/lib/webdav.php
+++ b/apps/files_external/lib/webdav.php
@@ -25,7 +25,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
$this->password=$params['password'];
$this->secure=isset($params['secure'])?(bool)$params['secure']:false;
$this->root=isset($params['root'])?$params['root']:'/';
- if(substr($this->root,0,1)!='/'){
+ if(!$this->root || $this->root[0]!='/'){
$this->root='/'.$this->root;
}
if(substr($this->root,-1,1)!='/'){
@@ -273,7 +273,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
}
private function cleanPath($path){
- if(substr($path,0,1)=='/'){
+ if(!$path || $path[0]=='/'){
return substr($path,1);
}else{
return $path;
diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php
new file mode 100755
index 00000000000..32e08742442
--- /dev/null
+++ b/apps/files_external/personal.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+* ownCloud
+*
+* @author Michael Gapczynski
+* @copyright 2012 Michael Gapczynski mtgap@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/>.
+*/
+
+OCP\Util::addScript('files_external', 'settings');
+OCP\Util::addStyle('files_external', 'settings');
+$backends = OC_Mount_Config::getBackends();
+// Remove local storage
+unset($backends['OC_Filestorage_Local']);
+$tmpl = new OCP\Template('files_external', 'settings');
+$tmpl->assign('isAdminPage', false);
+$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
+$tmpl->assign('backends', $backends);
+return $tmpl->fetchPage();
+
+?> \ No newline at end of file
diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php
index ce1b308d757..983855ecdcc 100644
--- a/apps/files_external/settings.php
+++ b/apps/files_external/settings.php
@@ -20,16 +20,15 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-OCP\Util::addscript('files_external', 'settings');
-OCP\Util::addstyle('files_external', 'settings');
+OCP\Util::addScript('files_external', 'settings');
+OCP\Util::addStyle('files_external', 'settings');
$tmpl = new OCP\Template('files_external', 'settings');
-$tmpl->assign('allowUserMounting', 'yes');
$tmpl->assign('isAdminPage', true);
-$tmpl->assign('storage', array());
+$tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints());
+$tmpl->assign('backends', OC_Mount_Config::getBackends());
$tmpl->assign('groups', OC_Group::getGroups());
-$tmpl->assign('backends', array('Amazon S3', 'FTP', 'Google Drive', 'SWIFT', 'WebDAV'));
-$tmpl->assign('configurations', '');
-$tmpl->assign('options', array('Encrypt', 'Version control', 'Allow sharing'));
+$tmpl->assign('users', OCP\User::getUsers());
+$tmpl->assign('allowUserMounting', OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes'));
return $tmpl->fetchPage();
?> \ No newline at end of file
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index e34c0322390..6c37df8001e 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -1,70 +1,85 @@
<form id="files_external">
<fieldset class="personalblock">
<legend><strong><?php echo $l->t('External Storage'); ?></strong></legend>
- <?php if (isset($_['storage'])): ?>
- <table id="externalStorage">
+ <table id="externalStorage" data-admin="<?php echo json_encode($_['isAdminPage']); ?>">
<thead>
<tr>
- <th><?php echo $l->t('Type'); ?></th>
+ <th><?php echo $l->t('Mount point'); ?></th>
+ <th><?php echo $l->t('Backend'); ?></th>
<th><?php echo $l->t('Configuration'); ?></th>
- <th><?php echo $l->t('Mount Location'); ?></th>
- <th><?php echo $l->t('Options'); ?></th>
- <?php if ($_['isAdminPage'] == true) echo '<th>'.$l->t('Applicable').'</th>'; ?>
+ <!--<th><?php echo $l->t('Options'); ?></th> -->
+ <?php if ($_['isAdminPage']) echo '<th>'.$l->t('Applicable').'</th>'; ?>
<th>&nbsp;</th>
</tr>
</thead>
- <tbody>
- <?php $_['storage'] = array_merge($_['storage'], array(array('id' => 'addStorage', 'mount' => ''))); ?>
- <?php foreach($_['storage'] as $storage): ?>
- <tr <?php if ($storage['id'] == 'addStorage') echo 'id="addStorage"'; ?> data-storage-id="<?php echo $storage['id']; ?>">
- <?php if ($storage['id'] == 'addStorage'): ?>
- <td class="selectStorage">
- <select id="selectStorage" data-configurations="<?php echo $_['configurations']; ?>">
- <option value="" disabled selected style="display:none;"><?php echo $l->t('Add storage'); ?></option>
- <?php foreach($_['backends'] as $backend): ?>
- <option value="<?php echo $backend; ?>"><?php echo $backend; ?></option>
+ <tbody width="100%">
+ <?php $_['mounts'] = array_merge($_['mounts'], array('' => array())); ?>
+ <?php foreach ($_['mounts'] as $mountPoint => $mount): ?>
+ <tr <?php if ($mountPoint == '') echo 'id="addMountPoint"'; ?>>
+ <td class="mountPoint"><input type="text" name="mountPoint" value="<?php echo $mountPoint; ?>" placeholder="<?php echo $l->t('Mount point'); ?>" /></td>
+ <?php if ($mountPoint == ''): ?>
+ <td class="backend">
+ <select id="selectBackend" data-configurations='<?php echo json_encode($_['backends']); ?>'>
+ <option value="" disabled selected style="display:none;"><?php echo $l->t('Add mount point'); ?></option>
+ <?php foreach ($_['backends'] as $class => $backend): ?>
+ <option value="<?php echo $class; ?>"><?php echo $backend['backend']; ?></option>
<?php endforeach; ?>
</select>
</td>
<?php else: ?>
- <td class="type" <?php if ($storage['status'] == 'error') echo 'class="error"'; ?>><?php echo $storage['type']; ?></td>
- <?php endif; ?>
- <td class ="configuration">
- <?php if (isset($storage['configuration'])): ?>
- <?php foreach($storage['configuration'] as $parameter => $value): ?>
- <?php if (strpos($parameter, '*') !== false): ?>
- <input type="password" value="<?php echo $value; ?>" placeholder="<?php echo $l->t(substr($parameter, 1)); ?>" />
- <?php else: ?>
- <input type="text" value="<?php echo $value; ?>" placeholder="<?php echo $l->t($parameter); ?>" />
- <?php endif; ?>
- <?php endforeach; ?>
+ <td class="backend" data-class="<?php echo $mount['class']; ?>"><?php echo $mount['backend']; ?></td>
<?php endif; ?>
+ <td class ="configuration" width="100%">
+ <?php if (isset($mount['configuration'])): ?>
+ <?php foreach ($mount['configuration'] as $parameter => $value): ?>
+ <?php if (isset($_['backends'][$mount['class']]['configuration'][$parameter])): ?>
+ <?php $placeholder = $_['backends'][$mount['class']]['configuration'][$parameter]; ?>
+ <?php if (strpos($placeholder, '*') !== false): ?>
+ <input type="password" data-parameter="<?php echo $parameter; ?>" value="<?php echo $value; ?>" placeholder="<?php echo substr($placeholder, 1); ?>" />
+ <?php elseif(strpos($placeholder, '!') !== false): ?>
+ <label><input type="checkbox" data-parameter="<?php echo $parameter; ?>" <?php if ($value == 'true') echo ' checked="checked"'; ?> /><?php echo substr($placeholder, 1); ?></label>
+ <?php elseif (strpos($placeholder, '&') !== false): ?>
+ <input type="text" class="optional" data-parameter="<?php echo $parameter; ?>" value="<?php echo $value; ?>" placeholder="<?php echo substr($placeholder, 1); ?>" />
+ <?php elseif (strpos($placeholder, '#') !== false): ?>
+ <input type="hidden" data-parameter="<?php echo $parameter; ?>" value="<?php echo $value; ?>" />
+ <?php else: ?>
+ <input type="text" data-parameter="<?php echo $parameter; ?>" value="<?php echo $value; ?>" placeholder="<?php echo $placeholder; ?>" />
+ <?php endif; ?>
+ <?php endif; ?>
+ <?php endforeach; ?>
+ <?php if (isset($_['backends'][$mount['class']]['custom'])) OCP\Util::addScript('files_external', $_['backends'][$mount['class']]['custom']); ?>
+ <?php endif; ?>
</td>
- <td class="mount"><input type="text" name="storageMountLocation" value="<?php echo $storage['mount']; ?>" placeholder="<?php echo $l->t('Mount Location'); ?>" /></td>
- <td class="options">
- <select class="selectOptions" title="<?php echo $l->t('None set')?>" multiple="multiple">
+ <!--<td class="options">
+ <select class="selectOptions" title="<?php echo $l->t('None set')?>" multiple="multiple" disabled>
<?php if (OCP\App::isEnabled('files_encryption')) echo '<option value="Encrypt">Encrypt</option>'; ?>
<?php if (OCP\App::isEnabled('files_versions')) echo '<option value="Version control">Version control</option>'; ?>
<?php if (OCP\App::isEnabled('files_sharing')) echo '<option value="Allow sharing">Allow sharing</option>'; ?>
</select>
- </td>
- <?php if ($_['isAdminPage'] == true): ?>
- <td class="applicable">
- <select class="selectApplicable" data-storage-applicable="<?php echo $storage['applicable']; ?>" title="<?php echo $l->t('None set'); ?>" multiple="multiple">
- <option value="Global"><?php echo $l->t('Global'); ?></option>
- <?php foreach($_['groups'] as $group): ?>
- <option value="<?php echo $group; ?>"><?php echo $group; ?></option>
- <?php endforeach; ?>
+ </td>-->
+ <?php if ($_['isAdminPage']): ?>
+ <td class="applicable" align="right" data-applicable-groups='<?php if (isset($mount['applicable']['groups'])) echo json_encode($mount['applicable']['groups']); ?>' data-applicable-users='<?php if (isset($mount['applicable']['users'])) echo json_encode($mount['applicable']['users']); ?>'>
+ <select class="chzn-select" multiple style="width:20em;" data-placeholder="<?php echo $l->t('None set'); ?>">
+ <option value="all"><?php echo $l->t('All Users'); ?></option>
+ <optgroup label="<?php echo $l->t('Groups'); ?>">
+ <?php foreach ($_['groups'] as $group): ?>
+ <option value="<?php echo $group; ?>(group)" <?php if (isset($mount['applicable']['groups']) && in_array($group, $mount['applicable']['groups'])) echo 'selected="selected"'; ?>><?php echo $group; ?></option>
+ <?php endforeach; ?>
+ </optgroup>
+ <optgroup label="<?php echo $l->t('Users'); ?>">
+ <?php foreach ($_['users'] as $user): ?>
+ <option value="<?php echo $user; ?>" <?php if (isset($mount['applicable']['users']) && in_array($user, $mount['applicable']['users'])) echo 'selected="selected"'; ?>"><?php echo $user; ?></option>
+ <?php endforeach; ?>
+ </optgroup>
</select>
</td>
<?php endif; ?>
- <td <?php if ($storage['id'] != 'addStorage') echo 'class="remove"'; ?>><img alt="<?php echo $l->t('Delete'); ?>" title="<?php echo $l->t('Delete'); ?>" class="svg action" src="<?php echo image_path('core', 'actions/delete.svg'); ?>" /></td>
+ <td <?php if ($mountPoint != '') echo 'class="remove"'; ?>><img alt="<?php echo $l->t('Delete'); ?>" title="<?php echo $l->t('Delete'); ?>" class="svg action" src="<?php echo image_path('core', 'actions/delete.svg'); ?>" /></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
- <?php endif; ?>
- <?php if ($_['isAdminPage'] == true): ?>
+ <?php if ($_['isAdminPage']): ?>
<br />
<input type="checkbox" name="allowUserMounting" id="allowUserMounting" value="1" <?php if ($_['allowUserMounting'] == 'yes') echo ' checked="checked"'; ?> />
<label for="allowUserMounting"><?php echo $l->t('Enable User External Storage'); ?></label><br/>
diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php
index 970008d642c..e58a87fabdf 100644
--- a/apps/files_external/tests/config.php
+++ b/apps/files_external/tests/config.php
@@ -34,7 +34,8 @@ return array(
'user'=>'test',
'password'=>'test',
'host'=>'localhost',
- 'root'=>'/test',
+ 'share'=>'/test',
+ 'root'=>'/test/',
),
'amazons3'=>array(
'run'=>false,
diff --git a/apps/files_external/tests/smb.php b/apps/files_external/tests/smb.php
index 52e1700b019..e1495b7480d 100644
--- a/apps/files_external/tests/smb.php
+++ b/apps/files_external/tests/smb.php
@@ -19,7 +19,7 @@ if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']){
public function setUp(){
$id=uniqid();
$this->config=include('apps/files_external/tests/config.php');
- $this->config['smb']['root'].='/'.$id;//make sure we have an new empty folder to work in
+ $this->config['smb']['root'].=$id;//make sure we have an new empty folder to work in
$this->instance=new OC_Filestorage_SMB($this->config['smb']);
}
diff --git a/apps/files_imageviewer/js/jquery.fancybox-1.3.4.js b/apps/files_imageviewer/js/jquery.fancybox-1.3.4.js
index be77275376b..a1db7b6198c 100644
--- a/apps/files_imageviewer/js/jquery.fancybox-1.3.4.js
+++ b/apps/files_imageviewer/js/jquery.fancybox-1.3.4.js
@@ -84,7 +84,7 @@
}
title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';
-
+
if (obj.nodeName && !selectedOpts.orig) {
selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
}
@@ -93,6 +93,8 @@
title = selectedOpts.orig.attr('alt');
}
+ title = title.replace(/</, "&lt;").replace(/>/, "&gt;");
+
href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;
if ((/^(?:javascript)/i).test(href) || href == '#') {
diff --git a/apps/files_imageviewer/js/jquery.fancybox-1.3.4.pack.js b/apps/files_imageviewer/js/jquery.fancybox-1.3.4.pack.js
index 1373ed0838b..e5ee2ae3595 100644
--- a/apps/files_imageviewer/js/jquery.fancybox-1.3.4.pack.js
+++ b/apps/files_imageviewer/js/jquery.fancybox-1.3.4.pack.js
@@ -1,46 +1 @@
-/*
- * FancyBox - jQuery Plugin
- * Simple and fancy lightbox alternative
- *
- * Examples and documentation at: http://fancybox.net
- *
- * Copyright (c) 2008 - 2010 Janis Skarnelis
- * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
- *
- * Version: 1.3.4 (11/11/2010)
- * Requires: jQuery v1.3+
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- */
-
-;(function(b){var m,t,u,f,D,j,E,n,z,A,q=0,e={},o=[],p=0,d={},l=[],G=null,v=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,y=0,s="",r,i,h=false,B=b.extend(b("<div/>")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){t.hide();v.onerror=v.onload=null;G&&G.abort();m.empty()},O=function(){if(false===e.onError(o,q,e)){t.hide();h=false}else{e.titleShow=false;e.width="auto";e.height="auto";m.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');
-F()}},I=function(){var a=o[q],c,g,k,C,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(o,q,e);if(w===false)h=false;else{if(typeof w=="object")e=b.extend(e,w);k=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(k===""&&e.orig&&e.titleFromAlt)k=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)||
-c=="#")c=null;if(e.type){g=e.type;if(!c)c=e.content}else if(e.content)g="html";else if(c)g=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(g){if(g=="inline"){a=c.substr(c.indexOf("#"));g=b(a).length>0?"inline":"ajax"}e.type=g;e.href=c;e.title=k;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=
-false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);m.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(j.children())});switch(g){case "html":m.html(e.content);F();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){h=false;break}b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(j.children())}).bind("fancybox-cancel",
-function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity();v=new Image;v.onerror=function(){O()};v.onload=function(){h=true;v.onerror=v.onload=null;e.width=v.width;e.height=v.height;b("<img />").attr({id:"fancybox-img",src:v.src,alt:e.title}).appendTo(m);Q()};v.src=c;break;case "swf":e.scrolling="no";C='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+c+
-'"></param>';P="";b.each(e.swf,function(x,H){C+='<param name="'+x+'" value="'+H+'"></param>';P+=" "+x+'="'+H+'"'});C+='<embed src="'+c+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+P+"></embed></object>";m.html(C);F();break;case "ajax":h=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;G=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(x){x.status>0&&O()},success:function(x,H,R){if((typeof R=="object"?R:G).status==200){if(typeof e.ajax.win==
-"function"){w=e.ajax.win(c,x,H,R);if(w===false){t.hide();return}else if(typeof w=="string"||typeof w=="object")x=w}m.html(x);F()}}}));break;case "iframe":Q()}}else O()}},F=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";m.wrapInner('<div style="width:'+a+";height:"+c+
-";overflow: "+(e.scrolling=="auto"?"auto":e.scrolling=="yes"?"scroll":"hidden")+';position:relative;"></div>');e.width=m.width();e.height=m.height();Q()},Q=function(){var a,c;t.hide();if(f.is(":visible")&&false===d.onCleanup(l,p,d)){b.event.trigger("fancybox-cancel");h=false}else{h=true;b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());l=o;p=q;d=e;if(d.overlayShow){u.css({"background-color":d.overlayColor,
-opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!u.is(":visible")){M&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});u.show()}}else u.hide();i=X();s=d.title||"";y=0;n.empty().removeAttr("style").removeClass();if(d.titleShow!==false){if(b.isFunction(d.titleFormat))a=d.titleFormat(s,l,p,d);else a=s&&s.length?
-d.titlePosition=="float"?'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+s+'</td><td id="fancybox-title-float-right"></td></tr></table>':'<div id="fancybox-title-'+d.titlePosition+'">'+s+"</div>":false;s=a;if(!(!s||s==="")){n.addClass("fancybox-title-"+d.titlePosition).html(s).appendTo("body").show();switch(d.titlePosition){case "inside":n.css({width:i.width-d.padding*2,marginLeft:d.padding,marginRight:d.padding});
-y=n.outerHeight(true);n.appendTo(D);i.height+=y;break;case "over":n.css({marginLeft:d.padding,width:i.width-d.padding*2,bottom:d.padding}).appendTo(D);break;case "float":n.css("left",parseInt((n.width()-i.width-40)/2,10)*-1).appendTo(f);break;default:n.css({width:i.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f)}}}n.hide();if(f.is(":visible")){b(E.add(z).add(A)).hide();a=f.position();r={top:a.top,left:a.left,width:f.width(),height:f.height()};c=r.width==i.width&&r.height==
-i.height;j.fadeTo(d.changeFade,0.3,function(){var g=function(){j.html(m.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");j.empty().removeAttr("filter").css({"border-width":d.padding,width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2});if(c)g();else{B.prop=0;b(B).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:g})}})}else{f.removeAttr("style");j.css("border-width",d.padding);if(d.transitionIn=="elastic"){r=V();j.html(m.contents());
-f.show();if(d.opacity)i.opacity=0;B.prop=0;b(B).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&y>0&&n.show();j.css({width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2}).html(m.contents());f.css(i).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},Y=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();b.fancybox.close()}else if((a.keyCode==
-37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&l.length>1||p!==0)z.show();if(d.cyclic&&l.length>1||p!=l.length-1)A.show()}else{z.hide();A.hide()}},S=function(){if(!b.support.opacity){j.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&j.css("height","auto");f.css("height","auto");
-s&&s.length&&n.show();d.showCloseButton&&E.show();Y();d.hideOnContentClick&&j.bind("click",b.fancybox.close);d.hideOnOverlayClick&&u.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" '+(b.browser.msie?'allowtransparency="true""':"")+' scrolling="'+e.scrolling+'" src="'+d.href+'"></iframe>').appendTo(j);
-f.show();h=false;b.fancybox.center();d.onComplete(l,p,d);var a,c;if(l.length-1>p){a=l[p+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(p>0){a=l[p-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(r.width+(i.width-r.width)*a,10),height:parseInt(r.height+(i.height-r.height)*a,10),top:parseInt(r.top+(i.top-r.top)*a,10),left:parseInt(r.left+(i.left-r.left)*a,10)};if(typeof i.opacity!=="undefined")c.opacity=a<0.5?0.5:a;f.css(c);
-j.css({width:c.width-d.padding*2,height:c.height-y*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},X=function(){var a=U(),c={},g=d.autoScale,k=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+k;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*parseFloat(d.height)/100,10):d.height+k;if(g&&(c.width>a[0]||c.height>a[1]))if(e.type==
-"image"||e.type=="swf"){g=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-k)/g+k,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-k)*g+k,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){c=a.offset();c.top+=parseInt(a.css("paddingTop"),
-10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();c={width:c.width+d.padding*2,height:c.height+d.padding*2,top:c.top-d.padding-20,left:c.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+a[0]*0.5,10)}}return c},Z=function(){if(t.is(":visible")){b("div",t).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)};
-b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!h){h=true;b(this).blur();o=[];q=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")o.push(this);else{o=b("a[rel="+c+"], area[rel="+c+"]");q=o.index(this)}I()}});return this};b.fancybox=function(a,c){var g;if(!h){h=true;g=typeof c!=="undefined"?c:{};o=[];q=parseInt(g.index,10)||0;if(b.isArray(a)){for(var k=
-0,C=a.length;k<C;k++)if(typeof a[k]=="object")b(a[k]).data("fancybox",b.extend({},g,a[k]));else a[k]=b({}).data("fancybox",b.extend({content:a[k]},g));o=jQuery.merge(o,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},g,a));else a=b({}).data("fancybox",b.extend({content:a},g));o.push(a)}if(q>o.length||q<0)q=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);t.show();K=setInterval(Z,66)};b.fancybox.hideActivity=function(){t.hide()};b.fancybox.next=function(){return b.fancybox.pos(p+
-1)};b.fancybox.prev=function(){return b.fancybox.pos(p-1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a);o=l;if(a>-1&&a<l.length){q=a;I()}else if(d.cyclic&&l.length>1){q=a>=l.length?0:l.length-1;I()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");N();e.onCancel(o,q,e);h=false}};b.fancybox.close=function(){function a(){u.fadeOut("fast");n.empty().hide();f.hide();b.event.trigger("fancybox-cleanup");j.empty();d.onClosed(l,p,d);l=e=[];p=q=0;d=e={};h=false}if(!(h||f.is(":hidden"))){h=
-true;if(d&&false===d.onCleanup(l,p,d))h=false;else{N();b(E.add(z).add(A)).hide();b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");j.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&n.empty();f.stop();if(d.transitionOut=="elastic"){r=V();var c=f.position();i={top:c.top,left:c.left,width:f.width(),height:f.height()};if(d.opacity)i.opacity=1;n.empty().hide();B.prop=1;
-b(B).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){u.is(":visible")&&u.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,g;if(!h){g=a===true?1:0;c=U();!g&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-20,c[3]+(c[1]-j.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-20,c[2]+(c[0]-j.width()-40)*0.5-
-d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('<div id="fancybox-tmp"></div>'),t=b('<div id="fancybox-loading"><div></div></div>'),u=b('<div id="fancybox-overlay"></div>'),f=b('<div id="fancybox-wrap"></div>'));D=b('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(f);
-D.append(j=b('<div id="fancybox-content"></div>'),E=b('<a id="fancybox-close"></a>'),n=b('<div id="fancybox-title"></div>'),z=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),A=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));E.click(b.fancybox.close);t.click(b.fancybox.cancel);z.click(function(a){a.preventDefault();b.fancybox.prev()});A.click(function(a){a.preventDefault();b.fancybox.next()});
-b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(h)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){t.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(D)}}};
-b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",
-easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery); \ No newline at end of file
+(function(B){var L,T,Q,M,d,m,J,A,O,z,C=0,H={},j=[],e=0,G={},y=[],f=null,o=new Image(),i=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,k=/[^\.]\.(swf)\s*$/i,p,N=1,h=0,t="",b,c,P=false,s=B.extend(B("<div/>")[0],{prop:0}),S=B.browser.msie&&B.browser.version<7&&!window.XMLHttpRequest,r=function(){T.hide();o.onerror=o.onload=null;if(f){f.abort()}L.empty()},x=function(){if(false===H.onError(j,C,H)){T.hide();P=false;return}H.titleShow=false;H.width="auto";H.height="auto";L.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');n()},w=function(){var Z=j[C],W,Y,ab,aa,V,X;r();H=B.extend({},B.fn.fancybox.defaults,(typeof B(Z).data("fancybox")=="undefined"?H:B(Z).data("fancybox")));X=H.onStart(j,C,H);if(X===false){P=false;return}else{if(typeof X=="object"){H=B.extend(H,X)}}ab=H.title||(Z.nodeName?B(Z).attr("title"):Z.title)||"";if(Z.nodeName&&!H.orig){H.orig=B(Z).children("img:first").length?B(Z).children("img:first"):B(Z)}if(ab===""&&H.orig&&H.titleFromAlt){ab=H.orig.attr("alt")}ab=ab.replace(/</,"&lt;").replace(/>/,"&gt;");W=H.href||(Z.nodeName?B(Z).attr("href"):Z.href)||null;if((/^(?:javascript)/i).test(W)||W=="#"){W=null}if(H.type){Y=H.type;if(!W){W=H.content}}else{if(H.content){Y="html"}else{if(W){if(W.match(i)){Y="image"}else{if(W.match(k)){Y="swf"}else{if(B(Z).hasClass("iframe")){Y="iframe"}else{if(W.indexOf("#")===0){Y="inline"}else{Y="ajax"}}}}}}}if(!Y){x();return}if(Y=="inline"){Z=W.substr(W.indexOf("#"));Y=B(Z).length>0?"inline":"ajax"}H.type=Y;H.href=W;H.title=ab;if(H.autoDimensions){if(H.type=="html"||H.type=="inline"||H.type=="ajax"){H.width="auto";H.height="auto"}else{H.autoDimensions=false}}if(H.modal){H.overlayShow=true;H.hideOnOverlayClick=false;H.hideOnContentClick=false;H.enableEscapeButton=false;H.showCloseButton=false}H.padding=parseInt(H.padding,10);H.margin=parseInt(H.margin,10);L.css("padding",(H.padding+H.margin));B(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){B(this).replaceWith(m.children())});switch(Y){case"html":L.html(H.content);n();break;case"inline":if(B(Z).parent().is("#fancybox-content")===true){P=false;return}B('<div class="fancybox-inline-tmp" />').hide().insertBefore(B(Z)).bind("fancybox-cleanup",function(){B(this).replaceWith(m.children())}).bind("fancybox-cancel",function(){B(this).replaceWith(L.children())});B(Z).appendTo(L);n();break;case"image":P=false;B.fancybox.showActivity();o=new Image();o.onerror=function(){x()};o.onload=function(){P=true;o.onerror=o.onload=null;F()};o.src=W;break;case"swf":H.scrolling="no";aa='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+H.width+'" height="'+H.height+'"><param name="movie" value="'+W+'"></param>';V="";B.each(H.swf,function(ac,ad){aa+='<param name="'+ac+'" value="'+ad+'"></param>';V+=" "+ac+'="'+ad+'"'});aa+='<embed src="'+W+'" type="application/x-shockwave-flash" width="'+H.width+'" height="'+H.height+'"'+V+"></embed></object>";L.html(aa);n();break;case"ajax":P=false;B.fancybox.showActivity();H.ajax.win=H.ajax.success;f=B.ajax(B.extend({},H.ajax,{url:W,data:H.ajax.data||{},error:function(ac,ae,ad){if(ac.status>0){x()}},success:function(ad,af,ac){var ae=typeof ac=="object"?ac:f;if(ae.status==200){if(typeof H.ajax.win=="function"){X=H.ajax.win(W,ad,af,ac);if(X===false){T.hide();return}else{if(typeof X=="string"||typeof X=="object"){ad=X}}}L.html(ad);n()}}}));break;case"iframe":E();break}},n=function(){var V=H.width,W=H.height;if(V.toString().indexOf("%")>-1){V=parseInt((B(window).width()-(H.margin*2))*parseFloat(V)/100,10)+"px"}else{V=V=="auto"?"auto":V+"px"}if(W.toString().indexOf("%")>-1){W=parseInt((B(window).height()-(H.margin*2))*parseFloat(W)/100,10)+"px"}else{W=W=="auto"?"auto":W+"px"}L.wrapInner('<div style="width:'+V+";height:"+W+";overflow: "+(H.scrolling=="auto"?"auto":(H.scrolling=="yes"?"scroll":"hidden"))+';position:relative;"></div>');H.width=L.width();H.height=L.height();E()},F=function(){H.width=o.width;H.height=o.height;B("<img />").attr({id:"fancybox-img",src:o.src,alt:H.title}).appendTo(L);E()},E=function(){var W,V;T.hide();if(M.is(":visible")&&false===G.onCleanup(y,e,G)){B.event.trigger("fancybox-cancel");P=false;return}P=true;B(m.add(Q)).unbind();B(window).unbind("resize.fb scroll.fb");B(document).unbind("keydown.fb");if(M.is(":visible")&&G.titlePosition!=="outside"){M.css("height",M.height())}y=j;e=C;G=H;if(G.overlayShow){Q.css({"background-color":G.overlayColor,opacity:G.overlayOpacity,cursor:G.hideOnOverlayClick?"pointer":"auto",height:B(document).height()});if(!Q.is(":visible")){if(S){B("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"})}Q.show()}}else{Q.hide()}c=R();l();if(M.is(":visible")){B(J.add(O).add(z)).hide();W=M.position(),b={top:W.top,left:W.left,width:M.width(),height:M.height()};V=(b.width==c.width&&b.height==c.height);m.fadeTo(G.changeFade,0.3,function(){var X=function(){m.html(L.contents()).fadeTo(G.changeFade,1,v)};B.event.trigger("fancybox-change");m.empty().removeAttr("filter").css({"border-width":G.padding,width:c.width-G.padding*2,height:H.autoDimensions?"auto":c.height-h-G.padding*2});if(V){X()}else{s.prop=0;B(s).animate({prop:1},{duration:G.changeSpeed,easing:G.easingChange,step:U,complete:X})}});return}M.removeAttr("style");m.css("border-width",G.padding);if(G.transitionIn=="elastic"){b=I();m.html(L.contents());M.show();if(G.opacity){c.opacity=0}s.prop=0;B(s).animate({prop:1},{duration:G.speedIn,easing:G.easingIn,step:U,complete:v});return}if(G.titlePosition=="inside"&&h>0){A.show()}m.css({width:c.width-G.padding*2,height:H.autoDimensions?"auto":c.height-h-G.padding*2}).html(L.contents());M.css(c).fadeIn(G.transitionIn=="none"?0:G.speedIn,v)},D=function(V){if(V&&V.length){if(G.titlePosition=="float"){return'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+V+'</td><td id="fancybox-title-float-right"></td></tr></table>'}return'<div id="fancybox-title-'+G.titlePosition+'">'+V+"</div>"}return false},l=function(){t=G.title||"";h=0;A.empty().removeAttr("style").removeClass();if(G.titleShow===false){A.hide();return}t=B.isFunction(G.titleFormat)?G.titleFormat(t,y,e,G):D(t);if(!t||t===""){A.hide();return}A.addClass("fancybox-title-"+G.titlePosition).html(t).appendTo("body").show();switch(G.titlePosition){case"inside":A.css({width:c.width-(G.padding*2),marginLeft:G.padding,marginRight:G.padding});h=A.outerHeight(true);A.appendTo(d);c.height+=h;break;case"over":A.css({marginLeft:G.padding,width:c.width-(G.padding*2),bottom:G.padding}).appendTo(d);break;case"float":A.css("left",parseInt((A.width()-c.width-40)/2,10)*-1).appendTo(M);break;default:A.css({width:c.width-(G.padding*2),paddingLeft:G.padding,paddingRight:G.padding}).appendTo(M);break}A.hide()},g=function(){if(G.enableEscapeButton||G.enableKeyboardNav){B(document).bind("keydown.fb",function(V){if(V.keyCode==27&&G.enableEscapeButton){V.preventDefault();B.fancybox.close()}else{if((V.keyCode==37||V.keyCode==39)&&G.enableKeyboardNav&&V.target.tagName!=="INPUT"&&V.target.tagName!=="TEXTAREA"&&V.target.tagName!=="SELECT"){V.preventDefault();B.fancybox[V.keyCode==37?"prev":"next"]()}}})}if(!G.showNavArrows){O.hide();z.hide();return}if((G.cyclic&&y.length>1)||e!==0){O.show()}if((G.cyclic&&y.length>1)||e!=(y.length-1)){z.show()}},v=function(){if(!B.support.opacity){m.get(0).style.removeAttribute("filter");M.get(0).style.removeAttribute("filter")}if(H.autoDimensions){m.css("height","auto")}M.css("height","auto");if(t&&t.length){A.show()}if(G.showCloseButton){J.show()}g();if(G.hideOnContentClick){m.bind("click",B.fancybox.close)}if(G.hideOnOverlayClick){Q.bind("click",B.fancybox.close)}B(window).bind("resize.fb",B.fancybox.resize);if(G.centerOnScroll){B(window).bind("scroll.fb",B.fancybox.center)}if(G.type=="iframe"){B('<iframe id="fancybox-frame" name="fancybox-frame'+new Date().getTime()+'" frameborder="0" hspace="0" '+(B.browser.msie?'allowtransparency="true""':"")+' scrolling="'+H.scrolling+'" src="'+G.href+'"></iframe>').appendTo(m)}M.show();P=false;B.fancybox.center();G.onComplete(y,e,G);K()},K=function(){var V,W;if((y.length-1)>e){V=y[e+1].href;if(typeof V!=="undefined"&&V.match(i)){W=new Image();W.src=V}}if(e>0){V=y[e-1].href;if(typeof V!=="undefined"&&V.match(i)){W=new Image();W.src=V}}},U=function(W){var V={width:parseInt(b.width+(c.width-b.width)*W,10),height:parseInt(b.height+(c.height-b.height)*W,10),top:parseInt(b.top+(c.top-b.top)*W,10),left:parseInt(b.left+(c.left-b.left)*W,10)};if(typeof c.opacity!=="undefined"){V.opacity=W<0.5?0.5:W}M.css(V);m.css({width:V.width-G.padding*2,height:V.height-(h*W)-G.padding*2})},u=function(){return[B(window).width()-(G.margin*2),B(window).height()-(G.margin*2),B(document).scrollLeft()+G.margin,B(document).scrollTop()+G.margin]},R=function(){var V=u(),Z={},W=G.autoScale,X=G.padding*2,Y;if(G.width.toString().indexOf("%")>-1){Z.width=parseInt((V[0]*parseFloat(G.width))/100,10)}else{Z.width=G.width+X}if(G.height.toString().indexOf("%")>-1){Z.height=parseInt((V[1]*parseFloat(G.height))/100,10)}else{Z.height=G.height+X}if(W&&(Z.width>V[0]||Z.height>V[1])){if(H.type=="image"||H.type=="swf"){Y=(G.width)/(G.height);if((Z.width)>V[0]){Z.width=V[0];Z.height=parseInt(((Z.width-X)/Y)+X,10)}if((Z.height)>V[1]){Z.height=V[1];Z.width=parseInt(((Z.height-X)*Y)+X,10)}}else{Z.width=Math.min(Z.width,V[0]);Z.height=Math.min(Z.height,V[1])}}Z.top=parseInt(Math.max(V[3]-20,V[3]+((V[1]-Z.height-40)*0.5)),10);Z.left=parseInt(Math.max(V[2]-20,V[2]+((V[0]-Z.width-40)*0.5)),10);return Z},q=function(V){var W=V.offset();W.top+=parseInt(V.css("paddingTop"),10)||0;W.left+=parseInt(V.css("paddingLeft"),10)||0;W.top+=parseInt(V.css("border-top-width"),10)||0;W.left+=parseInt(V.css("border-left-width"),10)||0;W.width=V.width();W.height=V.height();return W},I=function(){var Y=H.orig?B(H.orig):false,X={},W,V;if(Y&&Y.length){W=q(Y);X={width:W.width+(G.padding*2),height:W.height+(G.padding*2),top:W.top-G.padding-20,left:W.left-G.padding-20}}else{V=u();X={width:G.padding*2,height:G.padding*2,top:parseInt(V[3]+V[1]*0.5,10),left:parseInt(V[2]+V[0]*0.5,10)}}return X},a=function(){if(!T.is(":visible")){clearInterval(p);return}B("div",T).css("top",(N*-40)+"px");N=(N+1)%12};B.fn.fancybox=function(V){if(!B(this).length){return this}B(this).data("fancybox",B.extend({},V,(B.metadata?B(this).metadata():{}))).unbind("click.fb").bind("click.fb",function(X){X.preventDefault();if(P){return}P=true;B(this).blur();j=[];C=0;var W=B(this).attr("rel")||"";if(!W||W==""||W==="nofollow"){j.push(this)}else{j=B("a[rel="+W+"], area[rel="+W+"]");C=j.index(this)}w();return});return this};B.fancybox=function(Y){var X;if(P){return}P=true;X=typeof arguments[1]!=="undefined"?arguments[1]:{};j=[];C=parseInt(X.index,10)||0;if(B.isArray(Y)){for(var W=0,V=Y.length;W<V;W++){if(typeof Y[W]=="object"){B(Y[W]).data("fancybox",B.extend({},X,Y[W]))}else{Y[W]=B({}).data("fancybox",B.extend({content:Y[W]},X))}}j=jQuery.merge(j,Y)}else{if(typeof Y=="object"){B(Y).data("fancybox",B.extend({},X,Y))}else{Y=B({}).data("fancybox",B.extend({content:Y},X))}j.push(Y)}if(C>j.length||C<0){C=0}w()};B.fancybox.showActivity=function(){clearInterval(p);T.show();p=setInterval(a,66)};B.fancybox.hideActivity=function(){T.hide()};B.fancybox.next=function(){return B.fancybox.pos(e+1)};B.fancybox.prev=function(){return B.fancybox.pos(e-1)};B.fancybox.pos=function(V){if(P){return}V=parseInt(V);j=y;if(V>-1&&V<y.length){C=V;w()}else{if(G.cyclic&&y.length>1){C=V>=y.length?0:y.length-1;w()}}return};B.fancybox.cancel=function(){if(P){return}P=true;B.event.trigger("fancybox-cancel");r();H.onCancel(j,C,H);P=false};B.fancybox.close=function(){if(P||M.is(":hidden")){return}P=true;if(G&&false===G.onCleanup(y,e,G)){P=false;return}r();B(J.add(O).add(z)).hide();B(m.add(Q)).unbind();B(window).unbind("resize.fb scroll.fb");B(document).unbind("keydown.fb");m.find("iframe").attr("src",S&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");if(G.titlePosition!=="inside"){A.empty()}M.stop();function V(){Q.fadeOut("fast");A.empty().hide();M.hide();B.event.trigger("fancybox-cleanup");m.empty();G.onClosed(y,e,G);y=H=[];e=C=0;G=H={};P=false}if(G.transitionOut=="elastic"){b=I();var W=M.position();c={top:W.top,left:W.left,width:M.width(),height:M.height()};if(G.opacity){c.opacity=1}A.empty().hide();s.prop=1;B(s).animate({prop:0},{duration:G.speedOut,easing:G.easingOut,step:U,complete:V})}else{M.fadeOut(G.transitionOut=="none"?0:G.speedOut,V)}};B.fancybox.resize=function(){if(Q.is(":visible")){Q.css("height",B(document).height())}B.fancybox.center(true)};B.fancybox.center=function(){var V,W;if(P){return}W=arguments[0]===true?1:0;V=u();if(!W&&(M.width()>V[0]||M.height()>V[1])){return}M.stop().animate({top:parseInt(Math.max(V[3]-20,V[3]+((V[1]-m.height()-40)*0.5)-G.padding)),left:parseInt(Math.max(V[2]-20,V[2]+((V[0]-m.width()-40)*0.5)-G.padding))},typeof arguments[0]=="number"?arguments[0]:200)};B.fancybox.init=function(){if(B("#fancybox-wrap").length){return}B("body").append(L=B('<div id="fancybox-tmp"></div>'),T=B('<div id="fancybox-loading"><div></div></div>'),Q=B('<div id="fancybox-overlay"></div>'),M=B('<div id="fancybox-wrap"></div>'));d=B('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(M);d.append(m=B('<div id="fancybox-content"></div>'),J=B('<a id="fancybox-close"></a>'),A=B('<div id="fancybox-title"></div>'),O=B('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),z=B('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));J.click(B.fancybox.close);T.click(B.fancybox.cancel);O.click(function(V){V.preventDefault();B.fancybox.prev()});z.click(function(V){V.preventDefault();B.fancybox.next()});if(B.fn.mousewheel){M.bind("mousewheel.fb",function(V,W){if(P){V.preventDefault()}else{if(B(V.target).get(0).clientHeight==0||B(V.target).get(0).scrollHeight===B(V.target).get(0).clientHeight){V.preventDefault();B.fancybox[W>0?"prev":"next"]()}}})}if(!B.support.opacity){M.addClass("fancybox-ie")}if(S){T.addClass("fancybox-ie6");M.addClass("fancybox-ie6");B('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(d)}};B.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};B(document).ready(function(){B.fancybox.init()})})(jQuery); \ No newline at end of file
diff --git a/apps/files_pdfviewer/appinfo/app.php b/apps/files_pdfviewer/appinfo/app.php
index 06b15670674..c8ca2dc8d94 100644
--- a/apps/files_pdfviewer/appinfo/app.php
+++ b/apps/files_pdfviewer/appinfo/app.php
@@ -1,7 +1,9 @@
<?php
//load the required files
-OCP\Util::addscript( 'files_pdfviewer', 'viewer');
OCP\Util::addStyle( 'files_pdfviewer', 'viewer');
+
+OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/compatibility');
+OCP\Util::addscript( 'files_pdfviewer', 'viewer');
OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/build/pdf');
-OCP\Util::addscript( 'files_pdfviewer', 'pdfview');
+OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/viewer');
?>
diff --git a/apps/files_pdfviewer/appinfo/info.xml b/apps/files_pdfviewer/appinfo/info.xml
index e3813be1001..074962f57fb 100644
--- a/apps/files_pdfviewer/appinfo/info.xml
+++ b/apps/files_pdfviewer/appinfo/info.xml
@@ -4,7 +4,7 @@
<name>PDF Viewer</name>
<description>Inline PDF viewer (pdfjs-based)</description>
<licence>GPL</licence>
- <author>Joan Creus</author>
+ <author>Joan Creus, Thomas Müller</author>
<require>4</require>
<shipped>true</shipped>
<default_enable/>
diff --git a/apps/files_pdfviewer/css/viewer.css b/apps/files_pdfviewer/css/viewer.css
index b735dbfedfc..f9ce929d8b8 100644
--- a/apps/files_pdfviewer/css/viewer.css
+++ b/apps/files_pdfviewer/css/viewer.css
@@ -2,7 +2,6 @@
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
#viewer {
- background-color: #929292;
font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif;
/*margin: 0px;*/
padding: 0px;
diff --git a/apps/files_pdfviewer/js/pdfjs/build/pdf.js b/apps/files_pdfviewer/js/pdfjs/build/pdf.js
index a19a9b75fea..b1fc9d9747e 100644
--- a/apps/files_pdfviewer/js/pdfjs/build/pdf.js
+++ b/apps/files_pdfviewer/js/pdfjs/build/pdf.js
@@ -7,10 +7,9 @@ var PDFJS = {};
// Use strict in our context only - users might not want it
'use strict';
- PDFJS.build = 'd823592';
+ PDFJS.build = '2aae4fd';
// Files are inserted below - see Makefile
- /* PDFJSSCRIPT_INCLUDE_ALL */
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -20,7 +19,7 @@ var globalScope = (typeof window === 'undefined') ? this : window;
var isWorker = (typeof window == 'undefined');
-var ERRORS = 0, WARNINGS = 1, TODOS = 5;
+var ERRORS = 0, WARNINGS = 1, INFOS = 5;
var verbosity = WARNINGS;
// The global PDFJS object exposes the API
@@ -44,7 +43,19 @@ function getPdf(arg, callback) {
params = { url: arg };
var xhr = new XMLHttpRequest();
+
xhr.open('GET', params.url);
+
+ var headers = params.headers;
+ if (headers) {
+ for (var property in headers) {
+ if (typeof headers[property] === 'undefined')
+ continue;
+
+ xhr.setRequestHeader(property, params.headers[property]);
+ }
+ }
+
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
params.url.substring(0, params.url.indexOf(':') + 1);
@@ -76,8 +87,6 @@ var Page = (function PageClosure() {
function Page(xref, pageNumber, pageDict, ref) {
this.pageNumber = pageNumber;
this.pageDict = pageDict;
- this.stats = new StatTimer();
- this.stats.enabled = !!globalScope.PDFJS.enableStats;
this.xref = xref;
this.ref = ref;
@@ -113,18 +122,10 @@ var Page = (function PageClosure() {
return shadow(this, 'mediaBox', obj);
},
get view() {
+ var mediaBox = this.mediaBox;
var cropBox = this.inheritPageProp('CropBox');
- var view = {
- x: 0,
- y: 0,
- width: this.width,
- height: this.height
- };
if (!isArray(cropBox) || cropBox.length !== 4)
- return shadow(this, 'view', view);
-
- var mediaBox = this.mediaBox;
- var offsetX = mediaBox[0], offsetY = mediaBox[1];
+ return shadow(this, 'view', mediaBox);
// From the spec, 6th ed., p.963:
// "The crop, bleed, trim, and art boxes should not ordinarily
@@ -132,42 +133,13 @@ var Page = (function PageClosure() {
// 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', mediaBox);
- return shadow(this, 'view', view);
+ return shadow(this, 'view', cropBox);
},
get annotations() {
return shadow(this, 'annotations', this.inheritPageProp('Annots'));
},
- get width() {
- var mediaBox = this.mediaBox;
- var rotate = this.rotate;
- var width;
- if (rotate == 0 || rotate == 180) {
- width = (mediaBox[2] - mediaBox[0]);
- } else {
- width = (mediaBox[3] - mediaBox[1]);
- }
- return shadow(this, 'width', width);
- },
- get height() {
- var mediaBox = this.mediaBox;
- var rotate = this.rotate;
- var height;
- if (rotate == 0 || rotate == 180) {
- height = (mediaBox[3] - mediaBox[1]);
- } else {
- height = (mediaBox[2] - mediaBox[0]);
- }
- return shadow(this, 'height', height);
- },
get rotate() {
var rotate = this.inheritPageProp('Rotate') || 0;
// Normalize rotation so it's a multiple of 90 and between 0 and 270
@@ -183,43 +155,20 @@ var Page = (function PageClosure() {
return shadow(this, 'rotate', rotate);
},
- startRenderingFromOperatorList:
- function Page_startRenderingFromOperatorList(operatorList, fonts) {
- var self = this;
- 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() {
- self.displayReadyPromise.resolve();
- });
- };
-
- this.ensureFonts(fonts,
- function pageStartRenderingFromOperatorListEnsureFonts() {
- displayContinuation();
- }
- );
- },
-
getOperatorList: function Page_getOperatorList(handler, dependency) {
- if (this.operatorList) {
- // content was compiled
- return this.operatorList;
- }
-
- this.stats.time('Build IR Queue');
-
var xref = this.xref;
var content = this.content;
var resources = this.resources;
if (isArray(content)) {
// fetching items
+ var streams = [];
var i, n = content.length;
+ var streams = [];
for (i = 0; i < n; ++i)
- content[i] = xref.fetchIfRef(content[i]);
- content = new StreamsSequenceStream(content);
+ streams.push(xref.fetchIfRef(content[i]));
+ content = new StreamsSequenceStream(streams);
+ } else if (isStream(content)) {
+ content.reset();
} else if (!content) {
// replacing non-existent page content with empty one
content = new Stream(new Uint8Array(0));
@@ -228,9 +177,31 @@ var Page = (function PageClosure() {
var pe = this.pe = new PartialEvaluator(
xref, handler, 'p' + this.pageNumber + '_');
- this.operatorList = pe.getOperatorList(content, resources, dependency);
- this.stats.timeEnd('Build IR Queue');
- return this.operatorList;
+ return pe.getOperatorList(content, resources, dependency);
+ },
+ extractTextContent: function Page_extractTextContent() {
+ var handler = {
+ on: function nullHandlerOn() {},
+ send: function nullHandlerSend() {}
+ };
+
+ var xref = this.xref;
+ var content = xref.fetchIfRef(this.content);
+ var resources = xref.fetchIfRef(this.resources);
+ if (isArray(content)) {
+ // fetching items
+ var i, n = content.length;
+ var streams = [];
+ for (i = 0; i < n; ++i)
+ streams.push(xref.fetchIfRef(content[i]));
+ content = new StreamsSequenceStream(streams);
+ } else if (isStream(content)) {
+ content.reset();
+ }
+
+ var pe = new PartialEvaluator(
+ xref, handler, 'p' + this.pageNumber + '_');
+ return pe.getTextContent(content, resources);
},
ensureFonts: function Page_ensureFonts(fonts, callback) {
@@ -250,60 +221,6 @@ var Page = (function PageClosure() {
}.bind(this)
);
},
-
- display: function Page_display(gfx, callback) {
- var stats = this.stats;
- stats.time('Rendering');
- var xref = this.xref;
- var resources = this.resources;
- var mediaBox = this.mediaBox;
- assertWellFormed(isDict(resources), 'invalid page resources');
-
- gfx.xref = xref;
- gfx.res = resources;
- gfx.beginDrawing({ x: mediaBox[0], y: mediaBox[1],
- width: this.width,
- height: this.height,
- rotate: this.rotate });
-
- var startIdx = 0;
- 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.executeOperatorList(operatorList, startIdx, next, stepper);
- if (startIdx == length) {
- gfx.endDrawing();
- stats.timeEnd('Rendering');
- stats.timeEnd('Overall');
- if (callback) callback();
- }
- }
- next();
- },
- rotatePoint: function Page_rotatePoint(x, y, reverse) {
- var rotate = reverse ? (360 - this.rotate) : this.rotate;
- switch (rotate) {
- case 180:
- return {x: this.width - x, y: y};
- case 90:
- return {x: this.width - y, y: this.height - x};
- case 270:
- return {x: y, y: x};
- case 360:
- case 0:
- default:
- return {x: x, y: this.height - y};
- }
- },
getLinks: function Page_getLinks() {
var links = [];
var annotations = pageGetAnnotations();
@@ -337,6 +254,7 @@ var Page = (function PageClosure() {
case 'http':
case 'https':
case 'ftp':
+ case 'mailto':
return true;
default:
return false;
@@ -355,15 +273,10 @@ var Page = (function PageClosure() {
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 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);
+ item.rect = rect;
switch (subtype.name) {
case 'Link':
var a = annotation.get('A');
@@ -437,7 +350,8 @@ var Page = (function PageClosure() {
var title = annotation.get('T');
item.content = stringToPDFString(content || '');
item.title = stringToPDFString(title || '');
- item.name = annotation.get('Name').name;
+ item.name = !annotation.has('Name') ? 'Note' :
+ annotation.get('Name').name;
break;
default:
TODO('unimplemented annotation type: ' + subtype.name);
@@ -446,37 +360,6 @@ var Page = (function PageClosure() {
items.push(item);
}
return items;
- },
- 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);
- }
- );
}
};
@@ -484,26 +367,26 @@ var Page = (function PageClosure() {
})();
/**
- * The `PDFDocModel` holds all the data of the PDF file. Compared to the
+ * The `PDFDocument` holds all the data of the PDF file. Compared to the
* `PDFDoc`, this one doesn't have any job management code.
- * Right now there exists one PDFDocModel on the main thread + one object
+ * Right now there exists one PDFDocument 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.
+ * `PDFDocument` objects on the main thread created.
*/
-var PDFDocModel = (function PDFDocModelClosure() {
- function PDFDocModel(arg, callback) {
+var PDFDocument = (function PDFDocumentClosure() {
+ function PDFDocument(arg, password) {
if (isStream(arg))
- init.call(this, arg);
+ init.call(this, arg, password);
else if (isArrayBuffer(arg))
- init.call(this, new Stream(arg));
+ init.call(this, new Stream(arg), password);
else
- error('PDFDocModel: Unknown argument type');
+ error('PDFDocument: Unknown argument type');
}
- function init(stream) {
+ function init(stream, password) {
assertWellFormed(stream.length > 0, 'stream must have data');
this.stream = stream;
- this.setup();
+ this.setup(password);
this.acroForm = this.catalog.catDict.get('AcroForm');
}
@@ -523,7 +406,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
return true; /* found */
}
- PDFDocModel.prototype = {
+ PDFDocument.prototype = {
get linearization() {
var length = this.stream.length;
var linearization = false;
@@ -584,7 +467,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
},
// Find the header, remove leading garbage and setup the stream
// starting from the header.
- checkHeader: function PDFDocModel_checkHeader() {
+ checkHeader: function PDFDocument_checkHeader() {
var stream = this.stream;
stream.reset();
if (find(stream, '%PDF-', 1024)) {
@@ -594,11 +477,12 @@ var PDFDocModel = (function PDFDocModelClosure() {
}
// May not be a PDF file, continue anyway.
},
- setup: function PDFDocModel_setup(ownerPassword, userPassword) {
+ setup: function PDFDocument_setup(password) {
this.checkHeader();
var xref = new XRef(this.stream,
this.startXRef,
- this.mainXRefEntriesOffset);
+ this.mainXRefEntriesOffset,
+ password);
this.xref = xref;
this.catalog = new Catalog(xref);
},
@@ -608,7 +492,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
// shadow the prototype getter
return shadow(this, 'numPages', num);
},
- getDocumentInfo: function PDFDocModel_getDocumentInfo() {
+ getDocumentInfo: function PDFDocument_getDocumentInfo() {
var info;
if (this.xref.trailer.has('Info')) {
var infoDict = this.xref.trailer.get('Info');
@@ -622,7 +506,7 @@ var PDFDocModel = (function PDFDocModelClosure() {
return shadow(this, 'getDocumentInfo', info);
},
- getFingerprint: function PDFDocModel_getFingerprint() {
+ getFingerprint: function PDFDocument_getFingerprint() {
var xref = this.xref, fileID;
if (xref.trailer.has('ID')) {
fileID = '';
@@ -643,259 +527,22 @@ var PDFDocModel = (function PDFDocModelClosure() {
return shadow(this, 'getFingerprint', fileID);
},
- getPage: function PDFDocModel_getPage(n) {
+ getPage: function PDFDocument_getPage(n) {
return this.catalog.getPage(n);
}
};
- return PDFDocModel;
+ return PDFDocument;
})();
-var PDFDoc = (function PDFDocClosure() {
- function PDFDoc(arg, callback) {
- var stream = null;
- var data = null;
-
- if (isStream(arg)) {
- stream = arg;
- data = arg.bytes;
- } else if (isArrayBuffer(arg)) {
- stream = new Stream(arg);
- data = arg;
- } else {
- error('PDFDoc: Unknown argument type');
- }
-
- this.data = data;
- this.stream = stream;
- 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 = [];
- this.fontsLoading = {};
- this.workerReadyPromise = new Promise('workerReady');
-
- // If worker support isn't disabled explicit and the browser has worker
- // support, create a new web worker and test if it/the browser fullfills
- // all requirements to run parts of pdf.js in a web worker.
- // Right now, the requirement is, that an Uint8Array is still an Uint8Array
- // as it arrives on the worker. Chrome added this with version 15.
- if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
- var workerSrc = PDFJS.workerSrc;
- if (typeof workerSrc === 'undefined') {
- error('No PDFJS.workerSrc specified');
- }
-
- try {
- 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 {
- // 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);
- }
-
- 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();
- }
-
- PDFDoc.prototype = {
- setupFakeWorker: function PDFDoc_setupFakeWorker() {
- // If we don't use a worker, just post/sendMessage to the main thread.
- var fakeWorker = {
- postMessage: function PDFDoc_postMessage(obj) {
- fakeWorker.onmessage({data: obj});
- },
- terminate: function PDFDoc_terminate() {}
- };
-
- var messageHandler = new MessageHandler('main', fakeWorker);
- this.setupMessageHandler(messageHandler);
-
- // If the main thread is our worker, setup the handling for the messages
- // the main thread sends to it self.
- WorkerMessageHandler.setup(messageHandler);
- },
-
-
- setupMessageHandler: function PDFDoc_setupMessageHandler(messageHandler) {
- this.messageHandler = messageHandler;
-
- messageHandler.on('page', function pdfDocPage(data) {
- var pageNum = data.pageNum;
- var page = this.pageCache[pageNum];
- var depFonts = data.depFonts;
-
- page.stats.timeEnd('Page Request');
- page.startRenderingFromOperatorList(data.operatorList, depFonts);
- }, this);
-
- messageHandler.on('obj', function pdfDocObj(data) {
- var id = data[0];
- var type = data[1];
-
- switch (type) {
- case 'JpegStream':
- 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];
- var file = data[3];
- var properties = data[4];
-
- if (file) {
- // Rewrap the ArrayBuffer in a stream.
- var fontFileDict = new Dict();
- file = new Stream(file, 0, file.length, fontFileDict);
- }
-
- // 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:
- error('Got unkown object type ' + type);
- }
- }, this);
-
- 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);
-
- 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);
- this.workerReadyPromise.resolve(true);
- }.bind(this));
- },
-
- get numPages() {
- return this.pdfModel.numPages;
- },
-
- 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 PDFDoc_getPage(n) {
- if (this.pageCache[n])
- return this.pageCache[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;
- page.pdf = this;
- return (this.pageCache[n] = page);
- },
-
- destroy: function PDFDoc_destroy() {
- if (this.worker)
- this.worker.terminate();
-
- if (this.fontWorker)
- this.fontWorker.terminate();
-
- for (var n in this.pageCache)
- delete this.pageCache[n];
-
- delete this.data;
- delete this.stream;
- delete this.pdf;
- delete this.catalog;
- }
- };
-
- return PDFDoc;
-})();
-
-globalScope.PDFJS.PDFDoc = PDFDoc;
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
+// Use only for debugging purposes. This should not be used in any code that is
+// in mozilla master.
function log(msg) {
if (console && console.log)
console.log(msg);
@@ -903,32 +550,44 @@ function log(msg) {
print(msg);
}
-function warn(msg) {
- if (verbosity >= WARNINGS)
- log('Warning: ' + msg);
+// A notice for devs that will not trigger the fallback UI. These are good
+// for things that are helpful to devs, such as warning that Workers were
+// disabled, which is important to devs but not end users.
+function info(msg) {
+ if (verbosity >= INFOS) {
+ log('Info: ' + msg);
+ PDFJS.LogManager.notify('info', msg);
+ }
}
-function backtrace() {
- try {
- throw new Error();
- } catch (e) {
- return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
+// Non-fatal warnings that should trigger the fallback UI.
+function warn(msg) {
+ if (verbosity >= WARNINGS) {
+ log('Warning: ' + msg);
+ PDFJS.LogManager.notify('warn', msg);
}
}
+// Fatal errors that should trigger the fallback UI and halt execution by
+// throwing an exception.
function error(msg) {
log('Error: ' + msg);
log(backtrace());
+ PDFJS.LogManager.notify('error', msg);
throw new Error(msg);
}
+// Missing features that should trigger the fallback UI.
function TODO(what) {
- if (verbosity >= TODOS)
- log('TODO: ' + what);
+ warn('TODO: ' + what);
}
-function malformed(msg) {
- error('Malformed PDF: ' + msg);
+function backtrace() {
+ try {
+ throw new Error();
+ } catch (e) {
+ return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
+ }
}
function assert(cond, msg) {
@@ -940,9 +599,25 @@ function assert(cond, msg) {
// behavior is undefined.
function assertWellFormed(cond, msg) {
if (!cond)
- malformed(msg);
+ error(msg);
}
+var LogManager = PDFJS.LogManager = (function LogManagerClosure() {
+ var loggers = [];
+ return {
+ addLogger: function logManager_addLogger(logger) {
+ loggers.push(logger);
+ },
+ notify: function(type, message) {
+ for (var i = 0, ii = loggers.length; i < ii; i++) {
+ var logger = loggers[i];
+ if (logger[type])
+ logger[type](message);
+ }
+ }
+ };
+})();
+
function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value,
enumerable: true,
@@ -951,6 +626,19 @@ function shadow(obj, prop, value) {
return value;
}
+var PasswordException = (function PasswordExceptionClosure() {
+ function PasswordException(msg, code) {
+ this.name = 'PasswordException';
+ this.message = msg;
+ this.code = code;
+ }
+
+ PasswordException.prototype = new Error();
+ PasswordException.constructor = PasswordException;
+
+ return PasswordException;
+})();
+
function bytesToString(bytes) {
var str = '';
var length = bytes.length;
@@ -969,7 +657,7 @@ function stringToBytes(str) {
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
-var Util = (function UtilClosure() {
+var Util = PDFJS.Util = (function UtilClosure() {
function Util() {}
Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
@@ -990,6 +678,19 @@ var Util = (function UtilClosure() {
return [xt, yt];
};
+ Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ };
+
+ Util.inverseTransform = function Util_inverseTransform(m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
+ (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+ };
+
// Apply a generic 3d matrix M on a 3-vector v:
// | a b c | | X |
// | d e f | x | Y |
@@ -1058,7 +759,7 @@ var Util = (function UtilClosure() {
}
return result;
- }
+ };
Util.sign = function Util_sign(num) {
return num < 0 ? -1 : 1;
@@ -1067,6 +768,80 @@ var Util = (function UtilClosure() {
return Util;
})();
+var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
+ function PageViewport(viewBox, scale, rotate, offsetX, offsetY) {
+ // creating transform to convert pdf coordinate system to the normal
+ // canvas like coordinates taking in account scale and rotation
+ var centerX = (viewBox[2] + viewBox[0]) / 2;
+ var centerY = (viewBox[3] + viewBox[1]) / 2;
+ var rotateA, rotateB, rotateC, rotateD;
+ switch (rotate) {
+ case -180:
+ case 180:
+ rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
+ break;
+ case -270:
+ case 90:
+ rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
+ break;
+ case -90:
+ case 270:
+ rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
+ break;
+ case 360:
+ case 0:
+ default:
+ rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+ break;
+ }
+ var offsetCanvasX, offsetCanvasY;
+ var width, height;
+ if (rotateA == 0) {
+ offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+ width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ } else {
+ offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+ width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ }
+ // creating transform for the following operations:
+ // translate(-centerX, -centerY), rotate and flip vertically,
+ // scale, and translate(offsetCanvasX, offsetCanvasY)
+ this.transform = [
+ rotateA * scale,
+ rotateB * scale,
+ rotateC * scale,
+ rotateD * scale,
+ offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
+ offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
+ ];
+
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+ this.width = width;
+ this.height = height;
+ this.fontScale = scale;
+ }
+ PageViewport.prototype = {
+ convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
+ return Util.applyTransform([x, y], this.transform);
+ },
+ convertToViewportRectangle:
+ function PageViewport_convertToViewportRectangle(rect) {
+ var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
+ var br = Util.applyTransform([rect[2], rect[3]], this.transform);
+ return [tl[0], tl[1], br[0], br[1]];
+ },
+ convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
+ return Util.applyInverseTransform([x, y], this.transform);
+ }
+ };
+ return PageViewport;
+})();
+
var PDFStringTranslateTable = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
@@ -1095,6 +870,10 @@ function stringToPDFString(str) {
return str2;
}
+function stringToUTF8String(str) {
+ return decodeURIComponent(escape(str));
+}
+
function isBool(v) {
return typeof v == 'boolean';
}
@@ -1168,7 +947,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 PromiseClosure() {
+var Promise = PDFJS.Promise = (function PromiseClosure() {
var EMPTY_PROMISE = {};
/**
@@ -1190,6 +969,7 @@ var Promise = (function PromiseClosure() {
}
this.callbacks = [];
this.errbacks = [];
+ this.progressbacks = [];
};
/**
* Builds a promise that is resolved when all the passed in promises are
@@ -1205,7 +985,7 @@ var Promise = (function PromiseClosure() {
deferred.resolve(results);
return deferred;
}
- for (var i = 0; i < unresolved; ++i) {
+ for (var i = 0, ii = promises.length; i < ii; ++i) {
var promise = promises[i];
promise.then((function(i) {
return function(value) {
@@ -1261,7 +1041,7 @@ var Promise = (function PromiseClosure() {
}
this.isResolved = true;
- this.data = data || null;
+ this.data = (typeof data !== 'undefined') ? data : null;
var callbacks = this.callbacks;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
@@ -1269,7 +1049,14 @@ var Promise = (function PromiseClosure() {
}
},
- reject: function Promise_reject(reason) {
+ progress: function Promise_progress(data) {
+ var callbacks = this.progressbacks;
+ for (var i = 0, ii = callbacks.length; i < ii; i++) {
+ callbacks[i].call(null, data);
+ }
+ },
+
+ reject: function Promise_reject(reason, exception) {
if (this.isRejected) {
error('A Promise can be rejected only once ' + this.name);
}
@@ -1282,11 +1069,11 @@ var Promise = (function PromiseClosure() {
var errbacks = this.errbacks;
for (var i = 0, ii = errbacks.length; i < ii; i++) {
- errbacks[i].call(null, reason);
+ errbacks[i].call(null, reason, exception);
}
},
- then: function Promise_then(callback, errback) {
+ then: function Promise_then(callback, errback, progressback) {
if (!callback) {
error('Requiring callback' + this.name);
}
@@ -1303,6 +1090,9 @@ var Promise = (function PromiseClosure() {
if (errback)
this.errbacks.push(errback);
}
+
+ if (progressback)
+ this.progressbacks.push(progressback);
}
};
@@ -1361,6 +1151,659 @@ var StatTimer = (function StatTimerClosure() {
};
return StatTimer;
})();
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+/**
+ * This is the main entry point for loading a PDF and interacting with it.
+ * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
+ * is used, which means it must follow the same origin rules that any XHR does
+ * e.g. No cross domain requests without CORS.
+ *
+ * @param {string|TypedAray|object} source Can be an url to where a PDF is
+ * located, a typed array (Uint8Array) already populated with data or
+ * and parameter object with the following possible fields:
+ * - url - The URL of the PDF.
+ * - data - A typed array with PDF data.
+ * - httpHeaders - Basic authentication headers.
+ * - password - For decrypting password-protected PDFs.
+ *
+ * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object.
+ */
+PDFJS.getDocument = function getDocument(source) {
+ var url, data, headers, password, parameters = {};
+ if (typeof source === 'string') {
+ url = source;
+ } else if (isArrayBuffer(source)) {
+ data = source;
+ } else if (typeof source === 'object') {
+ url = source.url;
+ data = source.data;
+ headers = source.httpHeaders;
+ password = source.password;
+ parameters.password = password || null;
+
+ if (!url && !data)
+ error('Invalid parameter array, need either .data or .url');
+ } else {
+ error('Invalid parameter in getDocument, need either Uint8Array, ' +
+ 'string or a parameter object');
+ }
+
+ var promise = new PDFJS.Promise();
+ var transport = new WorkerTransport(promise);
+ if (data) {
+ // assuming the data is array, instantiating directly from it
+ transport.sendData(data, parameters);
+ } else if (url) {
+ // fetch url
+ PDFJS.getPdf(
+ {
+ url: url,
+ progress: function getPDFProgress(evt) {
+ if (evt.lengthComputable)
+ promise.progress({
+ loaded: evt.loaded,
+ total: evt.total
+ });
+ },
+ error: function getPDFError(e) {
+ promise.reject('Unexpected server response of ' +
+ e.target.status + '.');
+ },
+ headers: headers
+ },
+ function getPDFLoad(data) {
+ transport.sendData(data, parameters);
+ });
+ }
+
+ return promise;
+};
+
+/**
+ * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
+ * properties that can be read synchronously.
+ */
+var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
+ function PDFDocumentProxy(pdfInfo, transport) {
+ this.pdfInfo = pdfInfo;
+ this.transport = transport;
+ }
+ PDFDocumentProxy.prototype = {
+ /**
+ * @return {number} Total number of pages the PDF contains.
+ */
+ get numPages() {
+ return this.pdfInfo.numPages;
+ },
+ /**
+ * @return {string} A unique ID to identify a PDF. Not guaranteed to be
+ * unique.
+ */
+ get fingerprint() {
+ return this.pdfInfo.fingerprint;
+ },
+ /**
+ * @param {number} The page number to get. The first page is 1.
+ * @return {Promise} A promise that is resolved with a {PDFPageProxy}
+ * object.
+ */
+ getPage: function PDFDocumentProxy_getPage(number) {
+ return this.transport.getPage(number);
+ },
+ /**
+ * @return {Promise} A promise that is resolved with a lookup table for
+ * mapping named destinations to reference numbers.
+ */
+ getDestinations: function PDFDocumentProxy_getDestinations() {
+ var promise = new PDFJS.Promise();
+ var destinations = this.pdfInfo.destinations;
+ promise.resolve(destinations);
+ return promise;
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {array} that is a
+ * tree outline (if it has one) of the PDF. The tree is in the format of:
+ * [
+ * {
+ * title: string,
+ * bold: boolean,
+ * italic: boolean,
+ * color: rgb array,
+ * dest: dest obj,
+ * items: array of more items like this
+ * },
+ * ...
+ * ].
+ */
+ getOutline: function PDFDocumentProxy_getOutline() {
+ var promise = new PDFJS.Promise();
+ var outline = this.pdfInfo.outline;
+ promise.resolve(outline);
+ return promise;
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {object} that has
+ * info and metadata properties. Info is an {object} filled with anything
+ * available in the information dictionary and similarly metadata is a
+ * {Metadata} object with information from the metadata section of the PDF.
+ */
+ getMetadata: function PDFDocumentProxy_getMetadata() {
+ var promise = new PDFJS.Promise();
+ var info = this.pdfInfo.info;
+ var metadata = this.pdfInfo.metadata;
+ promise.resolve({
+ info: info,
+ metadata: metadata ? new PDFJS.Metadata(metadata) : null
+ });
+ return promise;
+ },
+ isEncrypted: function PDFDocumentProxy_isEncrypted() {
+ var promise = new PDFJS.Promise();
+ promise.resolve(this.pdfInfo.encrypted);
+ return promise;
+ },
+ /**
+ * @return {Promise} A promise that is resolved with a TypedArray that has
+ * the raw data from the PDF.
+ */
+ getData: function PDFDocumentProxy_getData() {
+ var promise = new PDFJS.Promise();
+ this.transport.getData(promise);
+ return promise;
+ },
+ destroy: function PDFDocumentProxy_destroy() {
+ this.transport.destroy();
+ }
+ };
+ return PDFDocumentProxy;
+})();
+
+var PDFPageProxy = (function PDFPageProxyClosure() {
+ function PDFPageProxy(pageInfo, transport) {
+ this.pageInfo = pageInfo;
+ this.transport = transport;
+ this.stats = new StatTimer();
+ this.stats.enabled = !!globalScope.PDFJS.enableStats;
+ this.objs = transport.objs;
+ this.renderInProgress = false;
+ }
+ PDFPageProxy.prototype = {
+ /**
+ * @return {number} Page number of the page. First page is 1.
+ */
+ get pageNumber() {
+ return this.pageInfo.pageIndex + 1;
+ },
+ /**
+ * @return {number} The number of degrees the page is rotated clockwise.
+ */
+ get rotate() {
+ return this.pageInfo.rotate;
+ },
+ /**
+ * @return {object} The reference that points to this page. It has 'num' and
+ * 'gen' properties.
+ */
+ get ref() {
+ return this.pageInfo.ref;
+ },
+ /**
+ * @return {array} An array of the visible portion of the PDF page in the
+ * user space units - [x1, y1, x2, y2].
+ */
+ get view() {
+ return this.pageInfo.view;
+ },
+ /**
+ * @param {number} scale The desired scale of the viewport.
+ * @param {number} rotate Degrees to rotate the viewport. If omitted this
+ * defaults to the page rotation.
+ * @return {PageViewport} Contains 'width' and 'height' properties along
+ * with transforms required for rendering.
+ */
+ getViewport: function PDFPageProxy_getViewport(scale, rotate) {
+ if (arguments.length < 2)
+ rotate = this.rotate;
+ return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {array} of the
+ * annotation objects.
+ */
+ getAnnotations: function PDFPageProxy_getAnnotations() {
+ if (this.annotationsPromise)
+ return this.annotationsPromise;
+
+ var promise = new PDFJS.Promise();
+ this.annotationsPromise = promise;
+ this.transport.getAnnotations(this.pageInfo.pageIndex);
+ return promise;
+ },
+ /**
+ * Begins the process of rendering a page to the desired context.
+ * @param {object} params A parameter object that supports:
+ * {
+ * canvasContext(required): A 2D context of a DOM Canvas object.,
+ * textLayer(optional): An object that has beginLayout, endLayout, and
+ * appendText functions.
+ * }.
+ * @return {Promise} A promise that is resolved when the page finishes
+ * rendering.
+ */
+ render: function PDFPageProxy_render(params) {
+ this.renderInProgress = true;
+
+ var promise = new Promise();
+ 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.displayReadyPromise = new Promise();
+ this.destroyed = false;
+
+ this.stats.time('Page Request');
+ this.transport.messageHandler.send('RenderPageRequest', {
+ pageIndex: this.pageNumber - 1
+ });
+ }
+
+ var self = this;
+ function complete(error) {
+ self.renderInProgress = false;
+ if (self.destroyed) {
+ delete self.operatorList;
+ delete self.displayReadyPromise;
+ }
+
+ if (error)
+ promise.reject(error);
+ else
+ promise.resolve();
+ };
+
+ // Once the operatorList and fonts are loaded, do the actual rendering.
+ this.displayReadyPromise.then(
+ function pageDisplayReadyPromise() {
+ if (self.destroyed) {
+ complete();
+ return;
+ }
+
+ var gfx = new CanvasGraphics(params.canvasContext,
+ this.objs, params.textLayer);
+ try {
+ this.display(gfx, params.viewport, complete);
+ } catch (e) {
+ complete(e);
+ }
+ }.bind(this),
+ function pageDisplayReadPromiseError(reason) {
+ complete(reason);
+ }
+ );
+
+ return promise;
+ },
+ /**
+ * For internal use only.
+ */
+ startRenderingFromOperatorList:
+ function PDFPageProxy_startRenderingFromOperatorList(operatorList,
+ fonts) {
+ var self = this;
+ 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() {
+ self.displayReadyPromise.resolve();
+ });
+ };
+
+ this.ensureFonts(fonts,
+ function pageStartRenderingFromOperatorListEnsureFonts() {
+ displayContinuation();
+ }
+ );
+ },
+ /**
+ * For internal use only.
+ */
+ ensureFonts: function PDFPageProxy_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
+ FontLoader.bind(
+ fonts,
+ function pageEnsureFontsFontObjs(fontObjs) {
+ this.stats.timeEnd('Font Loading');
+
+ callback.call(this);
+ }.bind(this)
+ );
+ },
+ /**
+ * For internal use only.
+ */
+ display: function PDFPageProxy_display(gfx, viewport, callback) {
+ var stats = this.stats;
+ stats.time('Rendering');
+
+ gfx.beginDrawing(viewport);
+
+ var startIdx = 0;
+ var length = this.operatorList.fnArray.length;
+ var operatorList = this.operatorList;
+ var stepper = null;
+ if (PDFJS.pdfBug && StepperManager.enabled) {
+ stepper = StepperManager.create(this.pageNumber - 1);
+ stepper.init(operatorList);
+ stepper.nextBreakPoint = stepper.getNextBreakPoint();
+ }
+
+ var self = this;
+ function next() {
+ startIdx =
+ gfx.executeOperatorList(operatorList, startIdx, next, stepper);
+ if (startIdx == length) {
+ gfx.endDrawing();
+ stats.timeEnd('Rendering');
+ stats.timeEnd('Overall');
+ if (callback) callback();
+ }
+ }
+ next();
+ },
+ /**
+ * @return {Promise} That is resolved with the a {string} that is the text
+ * content from the page.
+ */
+ getTextContent: function PDFPageProxy_getTextContent() {
+ var promise = new PDFJS.Promise();
+ this.transport.messageHandler.send('GetTextContent', {
+ pageIndex: this.pageNumber - 1
+ },
+ function textContentCallback(textContent) {
+ promise.resolve(textContent);
+ }
+ );
+ return promise;
+ },
+ /**
+ * Stub for future feature.
+ */
+ getOperationList: function PDFPageProxy_getOperationList() {
+ var promise = new PDFJS.Promise();
+ var operationList = { // not implemented
+ dependencyFontsID: null,
+ operatorList: null
+ };
+ promise.resolve(operationList);
+ return promise;
+ },
+ /**
+ * Destroys resources allocated by the page.
+ */
+ destroy: function PDFPageProxy_destroy() {
+ this.destroyed = true;
+
+ if (!this.renderInProgress) {
+ delete this.operatorList;
+ delete this.displayReadyPromise;
+ }
+ }
+ };
+ return PDFPageProxy;
+})();
+/**
+ * For internal use only.
+ */
+var WorkerTransport = (function WorkerTransportClosure() {
+ function WorkerTransport(promise) {
+ this.workerReadyPromise = promise;
+ this.objs = new PDFObjects();
+
+ this.pageCache = [];
+ this.pagePromises = [];
+ this.fontsLoading = {};
+
+ // If worker support isn't disabled explicit and the browser has worker
+ // support, create a new web worker and test if it/the browser fullfills
+ // all requirements to run parts of pdf.js in a web worker.
+ // Right now, the requirement is, that an Uint8Array is still an Uint8Array
+ // as it arrives on the worker. Chrome added this with version 15.
+ if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
+ var workerSrc = PDFJS.workerSrc;
+ if (typeof workerSrc === 'undefined') {
+ error('No PDFJS.workerSrc specified');
+ }
+
+ try {
+ 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 {
+ // 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);
+ }
+
+ var messageHandler = new MessageHandler('main', worker);
+ this.messageHandler = messageHandler;
+
+ messageHandler.on('test', function transportTest(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) {
+ info('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();
+ }
+ WorkerTransport.prototype = {
+ destroy: function WorkerTransport_destroy() {
+ if (this.worker)
+ this.worker.terminate();
+
+ this.pageCache = [];
+ this.pagePromises = [];
+ },
+ setupFakeWorker: function WorkerTransport_setupFakeWorker() {
+ // If we don't use a worker, just post/sendMessage to the main thread.
+ var fakeWorker = {
+ postMessage: function WorkerTransport_postMessage(obj) {
+ fakeWorker.onmessage({data: obj});
+ },
+ terminate: function WorkerTransport_terminate() {}
+ };
+
+ var messageHandler = new MessageHandler('main', fakeWorker);
+ this.setupMessageHandler(messageHandler);
+
+ // If the main thread is our worker, setup the handling for the messages
+ // the main thread sends to it self.
+ WorkerMessageHandler.setup(messageHandler);
+ },
+
+ setupMessageHandler:
+ function WorkerTransport_setupMessageHandler(messageHandler) {
+ this.messageHandler = messageHandler;
+
+ messageHandler.on('GetDoc', function transportDoc(data) {
+ var pdfInfo = data.pdfInfo;
+ var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
+ this.pdfDocument = pdfDocument;
+ this.workerReadyPromise.resolve(pdfDocument);
+ }, this);
+
+ messageHandler.on('NeedPassword', function transportPassword(data) {
+ this.workerReadyPromise.reject(data.exception.message, data.exception);
+ }, this);
+
+ messageHandler.on('IncorrectPassword', function transportBadPass(data) {
+ this.workerReadyPromise.reject(data.exception.message, data.exception);
+ }, this);
+
+ messageHandler.on('GetPage', function transportPage(data) {
+ var pageInfo = data.pageInfo;
+ var page = new PDFPageProxy(pageInfo, this);
+ this.pageCache[pageInfo.pageIndex] = page;
+ var promise = this.pagePromises[pageInfo.pageIndex];
+ promise.resolve(page);
+ }, this);
+
+ messageHandler.on('GetAnnotations', function transportAnnotations(data) {
+ var annotations = data.annotations;
+ var promise = this.pageCache[data.pageIndex].annotationsPromise;
+ promise.resolve(annotations);
+ }, this);
+
+ messageHandler.on('RenderPage', function transportRender(data) {
+ var page = this.pageCache[data.pageIndex];
+ var depFonts = data.depFonts;
+
+ page.stats.timeEnd('Page Request');
+ page.startRenderingFromOperatorList(data.operatorList, depFonts);
+ }, this);
+
+ messageHandler.on('obj', function transportObj(data) {
+ var id = data[0];
+ var type = data[1];
+ if (this.objs.hasData(id))
+ return;
+
+ switch (type) {
+ case 'JpegStream':
+ 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];
+ var file = data[3];
+ var properties = data[4];
+
+ if (file) {
+ // Rewrap the ArrayBuffer in a stream.
+ var fontFileDict = new Dict();
+ file = new Stream(file, 0, file.length, fontFileDict);
+ }
+
+ // 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:
+ error('Got unkown object type ' + type);
+ }
+ }, this);
+
+ messageHandler.on('PageError', function transportError(data) {
+ var page = this.pageCache[data.pageNum - 1];
+ if (page.displayReadyPromise)
+ page.displayReadyPromise.reject(data.error);
+ else
+ error(data.error);
+ }, this);
+
+ messageHandler.on('JpegDecode', 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;
+ });
+ },
+
+ sendData: function WorkerTransport_sendData(data, params) {
+ this.messageHandler.send('GetDocRequest', {data: data, params: params});
+ },
+
+ getData: function WorkerTransport_sendData(promise) {
+ this.messageHandler.send('GetData', null, function(data) {
+ promise.resolve(data);
+ });
+ },
+
+ getPage: function WorkerTransport_getPage(pageNumber, promise) {
+ var pageIndex = pageNumber - 1;
+ if (pageIndex in this.pagePromises)
+ return this.pagePromises[pageIndex];
+ var promise = new PDFJS.Promise('Page ' + pageNumber);
+ this.pagePromises[pageIndex] = promise;
+ this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
+ return promise;
+ },
+
+ getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
+ this.messageHandler.send('GetAnnotationsRequest',
+ { pageIndex: pageIndex });
+ }
+ };
+ return WorkerTransport;
+
+})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -1604,27 +2047,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
'shadingFill': true
},
- beginDrawing: function CanvasGraphics_beginDrawing(mediaBox) {
- var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
+ beginDrawing: function CanvasGraphics_beginDrawing(viewport) {
+ var transform = viewport.transform;
this.ctx.save();
- switch (mediaBox.rotate) {
- case 0:
- this.ctx.transform(1, 0, 0, -1, 0, ch);
- break;
- case 90:
- this.ctx.transform(0, 1, 1, 0, 0, 0);
- break;
- case 180:
- this.ctx.transform(-1, 0, 0, 1, cw, 0);
- break;
- case 270:
- 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);
+ this.ctx.transform.apply(this.ctx, transform);
if (this.textLayer)
this.textLayer.beginLayout();
@@ -1723,10 +2149,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.ctx.webkitLineDashOffset = dashPhase;
},
setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
- TODO('set rendering intent: ' + intent);
+ // Maybe if we one day fully support color spaces this will be important
+ // for now we can ignore.
+ // TODO set rendering intent?
},
setFlatness: function CanvasGraphics_setFlatness(flatness) {
- TODO('set flatness: ' + flatness);
+ // There's no way to control this with canvas, but we can safely ignore.
+ // TODO set flatness?
},
setGState: function CanvasGraphics_setGState(states) {
for (var i = 0, ii = states.length; i < ii; i++) {
@@ -2221,7 +2650,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
text.length += shownText.length;
}
} else {
- malformed('TJ array element ' + e + ' is not string or num');
+ error('TJ array element ' + e + ' is not string or num');
}
}
@@ -2474,6 +2903,40 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
}
}
+ function rescaleImage(pixels, widthScale, heightScale) {
+ var scaledWidth = Math.ceil(width / widthScale);
+ var scaledHeight = Math.ceil(height / heightScale);
+
+ var itemsSum = new Uint32Array(scaledWidth * scaledHeight * 4);
+ var itemsCount = new Uint32Array(scaledWidth * scaledHeight);
+ for (var i = 0, position = 0; i < height; i++) {
+ var lineOffset = (0 | (i / heightScale)) * scaledWidth;
+ for (var j = 0; j < width; j++) {
+ var countOffset = lineOffset + (0 | (j / widthScale));
+ var sumOffset = countOffset << 2;
+ itemsSum[sumOffset] += pixels[position];
+ itemsSum[sumOffset + 1] += pixels[position + 1];
+ itemsSum[sumOffset + 2] += pixels[position + 2];
+ itemsSum[sumOffset + 3] += pixels[position + 3];
+ itemsCount[countOffset]++;
+ position += 4;
+ }
+ }
+ var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight);
+ var tmpCtx = tmpCanvas.getContext('2d');
+ var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight);
+ pixels = imgData.data;
+ for (var i = 0, j = 0, ii = scaledWidth * scaledHeight; i < ii; i++) {
+ var count = itemsCount[i];
+ pixels[j] = itemsSum[j] / count;
+ pixels[j + 1] = itemsSum[j + 1] / count;
+ pixels[j + 2] = itemsSum[j + 2] / count;
+ pixels[j + 3] = itemsSum[j + 3] / count;
+ j += 4;
+ }
+ tmpCtx.putImageData(imgData, 0, 0);
+ return tmpCanvas;
+ }
this.save();
@@ -2496,8 +2959,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
applyStencilMask(pixels, inverseDecode);
- tmpCtx.putImageData(imgData, 0, 0);
- ctx.drawImage(tmpCanvas, 0, -h);
+ var currentTransform = ctx.mozCurrentTransformInverse;
+ var widthScale = Math.max(Math.abs(currentTransform[0]), 1);
+ var heightScale = Math.max(Math.abs(currentTransform[3]), 1);
+ if (widthScale >= 2 || heightScale >= 2) {
+ // canvas does not resize well large images to small -- using simple
+ // algorithm to perform pre-scaling
+ tmpCanvas = rescaleImage(imgData.data, widthScale, heightScale);
+ ctx.scale(widthScale, heightScale);
+ ctx.drawImage(tmpCanvas, 0, -h / heightScale);
+ } else {
+ tmpCtx.putImageData(imgData, 0, 0);
+ ctx.drawImage(tmpCanvas, 0, -h);
+ }
this.restore();
},
@@ -2624,6 +3098,7 @@ if (!isWorker) {
};
}
}
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -2663,51 +3138,55 @@ 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;
- }
+ var map = Object.create(null);
+
+ this.assignXref = function Dict_assignXref(newXref) {
+ xref = newXref;
+ };
- Dict.prototype = {
// automatically dereferences Ref objects
- get: function Dict_get(key1, key2, key3) {
+ this.get = function Dict_get(key1, key2, key3) {
var value;
- var xref = this.xref;
- if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
+ if (typeof (value = map[key1]) != 'undefined' || key1 in map ||
typeof key2 == 'undefined') {
- return xref ? this.xref.fetchIfRef(value) : value;
+ return xref ? xref.fetchIfRef(value) : value;
}
- if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
+ if (typeof (value = map[key2]) != 'undefined' || key2 in map ||
typeof key3 == 'undefined') {
- return xref ? this.xref.fetchIfRef(value) : value;
+ return xref ? xref.fetchIfRef(value) : value;
}
- value = this.map[key3] || null;
- return xref ? this.xref.fetchIfRef(value) : value;
- },
+ value = map[key3] || null;
+ return xref ? xref.fetchIfRef(value) : value;
+ };
+
// no dereferencing
- getRaw: function Dict_getRaw(key) {
- return this.map[key];
- },
+ this.getRaw = function Dict_getRaw(key) {
+ return map[key];
+ };
+
// creates new map and dereferences all Refs
- getAll: function Dict_getAll() {
+ this.getAll = function Dict_getAll() {
var all = {};
- for (var key in this.map)
- all[key] = this.get(key);
+ for (var key in map) {
+ var obj = this.get(key);
+ all[key] = obj instanceof Dict ? obj.getAll() : obj;
+ }
return all;
- },
+ };
- set: function Dict_set(key, value) {
- this.map[key] = value;
- },
+ this.set = function Dict_set(key, value) {
+ map[key] = value;
+ };
- has: function Dict_has(key) {
- return key in this.map;
- },
+ this.has = function Dict_has(key) {
+ return key in map;
+ };
- forEach: function Dict_forEach(callback) {
- for (var key in this.map) {
+ this.forEach = function Dict_forEach(callback) {
+ for (var key in map) {
callback(key, this.get(key));
}
- }
+ };
};
return Dict;
@@ -2754,7 +3233,14 @@ var Catalog = (function CatalogClosure() {
Catalog.prototype = {
get metadata() {
- var stream = this.catDict.get('Metadata');
+ var streamRef = this.catDict.getRaw('Metadata');
+ if (!isRef(streamRef))
+ return shadow(this, 'metadata', null);
+
+ var encryptMetadata = !this.xref.encrypt ? false :
+ this.xref.encrypt.encryptMetadata;
+
+ var stream = this.xref.fetch(streamRef, !encryptMetadata);
var metadata;
if (stream && isDict(stream.dict)) {
var type = stream.dict.get('Type');
@@ -2762,7 +3248,16 @@ var Catalog = (function CatalogClosure() {
if (isName(type) && isName(subtype) &&
type.name === 'Metadata' && subtype.name === 'XML') {
- metadata = stringToPDFString(bytesToString(stream.getBytes()));
+ // XXX: This should examine the charset the XML document defines,
+ // however since there are currently no real means to decode
+ // arbitrary charsets, let's just hope that the author of the PDF
+ // was reasonable enough to stick with the XML default charset,
+ // which is UTF-8.
+ try {
+ metadata = stringToUTF8String(bytesToString(stream.getBytes()));
+ } catch (e) {
+ info('Skipping invalid metadata.');
+ }
}
}
@@ -2920,12 +3415,12 @@ var Catalog = (function CatalogClosure() {
})();
var XRef = (function XRefClosure() {
- function XRef(stream, startXRef, mainXRefEntriesOffset) {
+ function XRef(stream, startXRef, mainXRefEntriesOffset, password) {
this.stream = stream;
this.entries = [];
this.xrefstms = {};
var trailerDict = this.readXRef(startXRef);
- trailerDict.xref = this;
+ trailerDict.assignXref(this);
this.trailer = trailerDict;
// prepare the XRef cache
this.cache = [];
@@ -2933,8 +3428,7 @@ var XRef = (function XRefClosure() {
var encrypt = trailerDict.get('Encrypt');
if (encrypt) {
var fileId = trailerDict.get('ID');
- this.encrypt = new CipherTransformFactory(encrypt,
- fileId[0] /*, password */);
+ this.encrypt = new CipherTransformFactory(encrypt, fileId[0], password);
}
// get the root dictionary (catalog) object
@@ -2986,9 +3480,8 @@ var XRef = (function XRefClosure() {
}
}
- // Sanity check: as per spec, first object must have these properties
- if (this.entries[0] &&
- !(this.entries[0].gen === 65535 && this.entries[0].free))
+ // Sanity check: as per spec, first object must be free
+ if (this.entries[0] && !this.entries[0].free)
error('Invalid XRef table: unexpected first object');
// Sanity check
@@ -3147,7 +3640,7 @@ var XRef = (function XRefClosure() {
}
// reading XRef streams
for (var i = 0, ii = xrefStms.length; i < ii; ++i) {
- this.readXRef(xrefStms[i]);
+ this.readXRef(xrefStms[i], true);
}
// finding main trailer
var dict;
@@ -3170,7 +3663,7 @@ var XRef = (function XRefClosure() {
// nothing helps
error('Invalid PDF structure');
},
- readXRef: function XRef_readXRef(startXRef) {
+ readXRef: function XRef_readXRef(startXRef, recoveryMode) {
var stream = this.stream;
stream.pos = startXRef;
@@ -3203,16 +3696,18 @@ var XRef = (function XRefClosure() {
error('Invalid XRef stream');
}
dict = this.readXRefStream(obj);
+ if (!dict)
+ error('Failed to read XRef stream');
}
// Recursively get previous dictionary, if any
obj = dict.get('Prev');
if (isInt(obj))
- this.readXRef(obj);
+ this.readXRef(obj, recoveryMode);
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);
+ this.readXRef(obj.num, recoveryMode);
}
return dict;
@@ -3220,6 +3715,9 @@ var XRef = (function XRefClosure() {
log('(while reading XRef): ' + e);
}
+ if (recoveryMode)
+ return;
+
warn('Indexing all PDF objects');
return this.indexObjects();
},
@@ -3432,6 +3930,7 @@ var PDFObjects = (function PDFObjectsClosure() {
return PDFObjects;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -4270,7 +4769,10 @@ var PostScriptLexer = (function PostScriptLexerClosure() {
// operator
var str = ch.toLowerCase();
while (true) {
- ch = stream.lookChar().toLowerCase();
+ ch = stream.lookChar();
+ if (ch === null)
+ break;
+ ch = ch.toLowerCase();
if (ch >= 'a' && ch <= 'z')
str += ch;
else
@@ -4306,6 +4808,7 @@ var PostScriptLexer = (function PostScriptLexerClosure() {
return PostScriptLexer;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -4411,6 +4914,7 @@ var ExpertSubsetCharset = [
'periodinferior', 'commainferior'
];
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -11344,6 +11848,7 @@ var CIDToUnicodeMaps = {
{f: 7, c: 19887}]
};
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -11797,12 +12302,12 @@ var LabCS = (function LabCSClosure() {
error('Invalid WhitePoint components, no fallback available');
if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
- warn('Invalid BlackPoint, falling back to default');
+ info('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');
+ info('Invalid Range, falling back to defaults');
this.amin = -100;
this.amax = 100;
this.bmin = -100;
@@ -11876,6 +12381,7 @@ var LabCS = (function LabCSClosure() {
};
return LabCS;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -12297,13 +12803,14 @@ var CipherTransform = (function CipherTransformClosure() {
})();
var CipherTransformFactory = (function CipherTransformFactoryClosure() {
+ var defaultPasswordBytes = new Uint8Array([
+ 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
+ 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
+ 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
+ 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
+
function prepareKeyData(fileId, password, ownerPassword, userPassword,
flags, revision, keyLength, encryptMetadata) {
- var defaultPasswordBytes = new Uint8Array([
- 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
- 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
- 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
- 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
var hashData = new Uint8Array(100), i = 0, j, n;
if (password) {
n = Math.min(32, password.length);
@@ -12340,9 +12847,8 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
var cipher, checkData;
if (revision >= 3) {
- // padded password in hashData, we can use this array for user
- // password check
- i = 32;
+ for (i = 0; i < 32; ++i)
+ hashData[i] = defaultPasswordBytes[i];
for (j = 0, n = fileId.length; j < n; ++j)
hashData[i++] = fileId[j];
cipher = new ARCFourCipher(encryptionKey);
@@ -12355,16 +12861,53 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
cipher = new ARCFourCipher(derivedKey);
checkData = cipher.encryptBlock(checkData);
}
+ for (j = 0, n = checkData.length; j < n; ++j) {
+ if (userPassword[j] != checkData[j])
+ return null;
+ }
} else {
cipher = new ARCFourCipher(encryptionKey);
- checkData = cipher.encryptBlock(hashData.subarray(0, 32));
- }
- for (j = 0, n = checkData.length; j < n; ++j) {
- if (userPassword[j] != checkData[j])
- error('incorrect password');
+ checkData = cipher.encryptBlock(defaultPasswordBytes);
+ for (j = 0, n = checkData.length; j < n; ++j) {
+ if (userPassword[j] != checkData[j])
+ return null;
+ }
}
return encryptionKey;
}
+ function decodeUserPassword(password, ownerPassword, revision, keyLength) {
+ var hashData = new Uint8Array(32), i = 0, j, n;
+ n = Math.min(32, password.length);
+ for (; i < n; ++i)
+ hashData[i] = password[i];
+ j = 0;
+ while (i < 32) {
+ hashData[i++] = defaultPasswordBytes[j++];
+ }
+ var hash = calculateMD5(hashData, 0, i);
+ var keyLengthInBytes = keyLength >> 3;
+ if (revision >= 3) {
+ for (j = 0; j < 50; ++j) {
+ hash = calculateMD5(hash, 0, hash.length);
+ }
+ }
+
+ var cipher, userPassword;
+ if (revision >= 3) {
+ userPassword = ownerPassword;
+ var derivedKey = new Uint8Array(keyLengthInBytes), k;
+ for (j = 19; j >= 0; j--) {
+ for (k = 0; k < keyLengthInBytes; ++k)
+ derivedKey[k] = hash[k] ^ j;
+ cipher = new ARCFourCipher(derivedKey);
+ userPassword = cipher.encryptBlock(userPassword);
+ }
+ } else {
+ cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
+ userPassword = cipher.encryptBlock(ownerPassword);
+ }
+ return userPassword;
+ }
var identityName = new Name('Identity');
@@ -12387,17 +12930,34 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
var userPassword = stringToBytes(dict.get('U'));
var flags = dict.get('P');
var revision = dict.get('R');
- var encryptMetadata =
+ var encryptMetadata = algorithm == 4 && // meaningful when V is 4
dict.get('EncryptMetadata') !== false; // makes true as default value
+ this.encryptMetadata = encryptMetadata;
+
var fileIdBytes = stringToBytes(fileId);
var passwordBytes;
if (password)
passwordBytes = stringToBytes(password);
- this.encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
- ownerPassword, userPassword,
- flags, revision,
- keyLength, encryptMetadata);
+ var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
+ ownerPassword, userPassword, flags,
+ revision, keyLength, encryptMetadata);
+ if (!encryptionKey && !password) {
+ throw new PasswordException('No password given', 'needpassword');
+ } else if (!encryptionKey && password) {
+ // Attempting use the password as an owner password
+ var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword,
+ revision, keyLength);
+ encryptionKey = prepareKeyData(fileIdBytes, decodedPassword,
+ ownerPassword, userPassword, flags,
+ revision, keyLength, encryptMetadata);
+ }
+
+ if (!encryptionKey)
+ throw new PasswordException('Incorrect Password', 'incorrectpassword');
+
+ this.encryptionKey = encryptionKey;
+
if (algorithm == 4) {
this.cf = dict.get('CF');
this.stmf = dict.get('StmF') || identityName;
@@ -12472,6 +13032,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
return CipherTransformFactory;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -12582,20 +13143,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// Compatibility
BX: 'beginCompat',
- EX: 'endCompat'
+ EX: 'endCompat',
+
+ // (reserved partial commands for the lexer)
+ BM: null,
+ BD: null,
+ 'true': null,
+ fa: null,
+ fal: null,
+ fals: null,
+ 'false': null,
+ nu: null,
+ nul: null,
+ 'null': null
};
- 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,
@@ -12627,13 +13189,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
font = xref.fetchIfRef(font) || fontRes.get(fontName);
assertWellFormed(isDict(font));
- if (!font.translated) {
+
+ ++self.objIdCounter;
+ if (!font.loadedName) {
font.translated = self.translateFont(font, xref, resources,
dependency);
if (font.translated) {
// keep track of each font we translated so the caller can
// load them asynchronously before calling display on a page
- loadedName = 'font_' + uniquePrefix + (++self.objIdCounter);
+ loadedName = 'font_' + uniquePrefix + self.objIdCounter;
font.translated.properties.loadedName = loadedName;
font.loadedName = loadedName;
@@ -12738,36 +13302,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
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 parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
var res = resources;
- var hasNextObj = false, nextObj;
var args = [], obj;
var TILING_PATTERN = 1, SHADING_PATTERN = 2;
while (true) {
- if (hasNextObj) {
- obj = nextObj;
- hasNextObj = false;
- } else {
- obj = parser.getObj();
- if (isEOF(obj))
- break;
- }
+ 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
- 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
@@ -12907,6 +13454,18 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
value[1]
]);
break;
+ case 'BM':
+ // We support the default so don't trigger the TODO.
+ if (!isName(value) || value.name != 'Normal')
+ TODO('graphic state operator ' + key);
+ break;
+ case 'SMask':
+ // We support the default so don't trigger the TODO.
+ if (!isName(value) || value.name != 'None')
+ TODO('graphic state operator ' + key);
+ break;
+ // Only generate info log messages for the following since
+ // they are unlikey to have a big impact on the rendering.
case 'OP':
case 'op':
case 'OPM':
@@ -12919,14 +13478,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
case 'HT':
case 'SM':
case 'SA':
- case 'BM':
- case 'SMask':
case 'AIS':
case 'TK':
- TODO('graphic state operator ' + key);
+ // TODO implement these operators.
+ info('graphic state operator ' + key);
break;
default:
- warn('Unknown graphic state operator ' + key);
+ info('Unknown graphic state operator ' + key);
break;
}
}
@@ -12940,13 +13498,88 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
args = [];
} else if (obj != null) {
assertWellFormed(args.length <= 33, 'Too many arguments');
- args.push(obj);
+ args.push(obj instanceof Dict ? obj.getAll() : obj);
}
}
return queue;
},
+ getTextContent: function partialEvaluatorGetIRQueue(stream, resources) {
+
+ var self = this;
+ var xref = this.xref;
+
+ function handleSetFont(fontName, fontRef) {
+ 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), tra;
+ assertWellFormed(isDict(font));
+ if (!font.translated) {
+ font.translated = self.translateFont(font, xref, resources);
+ }
+ return font;
+ }
+
+ resources = xref.fetchIfRef(resources) || new Dict();
+
+ var parser = new Parser(new Lexer(stream), false);
+ var res = resources;
+ var args = [], obj;
+
+ var text = '';
+ var chunk = '';
+ var font = null;
+ while (!isEOF(obj = parser.getObj())) {
+ if (isCmd(obj)) {
+ var cmd = obj.cmd;
+ switch (cmd) {
+ case 'Tf':
+ font = handleSetFont(args[0].name);
+ break;
+ case 'TJ':
+ var items = args[0];
+ for (var j = 0, jj = items.length; j < jj; j++) {
+ if (typeof items[j] === 'string') {
+ chunk += items[j];
+ } else if (items[j] < 0) {
+ // making all negative offsets a space - better to have
+ // a space in incorrect place than not have them at all
+ chunk += ' ';
+ }
+ }
+ break;
+ case 'Tj':
+ chunk += args[0];
+ break;
+ case "'":
+ chunk += args[0] + ' ';
+ break;
+ case '"':
+ chunk += args[2] + ' ';
+ break;
+ } // switch
+ if (chunk !== '') {
+ text += fontCharsToUnicode(chunk, font.translated.properties);
+ chunk = '';
+ }
+
+ args = [];
+ } else if (obj != null) {
+ assertWellFormed(args.length <= 33, 'Too many arguments');
+ args.push(obj);
+ }
+ }
+
+ return text;
+ },
+
extractDataStructures: function
partialEvaluatorExtractDataStructures(dict, baseDict,
xref, properties) {
@@ -12954,7 +13587,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var toUnicode = dict.get('ToUnicode') ||
baseDict.get('ToUnicode');
if (toUnicode)
- properties.toUnicode = this.readToUnicode(toUnicode, xref);
+ properties.toUnicode = this.readToUnicode(toUnicode, xref, properties);
if (properties.composite) {
// CIDSystemInfo helps to match CID to glyphs
@@ -13010,7 +13643,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
properties.hasEncoding = hasEncoding;
},
- readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref) {
+ readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref,
+ properties) {
var cmapObj = toUnicode;
var charToUnicode = [];
if (isName(cmapObj)) {
@@ -13099,6 +13733,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
} else if (octet == 0x3E) {
if (token.length) {
+ // Heuristic: guessing chars size by checking numbers sizes
+ // in the CMap entries.
+ if (token.length == 2 && properties.composite)
+ properties.wideChars = false;
+
if (token.length <= 4) {
// parsing hex number
tokens.push(parseInt(token, 16));
@@ -13316,6 +13955,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
length1: length1,
length2: length2,
composite: composite,
+ wideChars: composite,
fixedPitch: false,
fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX,
firstChar: firstChar || 0,
@@ -13336,7 +13976,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
properties.coded = true;
var charProcs = dict.get('CharProcs').getAll();
var fontResources = dict.get('Resources') || resources;
- properties.resources = fontResources;
properties.charProcOperatorList = {};
for (var key in charProcs) {
var glyphStream = charProcs[key];
@@ -13380,6 +14019,7 @@ var EvalState = (function EvalStateClosure() {
return EvalState;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -14135,6 +14775,736 @@ function isSpecialUnicode(unicode) {
unicode < kCmapGlyphOffset + kSizeOfGlyphArea);
}
+// The normalization table is obtained by filtering the Unicode characters
+// database with <compat> entries.
+var NormalizedUnicodes = {
+ '\u00A8': '\u0020\u0308',
+ '\u00AF': '\u0020\u0304',
+ '\u00B4': '\u0020\u0301',
+ '\u00B5': '\u03BC',
+ '\u00B8': '\u0020\u0327',
+ '\u0132': '\u0049\u004A',
+ '\u0133': '\u0069\u006A',
+ '\u013F': '\u004C\u00B7',
+ '\u0140': '\u006C\u00B7',
+ '\u0149': '\u02BC\u006E',
+ '\u017F': '\u0073',
+ '\u01C4': '\u0044\u017D',
+ '\u01C5': '\u0044\u017E',
+ '\u01C6': '\u0064\u017E',
+ '\u01C7': '\u004C\u004A',
+ '\u01C8': '\u004C\u006A',
+ '\u01C9': '\u006C\u006A',
+ '\u01CA': '\u004E\u004A',
+ '\u01CB': '\u004E\u006A',
+ '\u01CC': '\u006E\u006A',
+ '\u01F1': '\u0044\u005A',
+ '\u01F2': '\u0044\u007A',
+ '\u01F3': '\u0064\u007A',
+ '\u02D8': '\u0020\u0306',
+ '\u02D9': '\u0020\u0307',
+ '\u02DA': '\u0020\u030A',
+ '\u02DB': '\u0020\u0328',
+ '\u02DC': '\u0020\u0303',
+ '\u02DD': '\u0020\u030B',
+ '\u037A': '\u0020\u0345',
+ '\u0384': '\u0020\u0301',
+ '\u03D0': '\u03B2',
+ '\u03D1': '\u03B8',
+ '\u03D2': '\u03A5',
+ '\u03D5': '\u03C6',
+ '\u03D6': '\u03C0',
+ '\u03F0': '\u03BA',
+ '\u03F1': '\u03C1',
+ '\u03F2': '\u03C2',
+ '\u03F4': '\u0398',
+ '\u03F5': '\u03B5',
+ '\u03F9': '\u03A3',
+ '\u0587': '\u0565\u0582',
+ '\u0675': '\u0627\u0674',
+ '\u0676': '\u0648\u0674',
+ '\u0677': '\u06C7\u0674',
+ '\u0678': '\u064A\u0674',
+ '\u0E33': '\u0E4D\u0E32',
+ '\u0EB3': '\u0ECD\u0EB2',
+ '\u0EDC': '\u0EAB\u0E99',
+ '\u0EDD': '\u0EAB\u0EA1',
+ '\u0F77': '\u0FB2\u0F81',
+ '\u0F79': '\u0FB3\u0F81',
+ '\u1E9A': '\u0061\u02BE',
+ '\u1FBD': '\u0020\u0313',
+ '\u1FBF': '\u0020\u0313',
+ '\u1FC0': '\u0020\u0342',
+ '\u1FFE': '\u0020\u0314',
+ '\u2002': '\u0020',
+ '\u2003': '\u0020',
+ '\u2004': '\u0020',
+ '\u2005': '\u0020',
+ '\u2006': '\u0020',
+ '\u2008': '\u0020',
+ '\u2009': '\u0020',
+ '\u200A': '\u0020',
+ '\u2017': '\u0020\u0333',
+ '\u2024': '\u002E',
+ '\u2025': '\u002E\u002E',
+ '\u2026': '\u002E\u002E\u002E',
+ '\u2033': '\u2032\u2032',
+ '\u2034': '\u2032\u2032\u2032',
+ '\u2036': '\u2035\u2035',
+ '\u2037': '\u2035\u2035\u2035',
+ '\u203C': '\u0021\u0021',
+ '\u203E': '\u0020\u0305',
+ '\u2047': '\u003F\u003F',
+ '\u2048': '\u003F\u0021',
+ '\u2049': '\u0021\u003F',
+ '\u2057': '\u2032\u2032\u2032\u2032',
+ '\u205F': '\u0020',
+ '\u20A8': '\u0052\u0073',
+ '\u2100': '\u0061\u002F\u0063',
+ '\u2101': '\u0061\u002F\u0073',
+ '\u2103': '\u00B0\u0043',
+ '\u2105': '\u0063\u002F\u006F',
+ '\u2106': '\u0063\u002F\u0075',
+ '\u2107': '\u0190',
+ '\u2109': '\u00B0\u0046',
+ '\u2116': '\u004E\u006F',
+ '\u2121': '\u0054\u0045\u004C',
+ '\u2135': '\u05D0',
+ '\u2136': '\u05D1',
+ '\u2137': '\u05D2',
+ '\u2138': '\u05D3',
+ '\u213B': '\u0046\u0041\u0058',
+ '\u2160': '\u0049',
+ '\u2161': '\u0049\u0049',
+ '\u2162': '\u0049\u0049\u0049',
+ '\u2163': '\u0049\u0056',
+ '\u2164': '\u0056',
+ '\u2165': '\u0056\u0049',
+ '\u2166': '\u0056\u0049\u0049',
+ '\u2167': '\u0056\u0049\u0049\u0049',
+ '\u2168': '\u0049\u0058',
+ '\u2169': '\u0058',
+ '\u216A': '\u0058\u0049',
+ '\u216B': '\u0058\u0049\u0049',
+ '\u216C': '\u004C',
+ '\u216D': '\u0043',
+ '\u216E': '\u0044',
+ '\u216F': '\u004D',
+ '\u2170': '\u0069',
+ '\u2171': '\u0069\u0069',
+ '\u2172': '\u0069\u0069\u0069',
+ '\u2173': '\u0069\u0076',
+ '\u2174': '\u0076',
+ '\u2175': '\u0076\u0069',
+ '\u2176': '\u0076\u0069\u0069',
+ '\u2177': '\u0076\u0069\u0069\u0069',
+ '\u2178': '\u0069\u0078',
+ '\u2179': '\u0078',
+ '\u217A': '\u0078\u0069',
+ '\u217B': '\u0078\u0069\u0069',
+ '\u217C': '\u006C',
+ '\u217D': '\u0063',
+ '\u217E': '\u0064',
+ '\u217F': '\u006D',
+ '\u222C': '\u222B\u222B',
+ '\u222D': '\u222B\u222B\u222B',
+ '\u222F': '\u222E\u222E',
+ '\u2230': '\u222E\u222E\u222E',
+ '\u2474': '\u0028\u0031\u0029',
+ '\u2475': '\u0028\u0032\u0029',
+ '\u2476': '\u0028\u0033\u0029',
+ '\u2477': '\u0028\u0034\u0029',
+ '\u2478': '\u0028\u0035\u0029',
+ '\u2479': '\u0028\u0036\u0029',
+ '\u247A': '\u0028\u0037\u0029',
+ '\u247B': '\u0028\u0038\u0029',
+ '\u247C': '\u0028\u0039\u0029',
+ '\u247D': '\u0028\u0031\u0030\u0029',
+ '\u247E': '\u0028\u0031\u0031\u0029',
+ '\u247F': '\u0028\u0031\u0032\u0029',
+ '\u2480': '\u0028\u0031\u0033\u0029',
+ '\u2481': '\u0028\u0031\u0034\u0029',
+ '\u2482': '\u0028\u0031\u0035\u0029',
+ '\u2483': '\u0028\u0031\u0036\u0029',
+ '\u2484': '\u0028\u0031\u0037\u0029',
+ '\u2485': '\u0028\u0031\u0038\u0029',
+ '\u2486': '\u0028\u0031\u0039\u0029',
+ '\u2487': '\u0028\u0032\u0030\u0029',
+ '\u2488': '\u0031\u002E',
+ '\u2489': '\u0032\u002E',
+ '\u248A': '\u0033\u002E',
+ '\u248B': '\u0034\u002E',
+ '\u248C': '\u0035\u002E',
+ '\u248D': '\u0036\u002E',
+ '\u248E': '\u0037\u002E',
+ '\u248F': '\u0038\u002E',
+ '\u2490': '\u0039\u002E',
+ '\u2491': '\u0031\u0030\u002E',
+ '\u2492': '\u0031\u0031\u002E',
+ '\u2493': '\u0031\u0032\u002E',
+ '\u2494': '\u0031\u0033\u002E',
+ '\u2495': '\u0031\u0034\u002E',
+ '\u2496': '\u0031\u0035\u002E',
+ '\u2497': '\u0031\u0036\u002E',
+ '\u2498': '\u0031\u0037\u002E',
+ '\u2499': '\u0031\u0038\u002E',
+ '\u249A': '\u0031\u0039\u002E',
+ '\u249B': '\u0032\u0030\u002E',
+ '\u249C': '\u0028\u0061\u0029',
+ '\u249D': '\u0028\u0062\u0029',
+ '\u249E': '\u0028\u0063\u0029',
+ '\u249F': '\u0028\u0064\u0029',
+ '\u24A0': '\u0028\u0065\u0029',
+ '\u24A1': '\u0028\u0066\u0029',
+ '\u24A2': '\u0028\u0067\u0029',
+ '\u24A3': '\u0028\u0068\u0029',
+ '\u24A4': '\u0028\u0069\u0029',
+ '\u24A5': '\u0028\u006A\u0029',
+ '\u24A6': '\u0028\u006B\u0029',
+ '\u24A7': '\u0028\u006C\u0029',
+ '\u24A8': '\u0028\u006D\u0029',
+ '\u24A9': '\u0028\u006E\u0029',
+ '\u24AA': '\u0028\u006F\u0029',
+ '\u24AB': '\u0028\u0070\u0029',
+ '\u24AC': '\u0028\u0071\u0029',
+ '\u24AD': '\u0028\u0072\u0029',
+ '\u24AE': '\u0028\u0073\u0029',
+ '\u24AF': '\u0028\u0074\u0029',
+ '\u24B0': '\u0028\u0075\u0029',
+ '\u24B1': '\u0028\u0076\u0029',
+ '\u24B2': '\u0028\u0077\u0029',
+ '\u24B3': '\u0028\u0078\u0029',
+ '\u24B4': '\u0028\u0079\u0029',
+ '\u24B5': '\u0028\u007A\u0029',
+ '\u2A0C': '\u222B\u222B\u222B\u222B',
+ '\u2A74': '\u003A\u003A\u003D',
+ '\u2A75': '\u003D\u003D',
+ '\u2A76': '\u003D\u003D\u003D',
+ '\u2E9F': '\u6BCD',
+ '\u2EF3': '\u9F9F',
+ '\u2F00': '\u4E00',
+ '\u2F01': '\u4E28',
+ '\u2F02': '\u4E36',
+ '\u2F03': '\u4E3F',
+ '\u2F04': '\u4E59',
+ '\u2F05': '\u4E85',
+ '\u2F06': '\u4E8C',
+ '\u2F07': '\u4EA0',
+ '\u2F08': '\u4EBA',
+ '\u2F09': '\u513F',
+ '\u2F0A': '\u5165',
+ '\u2F0B': '\u516B',
+ '\u2F0C': '\u5182',
+ '\u2F0D': '\u5196',
+ '\u2F0E': '\u51AB',
+ '\u2F0F': '\u51E0',
+ '\u2F10': '\u51F5',
+ '\u2F11': '\u5200',
+ '\u2F12': '\u529B',
+ '\u2F13': '\u52F9',
+ '\u2F14': '\u5315',
+ '\u2F15': '\u531A',
+ '\u2F16': '\u5338',
+ '\u2F17': '\u5341',
+ '\u2F18': '\u535C',
+ '\u2F19': '\u5369',
+ '\u2F1A': '\u5382',
+ '\u2F1B': '\u53B6',
+ '\u2F1C': '\u53C8',
+ '\u2F1D': '\u53E3',
+ '\u2F1E': '\u56D7',
+ '\u2F1F': '\u571F',
+ '\u2F20': '\u58EB',
+ '\u2F21': '\u5902',
+ '\u2F22': '\u590A',
+ '\u2F23': '\u5915',
+ '\u2F24': '\u5927',
+ '\u2F25': '\u5973',
+ '\u2F26': '\u5B50',
+ '\u2F27': '\u5B80',
+ '\u2F28': '\u5BF8',
+ '\u2F29': '\u5C0F',
+ '\u2F2A': '\u5C22',
+ '\u2F2B': '\u5C38',
+ '\u2F2C': '\u5C6E',
+ '\u2F2D': '\u5C71',
+ '\u2F2E': '\u5DDB',
+ '\u2F2F': '\u5DE5',
+ '\u2F30': '\u5DF1',
+ '\u2F31': '\u5DFE',
+ '\u2F32': '\u5E72',
+ '\u2F33': '\u5E7A',
+ '\u2F34': '\u5E7F',
+ '\u2F35': '\u5EF4',
+ '\u2F36': '\u5EFE',
+ '\u2F37': '\u5F0B',
+ '\u2F38': '\u5F13',
+ '\u2F39': '\u5F50',
+ '\u2F3A': '\u5F61',
+ '\u2F3B': '\u5F73',
+ '\u2F3C': '\u5FC3',
+ '\u2F3D': '\u6208',
+ '\u2F3E': '\u6236',
+ '\u2F3F': '\u624B',
+ '\u2F40': '\u652F',
+ '\u2F41': '\u6534',
+ '\u2F42': '\u6587',
+ '\u2F43': '\u6597',
+ '\u2F44': '\u65A4',
+ '\u2F45': '\u65B9',
+ '\u2F46': '\u65E0',
+ '\u2F47': '\u65E5',
+ '\u2F48': '\u66F0',
+ '\u2F49': '\u6708',
+ '\u2F4A': '\u6728',
+ '\u2F4B': '\u6B20',
+ '\u2F4C': '\u6B62',
+ '\u2F4D': '\u6B79',
+ '\u2F4E': '\u6BB3',
+ '\u2F4F': '\u6BCB',
+ '\u2F50': '\u6BD4',
+ '\u2F51': '\u6BDB',
+ '\u2F52': '\u6C0F',
+ '\u2F53': '\u6C14',
+ '\u2F54': '\u6C34',
+ '\u2F55': '\u706B',
+ '\u2F56': '\u722A',
+ '\u2F57': '\u7236',
+ '\u2F58': '\u723B',
+ '\u2F59': '\u723F',
+ '\u2F5A': '\u7247',
+ '\u2F5B': '\u7259',
+ '\u2F5C': '\u725B',
+ '\u2F5D': '\u72AC',
+ '\u2F5E': '\u7384',
+ '\u2F5F': '\u7389',
+ '\u2F60': '\u74DC',
+ '\u2F61': '\u74E6',
+ '\u2F62': '\u7518',
+ '\u2F63': '\u751F',
+ '\u2F64': '\u7528',
+ '\u2F65': '\u7530',
+ '\u2F66': '\u758B',
+ '\u2F67': '\u7592',
+ '\u2F68': '\u7676',
+ '\u2F69': '\u767D',
+ '\u2F6A': '\u76AE',
+ '\u2F6B': '\u76BF',
+ '\u2F6C': '\u76EE',
+ '\u2F6D': '\u77DB',
+ '\u2F6E': '\u77E2',
+ '\u2F6F': '\u77F3',
+ '\u2F70': '\u793A',
+ '\u2F71': '\u79B8',
+ '\u2F72': '\u79BE',
+ '\u2F73': '\u7A74',
+ '\u2F74': '\u7ACB',
+ '\u2F75': '\u7AF9',
+ '\u2F76': '\u7C73',
+ '\u2F77': '\u7CF8',
+ '\u2F78': '\u7F36',
+ '\u2F79': '\u7F51',
+ '\u2F7A': '\u7F8A',
+ '\u2F7B': '\u7FBD',
+ '\u2F7C': '\u8001',
+ '\u2F7D': '\u800C',
+ '\u2F7E': '\u8012',
+ '\u2F7F': '\u8033',
+ '\u2F80': '\u807F',
+ '\u2F81': '\u8089',
+ '\u2F82': '\u81E3',
+ '\u2F83': '\u81EA',
+ '\u2F84': '\u81F3',
+ '\u2F85': '\u81FC',
+ '\u2F86': '\u820C',
+ '\u2F87': '\u821B',
+ '\u2F88': '\u821F',
+ '\u2F89': '\u826E',
+ '\u2F8A': '\u8272',
+ '\u2F8B': '\u8278',
+ '\u2F8C': '\u864D',
+ '\u2F8D': '\u866B',
+ '\u2F8E': '\u8840',
+ '\u2F8F': '\u884C',
+ '\u2F90': '\u8863',
+ '\u2F91': '\u897E',
+ '\u2F92': '\u898B',
+ '\u2F93': '\u89D2',
+ '\u2F94': '\u8A00',
+ '\u2F95': '\u8C37',
+ '\u2F96': '\u8C46',
+ '\u2F97': '\u8C55',
+ '\u2F98': '\u8C78',
+ '\u2F99': '\u8C9D',
+ '\u2F9A': '\u8D64',
+ '\u2F9B': '\u8D70',
+ '\u2F9C': '\u8DB3',
+ '\u2F9D': '\u8EAB',
+ '\u2F9E': '\u8ECA',
+ '\u2F9F': '\u8F9B',
+ '\u2FA0': '\u8FB0',
+ '\u2FA1': '\u8FB5',
+ '\u2FA2': '\u9091',
+ '\u2FA3': '\u9149',
+ '\u2FA4': '\u91C6',
+ '\u2FA5': '\u91CC',
+ '\u2FA6': '\u91D1',
+ '\u2FA7': '\u9577',
+ '\u2FA8': '\u9580',
+ '\u2FA9': '\u961C',
+ '\u2FAA': '\u96B6',
+ '\u2FAB': '\u96B9',
+ '\u2FAC': '\u96E8',
+ '\u2FAD': '\u9751',
+ '\u2FAE': '\u975E',
+ '\u2FAF': '\u9762',
+ '\u2FB0': '\u9769',
+ '\u2FB1': '\u97CB',
+ '\u2FB2': '\u97ED',
+ '\u2FB3': '\u97F3',
+ '\u2FB4': '\u9801',
+ '\u2FB5': '\u98A8',
+ '\u2FB6': '\u98DB',
+ '\u2FB7': '\u98DF',
+ '\u2FB8': '\u9996',
+ '\u2FB9': '\u9999',
+ '\u2FBA': '\u99AC',
+ '\u2FBB': '\u9AA8',
+ '\u2FBC': '\u9AD8',
+ '\u2FBD': '\u9ADF',
+ '\u2FBE': '\u9B25',
+ '\u2FBF': '\u9B2F',
+ '\u2FC0': '\u9B32',
+ '\u2FC1': '\u9B3C',
+ '\u2FC2': '\u9B5A',
+ '\u2FC3': '\u9CE5',
+ '\u2FC4': '\u9E75',
+ '\u2FC5': '\u9E7F',
+ '\u2FC6': '\u9EA5',
+ '\u2FC7': '\u9EBB',
+ '\u2FC8': '\u9EC3',
+ '\u2FC9': '\u9ECD',
+ '\u2FCA': '\u9ED1',
+ '\u2FCB': '\u9EF9',
+ '\u2FCC': '\u9EFD',
+ '\u2FCD': '\u9F0E',
+ '\u2FCE': '\u9F13',
+ '\u2FCF': '\u9F20',
+ '\u2FD0': '\u9F3B',
+ '\u2FD1': '\u9F4A',
+ '\u2FD2': '\u9F52',
+ '\u2FD3': '\u9F8D',
+ '\u2FD4': '\u9F9C',
+ '\u2FD5': '\u9FA0',
+ '\u3036': '\u3012',
+ '\u3038': '\u5341',
+ '\u3039': '\u5344',
+ '\u303A': '\u5345',
+ '\u309B': '\u0020\u3099',
+ '\u309C': '\u0020\u309A',
+ '\u3131': '\u1100',
+ '\u3132': '\u1101',
+ '\u3133': '\u11AA',
+ '\u3134': '\u1102',
+ '\u3135': '\u11AC',
+ '\u3136': '\u11AD',
+ '\u3137': '\u1103',
+ '\u3138': '\u1104',
+ '\u3139': '\u1105',
+ '\u313A': '\u11B0',
+ '\u313B': '\u11B1',
+ '\u313C': '\u11B2',
+ '\u313D': '\u11B3',
+ '\u313E': '\u11B4',
+ '\u313F': '\u11B5',
+ '\u3140': '\u111A',
+ '\u3141': '\u1106',
+ '\u3142': '\u1107',
+ '\u3143': '\u1108',
+ '\u3144': '\u1121',
+ '\u3145': '\u1109',
+ '\u3146': '\u110A',
+ '\u3147': '\u110B',
+ '\u3148': '\u110C',
+ '\u3149': '\u110D',
+ '\u314A': '\u110E',
+ '\u314B': '\u110F',
+ '\u314C': '\u1110',
+ '\u314D': '\u1111',
+ '\u314E': '\u1112',
+ '\u314F': '\u1161',
+ '\u3150': '\u1162',
+ '\u3151': '\u1163',
+ '\u3152': '\u1164',
+ '\u3153': '\u1165',
+ '\u3154': '\u1166',
+ '\u3155': '\u1167',
+ '\u3156': '\u1168',
+ '\u3157': '\u1169',
+ '\u3158': '\u116A',
+ '\u3159': '\u116B',
+ '\u315A': '\u116C',
+ '\u315B': '\u116D',
+ '\u315C': '\u116E',
+ '\u315D': '\u116F',
+ '\u315E': '\u1170',
+ '\u315F': '\u1171',
+ '\u3160': '\u1172',
+ '\u3161': '\u1173',
+ '\u3162': '\u1174',
+ '\u3163': '\u1175',
+ '\u3164': '\u1160',
+ '\u3165': '\u1114',
+ '\u3166': '\u1115',
+ '\u3167': '\u11C7',
+ '\u3168': '\u11C8',
+ '\u3169': '\u11CC',
+ '\u316A': '\u11CE',
+ '\u316B': '\u11D3',
+ '\u316C': '\u11D7',
+ '\u316D': '\u11D9',
+ '\u316E': '\u111C',
+ '\u316F': '\u11DD',
+ '\u3170': '\u11DF',
+ '\u3171': '\u111D',
+ '\u3172': '\u111E',
+ '\u3173': '\u1120',
+ '\u3174': '\u1122',
+ '\u3175': '\u1123',
+ '\u3176': '\u1127',
+ '\u3177': '\u1129',
+ '\u3178': '\u112B',
+ '\u3179': '\u112C',
+ '\u317A': '\u112D',
+ '\u317B': '\u112E',
+ '\u317C': '\u112F',
+ '\u317D': '\u1132',
+ '\u317E': '\u1136',
+ '\u317F': '\u1140',
+ '\u3180': '\u1147',
+ '\u3181': '\u114C',
+ '\u3182': '\u11F1',
+ '\u3183': '\u11F2',
+ '\u3184': '\u1157',
+ '\u3185': '\u1158',
+ '\u3186': '\u1159',
+ '\u3187': '\u1184',
+ '\u3188': '\u1185',
+ '\u3189': '\u1188',
+ '\u318A': '\u1191',
+ '\u318B': '\u1192',
+ '\u318C': '\u1194',
+ '\u318D': '\u119E',
+ '\u318E': '\u11A1',
+ '\u3200': '\u0028\u1100\u0029',
+ '\u3201': '\u0028\u1102\u0029',
+ '\u3202': '\u0028\u1103\u0029',
+ '\u3203': '\u0028\u1105\u0029',
+ '\u3204': '\u0028\u1106\u0029',
+ '\u3205': '\u0028\u1107\u0029',
+ '\u3206': '\u0028\u1109\u0029',
+ '\u3207': '\u0028\u110B\u0029',
+ '\u3208': '\u0028\u110C\u0029',
+ '\u3209': '\u0028\u110E\u0029',
+ '\u320A': '\u0028\u110F\u0029',
+ '\u320B': '\u0028\u1110\u0029',
+ '\u320C': '\u0028\u1111\u0029',
+ '\u320D': '\u0028\u1112\u0029',
+ '\u320E': '\u0028\u1100\u1161\u0029',
+ '\u320F': '\u0028\u1102\u1161\u0029',
+ '\u3210': '\u0028\u1103\u1161\u0029',
+ '\u3211': '\u0028\u1105\u1161\u0029',
+ '\u3212': '\u0028\u1106\u1161\u0029',
+ '\u3213': '\u0028\u1107\u1161\u0029',
+ '\u3214': '\u0028\u1109\u1161\u0029',
+ '\u3215': '\u0028\u110B\u1161\u0029',
+ '\u3216': '\u0028\u110C\u1161\u0029',
+ '\u3217': '\u0028\u110E\u1161\u0029',
+ '\u3218': '\u0028\u110F\u1161\u0029',
+ '\u3219': '\u0028\u1110\u1161\u0029',
+ '\u321A': '\u0028\u1111\u1161\u0029',
+ '\u321B': '\u0028\u1112\u1161\u0029',
+ '\u321C': '\u0028\u110C\u116E\u0029',
+ '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029',
+ '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029',
+ '\u3220': '\u0028\u4E00\u0029',
+ '\u3221': '\u0028\u4E8C\u0029',
+ '\u3222': '\u0028\u4E09\u0029',
+ '\u3223': '\u0028\u56DB\u0029',
+ '\u3224': '\u0028\u4E94\u0029',
+ '\u3225': '\u0028\u516D\u0029',
+ '\u3226': '\u0028\u4E03\u0029',
+ '\u3227': '\u0028\u516B\u0029',
+ '\u3228': '\u0028\u4E5D\u0029',
+ '\u3229': '\u0028\u5341\u0029',
+ '\u322A': '\u0028\u6708\u0029',
+ '\u322B': '\u0028\u706B\u0029',
+ '\u322C': '\u0028\u6C34\u0029',
+ '\u322D': '\u0028\u6728\u0029',
+ '\u322E': '\u0028\u91D1\u0029',
+ '\u322F': '\u0028\u571F\u0029',
+ '\u3230': '\u0028\u65E5\u0029',
+ '\u3231': '\u0028\u682A\u0029',
+ '\u3232': '\u0028\u6709\u0029',
+ '\u3233': '\u0028\u793E\u0029',
+ '\u3234': '\u0028\u540D\u0029',
+ '\u3235': '\u0028\u7279\u0029',
+ '\u3236': '\u0028\u8CA1\u0029',
+ '\u3237': '\u0028\u795D\u0029',
+ '\u3238': '\u0028\u52B4\u0029',
+ '\u3239': '\u0028\u4EE3\u0029',
+ '\u323A': '\u0028\u547C\u0029',
+ '\u323B': '\u0028\u5B66\u0029',
+ '\u323C': '\u0028\u76E3\u0029',
+ '\u323D': '\u0028\u4F01\u0029',
+ '\u323E': '\u0028\u8CC7\u0029',
+ '\u323F': '\u0028\u5354\u0029',
+ '\u3240': '\u0028\u796D\u0029',
+ '\u3241': '\u0028\u4F11\u0029',
+ '\u3242': '\u0028\u81EA\u0029',
+ '\u3243': '\u0028\u81F3\u0029',
+ '\u32C0': '\u0031\u6708',
+ '\u32C1': '\u0032\u6708',
+ '\u32C2': '\u0033\u6708',
+ '\u32C3': '\u0034\u6708',
+ '\u32C4': '\u0035\u6708',
+ '\u32C5': '\u0036\u6708',
+ '\u32C6': '\u0037\u6708',
+ '\u32C7': '\u0038\u6708',
+ '\u32C8': '\u0039\u6708',
+ '\u32C9': '\u0031\u0030\u6708',
+ '\u32CA': '\u0031\u0031\u6708',
+ '\u32CB': '\u0031\u0032\u6708',
+ '\u3358': '\u0030\u70B9',
+ '\u3359': '\u0031\u70B9',
+ '\u335A': '\u0032\u70B9',
+ '\u335B': '\u0033\u70B9',
+ '\u335C': '\u0034\u70B9',
+ '\u335D': '\u0035\u70B9',
+ '\u335E': '\u0036\u70B9',
+ '\u335F': '\u0037\u70B9',
+ '\u3360': '\u0038\u70B9',
+ '\u3361': '\u0039\u70B9',
+ '\u3362': '\u0031\u0030\u70B9',
+ '\u3363': '\u0031\u0031\u70B9',
+ '\u3364': '\u0031\u0032\u70B9',
+ '\u3365': '\u0031\u0033\u70B9',
+ '\u3366': '\u0031\u0034\u70B9',
+ '\u3367': '\u0031\u0035\u70B9',
+ '\u3368': '\u0031\u0036\u70B9',
+ '\u3369': '\u0031\u0037\u70B9',
+ '\u336A': '\u0031\u0038\u70B9',
+ '\u336B': '\u0031\u0039\u70B9',
+ '\u336C': '\u0032\u0030\u70B9',
+ '\u336D': '\u0032\u0031\u70B9',
+ '\u336E': '\u0032\u0032\u70B9',
+ '\u336F': '\u0032\u0033\u70B9',
+ '\u3370': '\u0032\u0034\u70B9',
+ '\u33E0': '\u0031\u65E5',
+ '\u33E1': '\u0032\u65E5',
+ '\u33E2': '\u0033\u65E5',
+ '\u33E3': '\u0034\u65E5',
+ '\u33E4': '\u0035\u65E5',
+ '\u33E5': '\u0036\u65E5',
+ '\u33E6': '\u0037\u65E5',
+ '\u33E7': '\u0038\u65E5',
+ '\u33E8': '\u0039\u65E5',
+ '\u33E9': '\u0031\u0030\u65E5',
+ '\u33EA': '\u0031\u0031\u65E5',
+ '\u33EB': '\u0031\u0032\u65E5',
+ '\u33EC': '\u0031\u0033\u65E5',
+ '\u33ED': '\u0031\u0034\u65E5',
+ '\u33EE': '\u0031\u0035\u65E5',
+ '\u33EF': '\u0031\u0036\u65E5',
+ '\u33F0': '\u0031\u0037\u65E5',
+ '\u33F1': '\u0031\u0038\u65E5',
+ '\u33F2': '\u0031\u0039\u65E5',
+ '\u33F3': '\u0032\u0030\u65E5',
+ '\u33F4': '\u0032\u0031\u65E5',
+ '\u33F5': '\u0032\u0032\u65E5',
+ '\u33F6': '\u0032\u0033\u65E5',
+ '\u33F7': '\u0032\u0034\u65E5',
+ '\u33F8': '\u0032\u0035\u65E5',
+ '\u33F9': '\u0032\u0036\u65E5',
+ '\u33FA': '\u0032\u0037\u65E5',
+ '\u33FB': '\u0032\u0038\u65E5',
+ '\u33FC': '\u0032\u0039\u65E5',
+ '\u33FD': '\u0033\u0030\u65E5',
+ '\u33FE': '\u0033\u0031\u65E5',
+ '\uFB00': '\u0066\u0066',
+ '\uFB01': '\u0066\u0069',
+ '\uFB02': '\u0066\u006C',
+ '\uFB03': '\u0066\u0066\u0069',
+ '\uFB04': '\u0066\u0066\u006C',
+ '\uFB05': '\u017F\u0074',
+ '\uFB06': '\u0073\u0074',
+ '\uFB13': '\u0574\u0576',
+ '\uFB14': '\u0574\u0565',
+ '\uFB15': '\u0574\u056B',
+ '\uFB16': '\u057E\u0576',
+ '\uFB17': '\u0574\u056D',
+ '\uFB4F': '\u05D0\u05DC',
+ '\uFE49': '\u203E',
+ '\uFE4A': '\u203E',
+ '\uFE4B': '\u203E',
+ '\uFE4C': '\u203E',
+ '\uFE4D': '\u005F',
+ '\uFE4E': '\u005F',
+ '\uFE4F': '\u005F'
+};
+
+function fontCharsToUnicode(charCodes, fontProperties) {
+ var toUnicode = fontProperties.toUnicode;
+ var composite = fontProperties.composite;
+ var encoding, differences, cidToUnicode;
+ var result = '';
+ if (composite) {
+ cidToUnicode = fontProperties.cidToUnicode;
+ for (var i = 0, ii = charCodes.length; i < ii; i += 2) {
+ var charCode = (charCodes.charCodeAt(i) << 8) |
+ charCodes.charCodeAt(i + 1);
+ if (toUnicode && charCode in toUnicode) {
+ var unicode = toUnicode[charCode];
+ result += typeof unicode !== 'number' ? unicode :
+ String.fromCharCode(unicode);
+ continue;
+ }
+ result += String.fromCharCode(!cidToUnicode ? charCode :
+ cidToUnicode[charCode] || charCode);
+ }
+ } else {
+ differences = fontProperties.differences;
+ encoding = fontProperties.baseEncoding;
+ for (var i = 0, ii = charCodes.length; i < ii; i++) {
+ var charCode = charCodes.charCodeAt(i);
+ var unicode;
+ if (toUnicode && charCode in toUnicode) {
+ var unicode = toUnicode[charCode];
+ result += typeof unicode !== 'number' ? unicode :
+ String.fromCharCode(unicode);
+ continue;
+ }
+
+ var glyphName = charCode in differences ? differences[charCode] :
+ encoding[charCode];
+ if (glyphName in GlyphsUnicode) {
+ result += String.fromCharCode(GlyphsUnicode[glyphName]);
+ continue;
+ }
+ result += String.fromCharCode(charCode);
+ }
+ }
+ // normalizing the unicode characters
+ for (var i = 0, ii = result.length; i < ii; i++) {
+ if (!(result[i] in NormalizedUnicodes))
+ continue;
+ result = result.substring(0, i) + NormalizedUnicodes[result[i]] +
+ result.substring(i + 1);
+ ii = result.length;
+ }
+ return result;
+}
+
/**
* 'Font' is the class the outside world should use, it encapsulate all the font
* decoding logics whatever type it is (assuming the font type is supported).
@@ -14148,7 +15518,6 @@ var Font = (function FontClosure() {
this.name = name;
this.coded = properties.coded;
this.charProcOperatorList = properties.charProcOperatorList;
- this.resources = properties.resources;
this.sizes = [];
var names = name.split('+');
@@ -14172,6 +15541,7 @@ var Font = (function FontClosure() {
this.widths = properties.widths;
this.defaultWidth = properties.defaultWidth;
this.composite = properties.composite;
+ this.wideChars = properties.wideChars;
this.hasEncoding = properties.hasEncoding;
this.fontMatrix = properties.fontMatrix;
@@ -15109,6 +16479,16 @@ var Font = (function FontClosure() {
properties.glyphNames = glyphNames;
}
+ function isOS2Valid(os2Table) {
+ var data = os2Table.data;
+ // usWinAscent == 0 makes font unreadable by windows
+ var usWinAscent = (data[74] << 8) | data[75];
+ if (usWinAscent == 0)
+ return false;
+
+ return true;
+ }
+
// Check that required tables are present
var requiredTables = ['OS/2', 'cmap', 'head', 'hhea',
'hmtx', 'maxp', 'name', 'post'];
@@ -15116,7 +16496,7 @@ var Font = (function FontClosure() {
var header = readOpenTypeHeader(font);
var numTables = header.numTables;
- var cmap, post, maxp, hhea, hmtx, vhea, vmtx, head, loca, glyf;
+ var cmap, post, maxp, hhea, hmtx, vhea, vmtx, head, loca, glyf, os2;
var tables = [];
for (var i = 0; i < numTables; i++) {
var table = readTableEntry(font);
@@ -15134,6 +16514,8 @@ var Font = (function FontClosure() {
hmtx = table;
else if (table.tag == 'head')
head = table;
+ else if (table.tag == 'OS/2')
+ os2 = table;
requiredTables.splice(index, 1);
} else {
@@ -15149,7 +16531,7 @@ var Font = (function FontClosure() {
tables.push(table);
}
- var numTables = header.numTables + requiredTables.length;
+ var numTables = tables.length + requiredTables.length;
// header and new offsets. Table entry information is appended to the
// end of file. The virtualOffset represents where to put the actual
@@ -15163,21 +16545,10 @@ var Font = (function FontClosure() {
// of missing tables
createOpenTypeHeader(header.version, ttf, numTables);
- if (requiredTables.indexOf('OS/2') != -1) {
- // extract some more font properties from the OpenType head and
- // hhea tables; yMin and descent value are always negative
- var override = {
- unitsPerEm: int16([head.data[18], head.data[19]]),
- yMax: int16([head.data[42], head.data[43]]),
- yMin: int16([head.data[38], head.data[39]]) - 0x10000,
- ascent: int16([hhea.data[4], hhea.data[5]]),
- descent: int16([hhea.data[6], hhea.data[7]]) - 0x10000
- };
-
- tables.push({
- tag: 'OS/2',
- data: stringToArray(createOS2Table(properties, null, override))
- });
+ // Invalid OS/2 can break the font for the Windows
+ if (os2 && !isOS2Valid(os2)) {
+ tables.splice(tables.indexOf(os2), 1);
+ os2 = null;
}
// Ensure the [h/v]mtx tables contains the advance width and
@@ -15357,9 +16728,9 @@ var Font = (function FontClosure() {
this.isSymbolicFont = false;
}
- // heuristics: if removed more than 2 glyphs encoding WinAnsiEncoding
- // does not set properly
- if (glyphsRemoved > 2) {
+ // heuristics: if removed more than 10 glyphs encoding WinAnsiEncoding
+ // does not set properly (broken PDFs have about 100 removed glyphs)
+ if (glyphsRemoved > 10) {
warn('Switching TrueType encoding to MacRomanEncoding for ' +
this.name + ' font');
encoding = Encodings.MacRomanEncoding;
@@ -15458,6 +16829,23 @@ var Font = (function FontClosure() {
}
this.unicodeIsEnabled = unicodeIsEnabled;
+ if (!os2) {
+ // extract some more font properties from the OpenType head and
+ // hhea tables; yMin and descent value are always negative
+ var override = {
+ unitsPerEm: int16([head.data[18], head.data[19]]),
+ yMax: int16([head.data[42], head.data[43]]),
+ yMin: int16([head.data[38], head.data[39]]) - 0x10000,
+ ascent: int16([hhea.data[4], hhea.data[5]]),
+ descent: int16([hhea.data[6], hhea.data[7]]) - 0x10000
+ };
+
+ tables.push({
+ tag: 'OS/2',
+ data: stringToArray(createOS2Table(properties, glyphs, override))
+ });
+ }
+
// Rewrite the 'post' table if needed
if (requiredTables.indexOf('post') != -1) {
tables.push({
@@ -15842,6 +17230,7 @@ var Font = (function FontClosure() {
}
// MacRoman encoding address by re-encoding the cmap table
+
fontCharCode = glyphName in this.glyphNameMap ?
this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
break;
@@ -15885,7 +17274,7 @@ var Font = (function FontClosure() {
glyphs = [];
- if (this.composite) {
+ if (this.wideChars) {
// composite fonts have multi-byte strings convert the string from
// single-byte to multi-byte
// XXX assuming CIDFonts are two-byte - later need to extract the
@@ -16841,7 +18230,7 @@ var CFFFont = (function CFFFontClosure() {
this.properties = properties;
var parser = new CFFParser(file, properties);
- var cff = parser.parse();
+ var cff = parser.parse(true);
var compiler = new CFFCompiler(cff);
this.readExtra(cff);
try {
@@ -16932,7 +18321,7 @@ var CFFParser = (function CFFParserClosure() {
this.properties = properties;
}
CFFParser.prototype = {
- parse: function CFFParser_parse() {
+ parse: function CFFParser_parse(normalizeCIDData) {
var properties = this.properties;
var cff = new CFF();
this.cff = cff;
@@ -16987,6 +18376,21 @@ var CFFParser = (function CFFParserClosure() {
cff.charset = charset;
cff.encoding = encoding;
+ if (!cff.isCIDFont || !normalizeCIDData)
+ return cff;
+
+ // DirectWrite does not like CID fonts data. Trying to convert/flatten
+ // the font data and remove CID properties.
+ if (cff.fdArray.length !== 1)
+ error('Unable to normalize CID font in CFF data');
+
+ var fontDict = cff.fdArray[0];
+ fontDict.setByKey(17, topDict.getByName('CharStrings'));
+ cff.topDict = fontDict;
+ cff.isCIDFont = false;
+ delete cff.fdArray;
+ delete cff.fdSelect;
+
return cff;
},
parseHeader: function CFFParser_parseHeader() {
@@ -16997,7 +18401,7 @@ var CFFParser = (function CFFParserClosure() {
++offset;
if (offset != 0) {
- warn('cff data is shifted');
+ info('cff data is shifted');
bytes = bytes.subarray(offset);
this.bytes = bytes;
}
@@ -17585,9 +18989,9 @@ var CFFPrivateDict = (function CFFPrivateDictClosure() {
[[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]
+ [21, 'nominalWidthX', 'num', 0],
+ [19, 'Subrs', 'offset', null]
];
var tables = null;
function CFFPrivateDict(strings) {
@@ -18045,6 +19449,7 @@ var CFFCompiler = (function CFFCompilerClosure() {
return CFFCompiler;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -22257,6 +23662,7 @@ var GlyphsUnicode = {
'.notdef': 0x0000
};
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -22274,7 +23680,7 @@ var PDFImage = (function PDFImageClosure() {
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) {
+ handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
var data = message.data;
var stream = new Stream(data, 0, data.length, image.dict);
promise.resolve(stream);
@@ -22632,6 +24038,7 @@ function loadJpegStream(id, imageData, objs) {
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: */
@@ -25579,6 +26986,7 @@ var Metrics = {
}
};
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -25830,9 +27238,12 @@ var Parser = (function ParserClosure() {
if (name == 'CCITTFaxDecode' || name == 'CCF') {
return new CCITTFaxStream(stream, params);
}
- if (name == 'RunLengthDecode') {
+ if (name == 'RunLengthDecode' || name == 'RL') {
return new RunLengthStream(stream);
}
+ if (name == 'JBIG2Decode') {
+ error('JBIG2 image format is not currently supprted.');
+ }
warn('filter "' + name + '" not supported yet');
return stream;
}
@@ -25842,8 +27253,16 @@ var Parser = (function ParserClosure() {
})();
var Lexer = (function LexerClosure() {
- function Lexer(stream) {
+ function Lexer(stream, knownCommands) {
this.stream = stream;
+ // The PDFs might have "glued" commands with other commands, operands or
+ // literals, e.g. "q1". The knownCommands is a dictionary of the valid
+ // commands and their prefixes. The prefixes are built the following way:
+ // if there a command that is a prefix of the other valid command or
+ // literal (e.g. 'f' and 'false') the following prefixes must be included,
+ // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no
+ // other commands or literals as a prefix. The knowCommands is optional.
+ this.knownCommands = knownCommands;
}
Lexer.isSpace = function Lexer_isSpace(ch) {
@@ -26107,12 +27526,18 @@ var Lexer = (function LexerClosure() {
// command
var str = ch;
+ var knownCommands = this.knownCommands;
+ var knownCommandFound = knownCommands && (str in knownCommands);
while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
+ // stop if known command is found and next character does not make
+ // the str a command
+ if (knownCommandFound && !((str + ch) in knownCommands))
+ break;
stream.skip();
if (str.length == 128)
error('Command token too long: ' + str.length);
-
str += ch;
+ knownCommandFound = knownCommands && (str in knownCommands);
}
if (str == 'true')
return true;
@@ -26218,6 +27643,7 @@ var Linearization = (function LinearizationClosure() {
return Linearization;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -26330,7 +27756,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
var r1 = raw[6];
return {
type: 'Pattern',
- getPattern: function(ctx) {
+ getPattern: function RadialAxial_getPattern(ctx) {
var curMatrix = ctx.mozCurrentTransform;
if (curMatrix) {
var userMatrix = ctx.mozCurrentTransformInverse;
@@ -26521,6 +27947,7 @@ var TilingPattern = (function TilingPatternClosure() {
return TilingPattern;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -28210,7 +29637,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (a1 > codingLine[codingPos]) {
if (a1 > this.columns) {
- warn('row is wrong length');
+ info('row is wrong length');
this.err = true;
a1 = this.columns;
}
@@ -28230,7 +29657,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (a1 > codingLine[codingPos]) {
if (a1 > this.columns) {
- warn('row is wrong length');
+ info('row is wrong length');
this.err = true;
a1 = this.columns;
}
@@ -28240,7 +29667,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
codingLine[codingPos] = a1;
} else if (a1 < codingLine[codingPos]) {
if (a1 < 0) {
- warn('invalid code');
+ info('invalid code');
this.err = true;
a1 = 0;
}
@@ -28402,7 +29829,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.eof = true;
break;
default:
- warn('bad 2d code');
+ info('bad 2d code');
this.addPixels(columns, 0);
this.err = true;
}
@@ -28465,7 +29892,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
for (var i = 0; i < 4; ++i) {
code1 = this.lookBits(12);
if (code1 != 1)
- warn('bad rtc code: ' + code1);
+ info('bad rtc code: ' + code1);
this.eatBits(12);
if (this.encoding > 0) {
this.lookBits(1);
@@ -28588,7 +30015,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (result[0] && result[2])
return result[1];
}
- warn('Bad two dim code');
+ info('Bad two dim code');
return EOF;
};
@@ -28621,7 +30048,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (result[0])
return result[1];
}
- warn('bad white code');
+ info('bad white code');
this.eatBits(1);
return 1;
};
@@ -28658,7 +30085,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (result[0])
return result[1];
}
- warn('bad black code');
+ info('bad black code');
this.eatBits(1);
return 1;
};
@@ -28815,6 +30242,7 @@ var LZWStream = (function LZWStreamClosure() {
return LZWStream;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -28828,10 +30256,13 @@ function MessageHandler(name, comObj) {
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
- console.log.apply(console, data);
+ console.log.apply(console, data);
}];
ah['console_error'] = [function ahConsoleError(data) {
- console.error.apply(console, data);
+ console.error.apply(console, data);
+ }];
+ ah['_warn'] = [function ah_Warn(data) {
+ warn(data);
}];
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
@@ -28902,15 +30333,68 @@ var WorkerMessageHandler = {
handler.send('test', data instanceof Uint8Array);
});
- handler.on('doc', function wphSetupDoc(data) {
+ handler.on('GetDocRequest', 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));
+ var pdfData = data.data;
+ var pdfPassword = data.params.password;
+ try {
+ pdfModel = new PDFDocument(new Stream(pdfData), pdfPassword);
+ } catch (e) {
+ if (e instanceof PasswordException) {
+ if (e.code === 'needpassword') {
+ handler.send('NeedPassword', {
+ exception: e
+ });
+ } else if (e.code === 'incorrectpassword') {
+ handler.send('IncorrectPassword', {
+ exception: e
+ });
+ }
+
+ return;
+ } else {
+ throw e;
+ }
+ }
+ var doc = {
+ numPages: pdfModel.numPages,
+ fingerprint: pdfModel.getFingerprint(),
+ destinations: pdfModel.catalog.destinations,
+ outline: pdfModel.catalog.documentOutline,
+ info: pdfModel.getDocumentInfo(),
+ metadata: pdfModel.catalog.metadata,
+ encrypted: !!pdfModel.xref.encrypt
+ };
+ handler.send('GetDoc', {pdfInfo: doc});
});
- handler.on('page_request', function wphSetupPageRequest(pageNum) {
- pageNum = parseInt(pageNum);
+ handler.on('GetPageRequest', function wphSetupGetPage(data) {
+ var pageNumber = data.pageIndex + 1;
+ var pdfPage = pdfModel.getPage(pageNumber);
+ var page = {
+ pageIndex: data.pageIndex,
+ rotate: pdfPage.rotate,
+ ref: pdfPage.ref,
+ view: pdfPage.view
+ };
+ handler.send('GetPage', {pageInfo: page});
+ });
+
+ handler.on('GetData', function wphSetupGetData(data, promise) {
+ promise.resolve(pdfModel.stream.bytes);
+ });
+
+ handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
+ var pdfPage = pdfModel.getPage(data.pageIndex + 1);
+ handler.send('GetAnnotations', {
+ pageIndex: data.pageIndex,
+ annotations: pdfPage.getAnnotations()
+ });
+ });
+ handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
+ var pageNum = data.pageIndex + 1;
// The following code does quite the same as
// Page.prototype.startRendering, but stops at one point and sends the
@@ -28947,7 +30431,7 @@ var WorkerMessageHandler = {
};
}
- handler.send('page_error', {
+ handler.send('PageError', {
pageNum: pageNum,
error: e
});
@@ -28965,13 +30449,30 @@ var WorkerMessageHandler = {
fonts[dep] = true;
}
}
-
- handler.send('page', {
- pageNum: pageNum,
+ handler.send('RenderPage', {
+ pageIndex: data.pageIndex,
operatorList: operatorList,
depFonts: Object.keys(fonts)
});
}, this);
+
+ handler.on('GetTextContent', function wphExtractText(data, promise) {
+ var pageNum = data.pageIndex + 1;
+ var start = Date.now();
+
+ var textContent = '';
+ try {
+ var page = pdfModel.getPage(pageNum);
+ textContent = page.extractTextContent();
+ promise.resolve(textContent);
+ } catch (e) {
+ // Skip errored pages
+ promise.reject(e);
+ }
+
+ console.log('text indexing: page=%d - time=%dms',
+ pageNum, Date.now() - start);
+ });
}
};
@@ -29012,10 +30513,22 @@ var workerConsole = {
if (typeof window === 'undefined') {
globalScope.console = workerConsole;
+ // Add a logger so we can pass warnings on to the main thread, errors will
+ // throw an exception which will be forwarded on automatically.
+ PDFJS.LogManager.addLogger({
+ warn: function(msg) {
+ postMessage({
+ action: '_warn',
+ data: msg
+ });
+ }
+ });
+
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: */
@@ -29655,7 +31168,10 @@ var JpegImage = (function jpegImage() {
tableData[z] = data[offset++];
}
} else if ((quantizationTableSpec >> 4) === 1) { //16 bit
- tableData[j] = readUint16();
+ for (j = 0; j < 64; j++) {
+ var z = dctZigZag[j];
+ tableData[z] = readUint16();
+ }
} else
throw "DQT: invalid table spec";
quantizationTables[quantizationTableSpec & 15] = tableData;
@@ -29670,7 +31186,8 @@ var JpegImage = (function jpegImage() {
frame.precision = data[offset++];
frame.scanLines = readUint16();
frame.samplesPerLine = readUint16();
- frame.components = [];
+ frame.components = {};
+ frame.componentsOrder = [];
var componentsCount = data[offset++], componentId;
var maxH = 0, maxV = 0;
for (i = 0; i < componentsCount; i++) {
@@ -29678,6 +31195,7 @@ var JpegImage = (function jpegImage() {
var h = data[offset + 1] >> 4;
var v = data[offset + 1] & 15;
var qId = data[offset + 2];
+ frame.componentsOrder.push(componentId);
frame.components[componentId] = {
h: h,
v: v,
@@ -29746,14 +31264,13 @@ var JpegImage = (function jpegImage() {
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
- });
- }
+ for (var i = 0; i < frame.componentsOrder.length; i++) {
+ var component = frame.components[frame.componentsOrder[i]];
+ this.components.push({
+ lines: buildComponentData(frame, component),
+ scaleX: component.h / frame.maxH,
+ scaleY: component.v / frame.maxV
+ });
}
},
getData: function getData(width, height) {
@@ -29926,7 +31443,8 @@ var JpegImage = (function jpegImage() {
};
return constructor;
-})();/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+})();
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
@@ -31788,6 +33306,7 @@ var JpxImage = (function JpxImageClosure() {
return JpxImage;
})();
+
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
@@ -32220,14 +33739,35 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
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 fixMetadata(meta) {
+ return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
+ var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
+ function(code, d1, d2, d3) {
+ return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+ });
+ var chars = '';
+ for (var i = 0; i < bytes.length; i += 2) {
+ var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+ chars += code >= 32 && code < 127 && code != 60 && code != 62 &&
+ code != 38 && false ? String.fromCharCode(code) :
+ '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
+ }
+ return '>' + chars;
+ });
+ }
+
function Metadata(meta) {
if (typeof meta === 'string') {
+ // Ghostscript produces invalid metadata
+ meta = fixMetadata(meta);
+
var parser = new DOMParser();
meta = parser.parseFromString(meta, 'application/xml');
} else if (!(meta instanceof Document)) {
diff --git a/apps/files_pdfviewer/js/pdfjs/compatibility.js b/apps/files_pdfviewer/js/pdfjs/compatibility.js
new file mode 100644
index 00000000000..528841bb614
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/compatibility.js
@@ -0,0 +1,340 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+// Checking if the typed arrays are supported
+(function checkTypedArrayCompatibility() {
+ if (typeof Uint8Array !== 'undefined') {
+ // some mobile version might not support Float64Array
+ if (typeof Float64Array === 'undefined')
+ window.Float64Array = Float32Array;
+
+ return;
+ }
+
+ function subarray(start, end) {
+ return new TypedArray(this.slice(start, end));
+ }
+
+ function setArrayOffset(array, offset) {
+ if (arguments.length < 2)
+ offset = 0;
+ for (var i = 0, n = array.length; i < n; ++i, ++offset)
+ this[offset] = array[i] & 0xFF;
+ }
+
+ function TypedArray(arg1) {
+ var result;
+ if (typeof arg1 === 'number') {
+ result = [];
+ for (var i = 0; i < arg1; ++i)
+ result[i] = 0;
+ } else
+ result = arg1.slice(0);
+
+ result.subarray = subarray;
+ result.buffer = result;
+ result.byteLength = result.length;
+ result.set = setArrayOffset;
+
+ if (typeof arg1 === 'object' && arg1.buffer)
+ result.buffer = arg1.buffer;
+
+ return result;
+ }
+
+ window.Uint8Array = TypedArray;
+
+ // we don't need support for set, byteLength for 32-bit array
+ // so we can use the TypedArray as well
+ window.Uint32Array = TypedArray;
+ window.Int32Array = TypedArray;
+ window.Uint16Array = TypedArray;
+ window.Float32Array = TypedArray;
+ window.Float64Array = TypedArray;
+})();
+
+// Object.create() ?
+(function checkObjectCreateCompatibility() {
+ if (typeof Object.create !== 'undefined')
+ return;
+
+ Object.create = function objectCreate(proto) {
+ var constructor = function objectCreateConstructor() {};
+ constructor.prototype = proto;
+ return new constructor();
+ };
+})();
+
+// Object.defineProperty() ?
+(function checkObjectDefinePropertyCompatibility() {
+ if (typeof Object.defineProperty !== 'undefined')
+ return;
+
+ Object.defineProperty = function objectDefineProperty(obj, name, def) {
+ delete obj[name];
+ if ('get' in def)
+ obj.__defineGetter__(name, def['get']);
+ if ('set' in def)
+ obj.__defineSetter__(name, def['set']);
+ if ('value' in def) {
+ obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
+ this.__defineGetter__(name, function objectDefinePropertyGetter() {
+ return value;
+ });
+ return value;
+ });
+ obj[name] = def.value;
+ }
+ };
+})();
+
+// Object.keys() ?
+(function checkObjectKeysCompatibility() {
+ if (typeof Object.keys !== 'undefined')
+ return;
+
+ Object.keys = function objectKeys(obj) {
+ var result = [];
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i))
+ result.push(i);
+ }
+ return result;
+ };
+})();
+
+// No XMLHttpRequest.response ?
+(function checkXMLHttpRequestResponseCompatibility() {
+ var xhrPrototype = XMLHttpRequest.prototype;
+ if ('response' in xhrPrototype ||
+ 'mozResponseArrayBuffer' in xhrPrototype ||
+ 'mozResponse' in xhrPrototype ||
+ 'responseArrayBuffer' in xhrPrototype)
+ return;
+ // IE ?
+ if (typeof VBArray !== 'undefined') {
+ Object.defineProperty(xhrPrototype, 'response', {
+ get: function xmlHttpRequestResponseGet() {
+ return new Uint8Array(new VBArray(this.responseBody).toArray());
+ }
+ });
+ Object.defineProperty(xhrPrototype, 'overrideMimeType', {
+ value: function xmlHttpRequestOverrideMimeType(mimeType) {}
+ });
+ return;
+ }
+
+ // other browsers
+ function responseTypeSetter() {
+ // will be only called to set "arraybuffer"
+ this.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+ if (typeof xhrPrototype.overrideMimeType === 'function') {
+ Object.defineProperty(xhrPrototype, 'responseType',
+ { set: responseTypeSetter });
+ }
+ function responseGetter() {
+ var text = this.responseText;
+ var i, n = text.length;
+ var result = new Uint8Array(n);
+ for (i = 0; i < n; ++i)
+ result[i] = text.charCodeAt(i) & 0xFF;
+ return result;
+ }
+ Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
+})();
+
+// window.btoa (base64 encode function) ?
+(function checkWindowBtoaCompatibility() {
+ if ('btoa' in window)
+ return;
+
+ var digits =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+
+ window.btoa = function windowBtoa(chars) {
+ var buffer = '';
+ var i, n;
+ for (i = 0, n = chars.length; i < n; i += 3) {
+ var b1 = chars.charCodeAt(i) & 0xFF;
+ var b2 = chars.charCodeAt(i + 1) & 0xFF;
+ var b3 = chars.charCodeAt(i + 2) & 0xFF;
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
+ var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
+ var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
+ buffer += (digits.charAt(d1) + digits.charAt(d2) +
+ digits.charAt(d3) + digits.charAt(d4));
+ }
+ return buffer;
+ };
+})();
+
+// Function.prototype.bind ?
+(function checkFunctionPrototypeBindCompatibility() {
+ if (typeof Function.prototype.bind !== 'undefined')
+ return;
+
+ Function.prototype.bind = function functionPrototypeBind(obj) {
+ var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
+ var bound = function functionPrototypeBindBound() {
+ var args = Array.prototype.concat.apply(headArgs, arguments);
+ return fn.apply(obj, args);
+ };
+ return bound;
+ };
+})();
+
+// IE9 text/html data URI
+(function checkDocumentDocumentModeCompatibility() {
+ if (!('documentMode' in document) || document.documentMode !== 9)
+ return;
+ // overriding the src property
+ var originalSrcDescriptor = Object.getOwnPropertyDescriptor(
+ HTMLIFrameElement.prototype, 'src');
+ Object.defineProperty(HTMLIFrameElement.prototype, 'src', {
+ get: function htmlIFrameElementPrototypeSrcGet() { return this.$src; },
+ set: function htmlIFrameElementPrototypeSrcSet(src) {
+ this.$src = src;
+ if (src.substr(0, 14) != 'data:text/html') {
+ originalSrcDescriptor.set.call(this, src);
+ return;
+ }
+ // for text/html, using blank document and then
+ // document's open, write, and close operations
+ originalSrcDescriptor.set.call(this, 'about:blank');
+ setTimeout((function htmlIFrameElementPrototypeSrcOpenWriteClose() {
+ var doc = this.contentDocument;
+ doc.open('text/html');
+ doc.write(src.substr(src.indexOf(',') + 1));
+ doc.close();
+ }).bind(this), 0);
+ },
+ enumerable: true
+ });
+})();
+
+// HTMLElement dataset property
+(function checkDatasetProperty() {
+ var div = document.createElement('div');
+ if ('dataset' in div)
+ return; // dataset property exists
+
+ Object.defineProperty(HTMLElement.prototype, 'dataset', {
+ get: function() {
+ if (this._dataset)
+ return this._dataset;
+
+ var dataset = {};
+ for (var j = 0, jj = this.attributes.length; j < jj; j++) {
+ var attribute = this.attributes[j];
+ if (attribute.name.substring(0, 5) != 'data-')
+ continue;
+ var key = attribute.name.substring(5).replace(/\-([a-z])/g,
+ function(all, ch) { return ch.toUpperCase(); });
+ dataset[key] = attribute.value;
+ }
+
+ Object.defineProperty(this, '_dataset', {
+ value: dataset,
+ writable: false,
+ enumerable: false
+ });
+ return dataset;
+ },
+ enumerable: true
+ });
+})();
+
+// HTMLElement classList property
+(function checkClassListProperty() {
+ var div = document.createElement('div');
+ if ('classList' in div)
+ return; // classList property exists
+
+ function changeList(element, itemName, add, remove) {
+ var s = element.className || '';
+ var list = s.split(/\s+/g);
+ if (list[0] == '') list.shift();
+ var index = list.indexOf(itemName);
+ if (index < 0 && add)
+ list.push(itemName);
+ if (index >= 0 && remove)
+ list.splice(index, 1);
+ element.className = list.join(' ');
+ }
+
+ var classListPrototype = {
+ add: function(name) {
+ changeList(this.element, name, true, false);
+ },
+ remove: function(name) {
+ changeList(this.element, name, false, true);
+ },
+ toggle: function(name) {
+ changeList(this.element, name, true, true);
+ }
+ };
+
+ Object.defineProperty(HTMLElement.prototype, 'classList', {
+ get: function() {
+ if (this._classList)
+ return this._classList;
+
+ var classList = Object.create(classListPrototype, {
+ element: {
+ value: this,
+ writable: false,
+ enumerable: true
+ }
+ });
+ Object.defineProperty(this, '_classList', {
+ value: classList,
+ writable: false,
+ enumerable: false
+ });
+ return classList;
+ },
+ enumerable: true
+ });
+})();
+
+// Check console compatability
+(function checkConsoleCompatibility() {
+ if (typeof console == 'undefined') {
+ console = {log: function() {}};
+ }
+})();
+
+// Check onclick compatibility in Opera
+(function checkOnClickCompatibility() {
+ // workaround for reported Opera bug DSK-354448:
+ // onclick fires on disabled buttons with opaque content
+ function ignoreIfTargetDisabled(event) {
+ if (isDisabled(event.target)) {
+ event.stopPropagation();
+ }
+ }
+ function isDisabled(node) {
+ return node.disabled || (node.parentNode && isDisabled(node.parentNode));
+ }
+ if (navigator.userAgent.indexOf('Opera') != -1) {
+ // use browser detection since we cannot feature-check this bug
+ document.addEventListener('click', ignoreIfTargetDisabled, true);
+ }
+})();
+
+// Checks if navigator.language is supported
+(function checkNavigatorLanguage() {
+ if ('language' in navigator)
+ return;
+ Object.defineProperty(navigator, 'language', {
+ get: function navigatorLanguage() {
+ var language = navigator.userLanguage || 'en-US';
+ return language.substring(0, 2).toLowerCase() +
+ language.substring(2).toUpperCase();
+ },
+ enumerable: true
+ });
+})();
diff --git a/apps/files_pdfviewer/js/pdfjs/update.sh b/apps/files_pdfviewer/js/pdfjs/update.sh
index 599f6338602..df100e780ba 100755
--- a/apps/files_pdfviewer/js/pdfjs/update.sh
+++ b/apps/files_pdfviewer/js/pdfjs/update.sh
@@ -1,3 +1,6 @@
cd build
rm pdf.js
wget http://mozilla.github.com/pdf.js/build/pdf.js
+wget http://mozilla.github.com/pdf.js/web/compatibility.js
+wget http://mozilla.github.com/pdf.js/web/viewer.js
+
diff --git a/apps/files_pdfviewer/js/pdfjs/viewer.js b/apps/files_pdfviewer/js/pdfjs/viewer.js
new file mode 100644
index 00000000000..8a568e6a749
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/viewer.js
@@ -0,0 +1,1940 @@
+/* -*- 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 kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf';
+var kDefaultScale = 'auto';
+var kDefaultScaleDelta = 1.1;
+var kUnknownScale = 0;
+var kCacheSize = 20;
+var kCssUnits = 96.0 / 72.0;
+var kScrollbarPadding = 40;
+var kMinScale = 0.25;
+var kMaxScale = 4.0;
+var kImageDirectory = './images/';
+var kSettingsMemory = 20;
+
+var mozL10n = document.mozL10n || document.webL10n;
+
+function getFileName(url) {
+ var anchor = url.indexOf('#');
+ var query = url.indexOf('?');
+ var end = Math.min(
+ anchor > 0 ? anchor : url.length,
+ query > 0 ? query : url.length);
+ return url.substring(url.lastIndexOf('/', end) + 1, end);
+}
+
+var Cache = function cacheCache(size) {
+ var data = [];
+ this.push = function cachePush(view) {
+ var i = data.indexOf(view);
+ if (i >= 0)
+ data.splice(i);
+ data.push(view);
+ if (data.length > size)
+ data.shift().destroy();
+ };
+};
+
+var ProgressBar = (function ProgressBarClosure() {
+
+ function clamp(v, min, max) {
+ return Math.min(Math.max(v, min), max);
+ }
+
+ function ProgressBar(id, opts) {
+
+ // Fetch the sub-elements for later
+ this.div = document.querySelector(id + ' .progress');
+
+ // Get options, with sensible defaults
+ this.height = opts.height || 100;
+ this.width = opts.width || 100;
+ this.units = opts.units || '%';
+ this.percent = opts.percent || 0;
+
+ // Initialize heights
+ this.div.style.height = this.height + this.units;
+ }
+
+ ProgressBar.prototype = {
+
+ updateBar: function ProgressBar_updateBar() {
+ var progressSize = this.width * this._percent / 100;
+
+ if (this._percent > 95)
+ this.div.classList.add('full');
+
+ this.div.style.width = progressSize + this.units;
+ },
+
+ get percent() {
+ return this._percent;
+ },
+
+ set percent(val) {
+ this._percent = clamp(val, 0, 100);
+ this.updateBar();
+ }
+ };
+
+ return ProgressBar;
+})();
+
+var RenderingQueue = (function RenderingQueueClosure() {
+ function RenderingQueue() {
+ this.items = [];
+ }
+
+ RenderingQueue.prototype = {
+ enqueueDraw: function RenderingQueueEnqueueDraw(item) {
+ if (!item.drawingRequired())
+ return; // as no redraw required, no need for queueing.
+
+ this.items.push(item);
+ if (this.items.length > 1)
+ return; // not first item
+
+ item.draw(this.continueExecution.bind(this));
+ },
+ continueExecution: function RenderingQueueContinueExecution() {
+ var item = this.items.shift();
+
+ if (this.items.length == 0)
+ return; // queue is empty
+
+ item = this.items[0];
+ item.draw(this.continueExecution.bind(this));
+ }
+ };
+
+ return RenderingQueue;
+})();
+
+var FirefoxCom = (function FirefoxComClosure() {
+ return {
+ /**
+ * Creates an event that the extension is listening for and will
+ * synchronously respond to.
+ * NOTE: It is reccomended to use request() instead since one day we may not
+ * be able to synchronously reply.
+ * @param {String} action The action to trigger.
+ * @param {String} data Optional data to send.
+ * @return {*} The response.
+ */
+ requestSync: function(action, data) {
+ var request = document.createTextNode('');
+ request.setUserData('action', action, null);
+ request.setUserData('data', data, null);
+ request.setUserData('sync', true, null);
+ document.documentElement.appendChild(request);
+
+ var sender = document.createEvent('Events');
+ sender.initEvent('pdf.js.message', true, false);
+ request.dispatchEvent(sender);
+ var response = request.getUserData('response');
+ document.documentElement.removeChild(request);
+ return response;
+ },
+ /**
+ * Creates an event that the extension is listening for and will
+ * asynchronously respond by calling the callback.
+ * @param {String} action The action to trigger.
+ * @param {String} data Optional data to send.
+ * @param {Function} callback Optional response callback that will be called
+ * with one data argument.
+ */
+ request: function(action, data, callback) {
+ var request = document.createTextNode('');
+ request.setUserData('action', action, null);
+ request.setUserData('data', data, null);
+ request.setUserData('sync', false, null);
+ if (callback) {
+ request.setUserData('callback', callback, null);
+
+ document.addEventListener('pdf.js.response', function listener(event) {
+ var node = event.target,
+ callback = node.getUserData('callback'),
+ response = node.getUserData('response');
+
+ document.documentElement.removeChild(node);
+
+ document.removeEventListener('pdf.js.response', listener, false);
+ return callback(response);
+ }, false);
+ }
+ document.documentElement.appendChild(request);
+
+ var sender = document.createEvent('HTMLEvents');
+ sender.initEvent('pdf.js.message', true, false);
+ return request.dispatchEvent(sender);
+ }
+ };
+})();
+
+// Settings Manager - This is a utility for saving settings
+// First we see if localStorage is available
+// If not, we use FUEL in FF
+var Settings = (function SettingsClosure() {
+ var isLocalStorageEnabled = (function localStorageEnabledTest() {
+ // Feature test as per http://diveintohtml5.info/storage.html
+ // The additional localStorage call is to get around a FF quirk, see
+ // bug #495747 in bugzilla
+ try {
+ return 'localStorage' in window && window['localStorage'] !== null &&
+ localStorage;
+ } catch (e) {
+ return false;
+ }
+ })();
+
+ var isFirefoxExtension = PDFJS.isFirefoxExtension;
+
+ function Settings(fingerprint) {
+ var database = null;
+ var index;
+ if (isFirefoxExtension)
+ database = FirefoxCom.requestSync('getDatabase', null) || '{}';
+ else if (isLocalStorageEnabled)
+ database = localStorage.getItem('database') || '{}';
+ else
+ return false;
+
+ database = JSON.parse(database);
+ if (!('files' in database))
+ database.files = [];
+ if (database.files.length >= kSettingsMemory)
+ database.files.shift();
+ for (var i = 0, length = database.files.length; i < length; i++) {
+ var branch = database.files[i];
+ if (branch.fingerprint == fingerprint) {
+ index = i;
+ break;
+ }
+ }
+ if (typeof index != 'number')
+ index = database.files.push({fingerprint: fingerprint}) - 1;
+ this.file = database.files[index];
+ this.database = database;
+ }
+
+ Settings.prototype = {
+ set: function settingsSet(name, val) {
+ if (!('file' in this))
+ return false;
+
+ var file = this.file;
+ file[name] = val;
+ var database = JSON.stringify(this.database);
+ if (isFirefoxExtension)
+ FirefoxCom.requestSync('setDatabase', database);
+ else if (isLocalStorageEnabled)
+ localStorage.setItem('database', database);
+ },
+
+ get: function settingsGet(name, defaultValue) {
+ if (!('file' in this))
+ return defaultValue;
+
+ return this.file[name] || defaultValue;
+ }
+ };
+
+ return Settings;
+})();
+
+var cache = new Cache(kCacheSize);
+var renderingQueue = new RenderingQueue();
+var currentPageNumber = 1;
+
+var PDFView = {
+ pages: [],
+ thumbnails: [],
+ currentScale: kUnknownScale,
+ currentScaleValue: null,
+ initialBookmark: document.location.hash.substring(1),
+ startedTextExtraction: false,
+ pageText: [],
+ container: null,
+ initialized: false,
+ fellback: false,
+ pdfDocument: null,
+ // called once when the document is loaded
+ initialize: function pdfViewInitialize() {
+ this.container = document.getElementById('viewer');
+ this.initialized = true;
+ },
+
+ setScale: function pdfViewSetScale(val, resetAutoSettings) {
+ if (val == this.currentScale)
+ return;
+
+ var pages = this.pages;
+ for (var i = 0; i < pages.length; i++)
+ pages[i].update(val * kCssUnits);
+
+ if (this.currentScale != val)
+ this.pages[this.page - 1].scrollIntoView();
+ this.currentScale = val;
+
+ var event = document.createEvent('UIEvents');
+ event.initUIEvent('scalechange', false, false, window, 0);
+ event.scale = val;
+ event.resetAutoSettings = resetAutoSettings;
+ window.dispatchEvent(event);
+ },
+
+ parseScale: function pdfViewParseScale(value, resetAutoSettings) {
+ if ('custom' == value)
+ return;
+
+ var scale = parseFloat(value);
+ this.currentScaleValue = value;
+ if (scale) {
+ this.setScale(scale, true);
+ return;
+ }
+
+ var container = this.container;
+ var currentPage = this.pages[this.page - 1];
+ var pageWidthScale = (container.clientWidth - kScrollbarPadding) /
+ currentPage.width * currentPage.scale / kCssUnits;
+ var pageHeightScale = (container.clientHeight - kScrollbarPadding) /
+ currentPage.height * currentPage.scale / kCssUnits;
+ switch (value) {
+ case 'page-actual':
+ this.setScale(1, resetAutoSettings);
+ break;
+ case 'page-width':
+ this.setScale(pageWidthScale, resetAutoSettings);
+ break;
+ case 'page-height':
+ this.setScale(pageHeightScale, resetAutoSettings);
+ break;
+ case 'page-fit':
+ this.setScale(
+ Math.min(pageWidthScale, pageHeightScale), resetAutoSettings);
+ break;
+ case 'auto':
+ this.setScale(Math.min(1.0, pageWidthScale), resetAutoSettings);
+ break;
+ }
+
+ selectScaleOption(value);
+ },
+
+ zoomIn: function pdfViewZoomIn() {
+ var newScale = (this.currentScale * kDefaultScaleDelta).toFixed(2);
+ newScale = Math.min(kMaxScale, newScale);
+ this.parseScale(newScale, true);
+ },
+
+ zoomOut: function pdfViewZoomOut() {
+ var newScale = (this.currentScale / kDefaultScaleDelta).toFixed(2);
+ newScale = Math.max(kMinScale, newScale);
+ this.parseScale(newScale, true);
+ },
+
+ set page(val) {
+ var pages = this.pages;
+ var input = document.getElementById('pageNumber');
+ if (!(0 < val && val <= pages.length)) {
+ var event = document.createEvent('UIEvents');
+ event.initUIEvent('pagechange', false, false, window, 0);
+ event.pageNumber = this.page;
+ window.dispatchEvent(event);
+ return;
+ }
+
+ pages[val - 1].updateStats();
+ currentPageNumber = val;
+ var event = document.createEvent('UIEvents');
+ event.initUIEvent('pagechange', false, false, window, 0);
+ event.pageNumber = val;
+ window.dispatchEvent(event);
+
+ // checking if the this.page was called from the updateViewarea function:
+ // avoiding the creation of two "set page" method (internal and public)
+ if (updateViewarea.inProgress)
+ return;
+
+ // Avoid scrolling the first page during loading
+ if (this.loading && val == 1)
+ return;
+
+ pages[val - 1].scrollIntoView();
+ },
+
+ get page() {
+ return currentPageNumber;
+ },
+
+ open: function pdfViewOpen(url, scale, password) {
+ var parameters = {password: password};
+ if (typeof url === 'string') { // URL
+ this.url = url;
+ document.title = decodeURIComponent(getFileName(url)) || url;
+ parameters.url = url;
+ } else if (url && 'byteLength' in url) { // ArrayBuffer
+ parameters.data = url;
+ }
+
+// if (!PDFView.loadingBar) {
+// PDFView.loadingBar = new ProgressBar('#loadingBar', {});
+// }
+
+ this.container = document.getElementById('viewer');
+
+ this.pdfDocument = null;
+ var self = this;
+ self.loading = true;
+ PDFJS.getDocument(parameters).then(
+ function getDocumentCallback(pdfDocument) {
+ self.load(pdfDocument, scale);
+ self.loading = false;
+ },
+ function getDocumentError(message, exception) {
+ if (exception.name === 'PasswordException') {
+ if (exception.code === 'needpassword') {
+ var promptString = mozL10n.get('request_password', null,
+ 'PDF is protected by a password:');
+ password = prompt(promptString);
+ if (password && password.length > 0) {
+ return PDFView.open(url, scale, password);
+ }
+ }
+ }
+
+ var loadingIndicator = document.getElementById('loading');
+ loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
+ null, 'Error');
+ var moreInfo = {
+ message: message
+ };
+ self.error(mozL10n.get('loading_error', null,
+ 'An error occurred while loading the PDF.'), moreInfo);
+ self.loading = false;
+ },
+ function getDocumentProgress(progressData) {
+ self.progress(progressData.loaded / progressData.total);
+ }
+ );
+ },
+
+ download: function pdfViewDownload() {
+ function noData() {
+ FirefoxCom.request('download', { originalUrl: url });
+ }
+
+ var url = this.url.split('#')[0];
+ if (PDFJS.isFirefoxExtension) {
+ // Document isn't ready just try to download with the url.
+ if (!this.pdfDocument) {
+ noData();
+ return;
+ }
+ this.pdfDocument.getData().then(
+ function getDataSuccess(data) {
+ var bb = new MozBlobBuilder();
+ bb.append(data.buffer);
+ var blobUrl = window.URL.createObjectURL(
+ bb.getBlob('application/pdf'));
+
+ FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url },
+ function response(err) {
+ if (err) {
+ // This error won't really be helpful because it's likely the
+ // fallback won't work either (or is already open).
+ PDFView.error('PDF failed to download.');
+ }
+ window.URL.revokeObjectURL(blobUrl);
+ }
+ );
+ },
+ noData // Error ocurred try downloading with just the url.
+ );
+ } else {
+ url += '#pdfjs.action=download', '_parent';
+ window.open(url, '_parent');
+ }
+ },
+
+ fallback: function pdfViewFallback() {
+ if (!PDFJS.isFirefoxExtension)
+ return;
+ // Only trigger the fallback once so we don't spam the user with messages
+ // for one PDF.
+ if (this.fellback)
+ return;
+ this.fellback = true;
+ var url = this.url.split('#')[0];
+ FirefoxCom.request('fallback', url, function response(download) {
+ if (!download)
+ return;
+ PDFView.download();
+ });
+ },
+
+ navigateTo: function pdfViewNavigateTo(dest) {
+ if (typeof dest === 'string')
+ dest = this.destinations[dest];
+ if (!(dest instanceof Array))
+ return; // invalid destination
+ // dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
+ var destRef = dest[0];
+ var pageNumber = destRef instanceof Object ?
+ this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : (destRef + 1);
+ if (pageNumber > this.pages.length)
+ pageNumber = this.pages.length;
+ if (pageNumber) {
+ this.page = pageNumber;
+ var currentPage = this.pages[pageNumber - 1];
+ currentPage.scrollIntoView(dest);
+ }
+ },
+
+ getDestinationHash: function pdfViewGetDestinationHash(dest) {
+ if (typeof dest === 'string')
+ return PDFView.getAnchorUrl('#' + escape(dest));
+ if (dest instanceof Array) {
+ var destRef = dest[0]; // see navigateTo method for dest format
+ var pageNumber = destRef instanceof Object ?
+ this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] :
+ (destRef + 1);
+ if (pageNumber) {
+ var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber);
+ var destKind = dest[1];
+ if (typeof destKind === 'object' && 'name' in destKind &&
+ destKind.name == 'XYZ') {
+ var scale = (dest[4] || this.currentScale);
+ pdfOpenParams += '&zoom=' + (scale * 100);
+ if (dest[2] || dest[3]) {
+ pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
+ }
+ }
+ return pdfOpenParams;
+ }
+ }
+ return '';
+ },
+
+ /**
+ * For the firefox extension we prefix the full url on anchor links so they
+ * don't come up as resource:// urls and so open in new tab/window works.
+ * @param {String} anchor The anchor hash include the #.
+ */
+ getAnchorUrl: function getAnchorUrl(anchor) {
+ if (PDFJS.isFirefoxExtension)
+ return this.url.split('#')[0] + anchor;
+ return anchor;
+ },
+
+ /**
+ * Show the error box.
+ * @param {String} message A message that is human readable.
+ * @param {Object} moreInfo (optional) Further information about the error
+ * that is more technical. Should have a 'message'
+ * and optionally a 'stack' property.
+ */
+ error: function pdfViewError(message, moreInfo) {
+ var moreInfoText = mozL10n.get('error_build', {build: PDFJS.build},
+ 'PDF.JS Build: {{build}}') + '\n';
+ if (moreInfo) {
+ moreInfoText +=
+ mozL10n.get('error_message', {message: moreInfo.message},
+ 'Message: {{message}}');
+ if (moreInfo.stack) {
+ moreInfoText += '\n' +
+ mozL10n.get('error_stack', {stack: moreInfo.stack},
+ 'Stack: {{stack}}');
+ } else {
+ if (moreInfo.filename) {
+ moreInfoText += '\n' +
+ mozL10n.get('error_file', {file: moreInfo.filename},
+ 'File: {{file}}');
+ }
+ if (moreInfo.lineNumber) {
+ moreInfoText += '\n' +
+ mozL10n.get('error_line', {line: moreInfo.lineNumber},
+ 'Line: {{line}}');
+ }
+ }
+ }
+ if (PDFJS.isFirefoxExtension) {
+ console.error(message + '\n' + moreInfoText);
+ this.fallback();
+ return;
+ }
+ var errorWrapper = document.getElementById('errorWrapper');
+ errorWrapper.removeAttribute('hidden');
+
+ var errorMessage = document.getElementById('errorMessage');
+ errorMessage.textContent = message;
+
+ var closeButton = document.getElementById('errorClose');
+ closeButton.onclick = function() {
+ errorWrapper.setAttribute('hidden', 'true');
+ };
+
+ var errorMoreInfo = document.getElementById('errorMoreInfo');
+ var moreInfoButton = document.getElementById('errorShowMore');
+ var lessInfoButton = document.getElementById('errorShowLess');
+ moreInfoButton.onclick = function() {
+ errorMoreInfo.removeAttribute('hidden');
+ moreInfoButton.setAttribute('hidden', 'true');
+ lessInfoButton.removeAttribute('hidden');
+ };
+ lessInfoButton.onclick = function() {
+ errorMoreInfo.setAttribute('hidden', 'true');
+ moreInfoButton.removeAttribute('hidden');
+ lessInfoButton.setAttribute('hidden', 'true');
+ };
+ moreInfoButton.removeAttribute('hidden');
+ lessInfoButton.setAttribute('hidden', 'true');
+ errorMoreInfo.value = moreInfoText;
+
+ errorMoreInfo.rows = moreInfoText.split('\n').length - 1;
+ },
+
+ progress: function pdfViewProgress(level) {
+ var percent = Math.round(level * 100);
+ var loadingIndicator = document.getElementById('loading');
+ loadingIndicator.textContent = mozL10n.get('loading', {percent: percent},
+ 'Loading... {{percent}}%');
+
+// PDFView.loadingBar.percent = percent;
+ },
+
+ load: function pdfViewLoad(pdfDocument, scale) {
+ function bindOnAfterDraw(pageView, thumbnailView) {
+ // when page is painted, using the image as thumbnail base
+ pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() {
+ thumbnailView.setImage(pageView.canvas);
+ preDraw();
+ };
+ }
+
+ this.pdfDocument = pdfDocument;
+
+// var errorWrapper = document.getElementById('errorWrapper');
+// errorWrapper.setAttribute('hidden', 'true');
+
+ var loadingBox = document.getElementById('loading');
+ loadingBox.setAttribute('hidden', 'true');
+
+// var loadingBox = document.getElementById('loadingBox');
+// loadingBox.setAttribute('hidden', 'true');
+
+// var thumbsView = document.getElementById('thumbnailView');
+// thumbsView.parentNode.scrollTop = 0;
+
+// while (thumbsView.hasChildNodes())
+// thumbsView.removeChild(thumbsView.lastChild);
+
+// if ('_loadingInterval' in thumbsView)
+// clearInterval(thumbsView._loadingInterval);
+
+ var container = document.getElementById('viewer');
+ while (container.hasChildNodes())
+ container.removeChild(container.lastChild);
+
+ var pagesCount = pdfDocument.numPages;
+ var id = pdfDocument.fingerprint;
+ var storedHash = null;
+// document.getElementById('numPages').textContent =
+// mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}');
+ document.getElementById('numPages').innerHTML = pagesCount;
+ document.getElementById('pageNumber').max = pagesCount;
+ PDFView.documentFingerprint = id;
+ var store = PDFView.store = new Settings(id);
+ if (store.get('exists', false)) {
+ var page = store.get('page', '1');
+ var zoom = store.get('zoom', PDFView.currentScale);
+ var left = store.get('scrollLeft', '0');
+ var top = store.get('scrollTop', '0');
+
+ storedHash = 'page=' + page + '&zoom=' + zoom + ',' + left + ',' + top;
+ }
+
+ var pages = this.pages = [];
+ this.pageText = [];
+ this.startedTextExtraction = false;
+ var pagesRefMap = {};
+ var thumbnails = this.thumbnails = [];
+ var pagePromises = [];
+ for (var i = 1; i <= pagesCount; i++)
+ pagePromises.push(pdfDocument.getPage(i));
+ var self = this;
+ var pagesPromise = PDFJS.Promise.all(pagePromises);
+ pagesPromise.then(function(promisedPages) {
+ for (var i = 1; i <= pagesCount; i++) {
+ var page = promisedPages[i - 1];
+ var pageView = new PageView(container, page, i, scale,
+ page.stats, self.navigateTo.bind(self));
+// var thumbnailView = new ThumbnailView(thumbsView, page, i);
+// bindOnAfterDraw(pageView, thumbnailView);
+
+ pages.push(pageView);
+// thumbnails.push(thumbnailView);
+ var pageRef = page.ref;
+ pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i;
+ }
+
+ self.pagesRefMap = pagesRefMap;
+ });
+
+ var destinationsPromise = pdfDocument.getDestinations();
+ destinationsPromise.then(function(destinations) {
+ self.destinations = destinations;
+ });
+
+ // outline and initial view depends on destinations and pagesRefMap
+ PDFJS.Promise.all([pagesPromise, destinationsPromise]).then(function() {
+ pdfDocument.getOutline().then(function(outline) {
+ self.outline = new DocumentOutlineView(outline);
+ });
+
+ self.setInitialView(storedHash, scale);
+ });
+
+ pdfDocument.getMetadata().then(function(data) {
+ var info = data.info, metadata = data.metadata;
+ self.documentInfo = info;
+ self.metadata = metadata;
+
+ var pdfTitle;
+ if (metadata) {
+ if (metadata.has('dc:title'))
+ pdfTitle = metadata.get('dc:title');
+ }
+
+ if (!pdfTitle && info && info['Title'])
+ pdfTitle = info['Title'];
+
+ if (pdfTitle)
+ document.title = pdfTitle + ' - ' + document.title;
+ });
+ },
+
+ setInitialView: function pdfViewSetInitialView(storedHash, scale) {
+ // Reset the current scale, as otherwise the page's scale might not get
+ // updated if the zoom level stayed the same.
+ this.currentScale = 0;
+ this.currentScaleValue = null;
+ if (this.initialBookmark) {
+ this.setHash(this.initialBookmark);
+ this.initialBookmark = null;
+ }
+ else if (storedHash)
+ this.setHash(storedHash);
+ else if (scale) {
+ this.parseScale(scale, true);
+ this.page = 1;
+ }
+
+ if (PDFView.currentScale === kUnknownScale) {
+ // Scale was not initialized: invalid bookmark or scale was not specified.
+ // Setting the default one.
+ this.parseScale(kDefaultScale, true);
+ }
+ },
+
+ search: function pdfViewStartSearch() {
+ // Limit this function to run every <SEARCH_TIMEOUT>ms.
+ var SEARCH_TIMEOUT = 250;
+ var lastSeach = this.lastSearch;
+ var now = Date.now();
+ if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) {
+ if (!this.searchTimer) {
+ this.searchTimer = setTimeout(function resumeSearch() {
+ PDFView.search();
+ },
+ SEARCH_TIMEOUT - (now - lastSeach)
+ );
+ }
+ return;
+ }
+ this.searchTimer = null;
+ this.lastSearch = now;
+
+ function bindLink(link, pageNumber) {
+ link.href = '#' + pageNumber;
+ link.onclick = function searchBindLink() {
+ PDFView.page = pageNumber;
+ return false;
+ };
+ }
+
+ var searchResults = document.getElementById('searchResults');
+
+ var searchTermsInput = document.getElementById('searchTermsInput');
+ searchResults.removeAttribute('hidden');
+ searchResults.textContent = '';
+
+ var terms = searchTermsInput.value;
+
+ if (!terms)
+ return;
+
+ // simple search: removing spaces and hyphens, then scanning every
+ terms = terms.replace(/\s-/g, '').toLowerCase();
+ var index = PDFView.pageText;
+ var pageFound = false;
+ for (var i = 0, ii = index.length; i < ii; i++) {
+ var pageText = index[i].replace(/\s-/g, '').toLowerCase();
+ var j = pageText.indexOf(terms);
+ if (j < 0)
+ continue;
+
+ var pageNumber = i + 1;
+ var textSample = index[i].substr(j, 50);
+ var link = document.createElement('a');
+ bindLink(link, pageNumber);
+ link.textContent = 'Page ' + pageNumber + ': ' + textSample;
+ searchResults.appendChild(link);
+
+ pageFound = true;
+ }
+ if (!pageFound) {
+ searchResults.textContent = mozL10n.get('search_terms_not_found', null,
+ '(Not found)');
+ }
+ },
+
+ setHash: function pdfViewSetHash(hash) {
+ if (!hash)
+ return;
+
+ if (hash.indexOf('=') >= 0) {
+ var params = PDFView.parseQueryString(hash);
+ // borrowing syntax from "Parameters for Opening PDF Files"
+ if ('nameddest' in params) {
+ PDFView.navigateTo(params.nameddest);
+ return;
+ }
+ if ('page' in params) {
+ var pageNumber = (params.page | 0) || 1;
+ this.page = pageNumber;
+ if ('zoom' in params) {
+ var zoomArgs = params.zoom.split(','); // scale,left,top
+ // building destination array
+
+ // If the zoom value, it has to get divided by 100. If it is a string,
+ // it should stay as it is.
+ var zoomArg = zoomArgs[0];
+ var zoomArgNumber = parseFloat(zoomArg);
+ if (zoomArgNumber)
+ zoomArg = zoomArgNumber / 100;
+
+ var dest = [null, {name: 'XYZ'}, (zoomArgs[1] | 0),
+ (zoomArgs[2] | 0), zoomArg];
+ var currentPage = this.pages[pageNumber - 1];
+ currentPage.scrollIntoView(dest);
+ } else
+ this.page = params.page; // simple page
+ return;
+ }
+ } else if (/^\d+$/.test(hash)) // page number
+ this.page = hash;
+ else // named destination
+ PDFView.navigateTo(unescape(hash));
+ },
+
+ switchSidebarView: function pdfViewSwitchSidebarView(view) {
+ var thumbsView = document.getElementById('thumbnailView');
+ var outlineView = document.getElementById('outlineView');
+ var searchView = document.getElementById('searchView');
+
+ var thumbsButton = document.getElementById('viewThumbnail');
+ var outlineButton = document.getElementById('viewOutline');
+ var searchButton = document.getElementById('viewSearch');
+
+ switch (view) {
+ case 'thumbs':
+ thumbsButton.classList.add('toggled');
+ outlineButton.classList.remove('toggled');
+ searchButton.classList.remove('toggled');
+ thumbsView.classList.remove('hidden');
+ outlineView.classList.add('hidden');
+ searchView.classList.add('hidden');
+
+ updateThumbViewArea();
+ break;
+
+ case 'outline':
+ thumbsButton.classList.remove('toggled');
+ outlineButton.classList.add('toggled');
+ searchButton.classList.remove('toggled');
+ thumbsView.classList.add('hidden');
+ outlineView.classList.remove('hidden');
+ searchView.classList.add('hidden');
+
+ if (outlineButton.getAttribute('disabled'))
+ return;
+ break;
+
+ case 'search':
+ thumbsButton.classList.remove('toggled');
+ outlineButton.classList.remove('toggled');
+ searchButton.classList.add('toggled');
+ thumbsView.classList.add('hidden');
+ outlineView.classList.add('hidden');
+ searchView.classList.remove('hidden');
+
+ var searchTermsInput = document.getElementById('searchTermsInput');
+ searchTermsInput.focus();
+ // Start text extraction as soon as the search gets displayed.
+ this.extractText();
+ break;
+ }
+ },
+
+ extractText: function() {
+ if (this.startedTextExtraction)
+ return;
+ this.startedTextExtraction = true;
+ var self = this;
+ function extractPageText(pageIndex) {
+ self.pages[pageIndex].pdfPage.getTextContent().then(
+ function textContentResolved(textContent) {
+ self.pageText[pageIndex] = textContent;
+ self.search();
+ if ((pageIndex + 1) < self.pages.length)
+ extractPageText(pageIndex + 1);
+ }
+ );
+ };
+ extractPageText(0);
+ },
+
+ getVisiblePages: function pdfViewGetVisiblePages() {
+ var pages = this.pages;
+ var kBottomMargin = 10;
+ var kTopPadding = 30;
+ var visiblePages = [];
+
+ var currentHeight = kTopPadding + kBottomMargin;
+ //var container = this.container;
+ var container = document.getElementById('viewer');
+
+ // Add 1px to the scrolltop to give a little wiggle room if the math is off,
+ // this won't be needed if we calc current page number based off the middle
+ // of the screen instead of the top.
+ var containerTop = container.scrollTop + 1;
+ for (var i = 1; i <= pages.length; ++i) {
+ var page = pages[i - 1];
+ var pageHeight = page.height + kBottomMargin;
+ if (currentHeight + pageHeight > containerTop)
+ break;
+
+ currentHeight += pageHeight;
+ }
+
+ var containerBottom = containerTop + container.clientHeight;
+ for (; i <= pages.length && currentHeight < containerBottom; ++i) {
+ var singlePage = pages[i - 1];
+ visiblePages.push({ id: singlePage.id, y: currentHeight,
+ view: singlePage });
+ currentHeight += page.height + kBottomMargin;
+ }
+ return visiblePages;
+ },
+
+ getVisibleThumbs: function pdfViewGetVisibleThumbs() {
+ var thumbs = this.thumbnails;
+ var kBottomMargin = 15;
+ var visibleThumbs = [];
+
+ var view = document.getElementById('thumbnailView');
+ var currentHeight = kBottomMargin;
+
+ var top = view.scrollTop;
+ for (var i = 1; i <= thumbs.length; ++i) {
+ var thumb = thumbs[i - 1];
+ var thumbHeight = thumb.height * thumb.scaleY + kBottomMargin;
+ if (currentHeight + thumbHeight > top)
+ break;
+
+ currentHeight += thumbHeight;
+ }
+
+ var bottom = top + view.clientHeight;
+ for (; i <= thumbs.length && currentHeight < bottom; ++i) {
+ var singleThumb = thumbs[i - 1];
+ visibleThumbs.push({ id: singleThumb.id, y: currentHeight,
+ view: singleThumb });
+ currentHeight += singleThumb.height * singleThumb.scaleY + kBottomMargin;
+ }
+
+ return visibleThumbs;
+ },
+
+ // Helper function to parse query string (e.g. ?param1=value&parm2=...).
+ parseQueryString: function pdfViewParseQueryString(query) {
+ var parts = query.split('&');
+ var params = {};
+ for (var i = 0, ii = parts.length; i < parts.length; ++i) {
+ var param = parts[i].split('=');
+ var key = param[0];
+ var value = param.length > 1 ? param[1] : null;
+ params[unescape(key)] = unescape(value);
+ }
+ return params;
+ }
+};
+
+var PageView = function pageView(container, pdfPage, id, scale,
+ stats, navigateTo) {
+ this.id = id;
+ this.pdfPage = pdfPage;
+
+ this.scale = scale || 1.0;
+ this.viewport = this.pdfPage.getViewport(this.scale);
+
+ var anchor = document.createElement('a');
+ anchor.name = '' + this.id;
+
+ var div = document.createElement('div');
+ div.id = 'pageContainer' + this.id;
+ div.className = 'page';
+
+ container.appendChild(anchor);
+ container.appendChild(div);
+
+ this.destroy = function pageViewDestroy() {
+ this.update();
+ this.pdfPage.destroy();
+ };
+
+ this.update = function pageViewUpdate(scale) {
+ this.scale = scale || this.scale;
+ var viewport = this.pdfPage.getViewport(this.scale);
+
+ this.viewport = viewport;
+ div.style.width = viewport.width + 'px';
+ div.style.height = viewport.height + 'px';
+
+ while (div.hasChildNodes())
+ div.removeChild(div.lastChild);
+ div.removeAttribute('data-loaded');
+
+ delete this.canvas;
+
+ this.loadingIconDiv = document.createElement('div');
+ this.loadingIconDiv.className = 'loadingIcon';
+ div.appendChild(this.loadingIconDiv);
+ };
+
+ Object.defineProperty(this, 'width', {
+ get: function PageView_getWidth() {
+ return this.viewport.width;
+ },
+ enumerable: true
+ });
+
+ Object.defineProperty(this, 'height', {
+ get: function PageView_getHeight() {
+ return this.viewport.height;
+ },
+ enumerable: true
+ });
+
+ function setupAnnotations(pdfPage, viewport) {
+ function bindLink(link, dest) {
+ link.href = PDFView.getDestinationHash(dest);
+ link.onclick = function pageViewSetupLinksOnclick() {
+ if (dest)
+ PDFView.navigateTo(dest);
+ return false;
+ };
+ }
+ function createElementWithStyle(tagName, item) {
+ var rect = viewport.convertToViewportRectangle(item.rect);
+ rect = PDFJS.Util.normalizeRect(rect);
+ var element = document.createElement(tagName);
+ element.style.left = Math.floor(rect[0]) + 'px';
+ element.style.top = Math.floor(rect[1]) + 'px';
+ element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
+ element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
+ return element;
+ }
+ function createCommentAnnotation(type, item) {
+ var container = document.createElement('section');
+ container.className = 'annotComment';
+
+ var image = createElementWithStyle('img', item);
+ var type = item.type;
+ var rect = viewport.convertToViewportRectangle(item.rect);
+ rect = PDFJS.Util.normalizeRect(rect);
+ image.src = kImageDirectory + 'annotation-' + type.toLowerCase() + '.svg';
+ image.alt = mozL10n.get('text_annotation_type', {type: type},
+ '[{{type}} Annotation]');
+ var content = document.createElement('div');
+ content.setAttribute('hidden', true);
+ var title = document.createElement('h1');
+ var text = document.createElement('p');
+ content.style.left = Math.floor(rect[2]) + 'px';
+ content.style.top = Math.floor(rect[1]) + 'px';
+ title.textContent = item.title;
+
+ if (!item.content && !item.title) {
+ content.setAttribute('hidden', true);
+ } else {
+ var e = document.createElement('span');
+ var lines = item.content.split('\n');
+ for (var i = 0, ii = lines.length; i < ii; ++i) {
+ var line = lines[i];
+ e.appendChild(document.createTextNode(line));
+ if (i < (ii - 1))
+ e.appendChild(document.createElement('br'));
+ }
+ text.appendChild(e);
+ image.addEventListener('mouseover', function annotationImageOver() {
+ content.removeAttribute('hidden');
+ }, false);
+
+ image.addEventListener('mouseout', function annotationImageOut() {
+ content.setAttribute('hidden', true);
+ }, false);
+ }
+
+ content.appendChild(title);
+ content.appendChild(text);
+ container.appendChild(image);
+ container.appendChild(content);
+
+ return container;
+ }
+
+ pdfPage.getAnnotations().then(function(items) {
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ switch (item.type) {
+ case 'Link':
+ var link = createElementWithStyle('a', item);
+ link.href = item.url || '';
+ if (!item.url)
+ bindLink(link, ('dest' in item) ? item.dest : null);
+ div.appendChild(link);
+ break;
+ case 'Text':
+ var comment = createCommentAnnotation(item.name, item);
+ if (comment)
+ div.appendChild(comment);
+ break;
+ case 'Widget':
+ // TODO: support forms
+ PDFView.fallback();
+ break;
+ }
+ }
+ });
+ }
+
+ this.getPagePoint = function pageViewGetPagePoint(x, y) {
+ return this.viewport.convertToPdfPoint(x, y);
+ };
+
+ this.scrollIntoView = function pageViewScrollIntoView(dest) {
+ if (!dest) {
+ div.scrollIntoView(true);
+ return;
+ }
+
+ var x = 0, y = 0;
+ var width = 0, height = 0, widthScale, heightScale;
+ var scale = 0;
+ switch (dest[1].name) {
+ case 'XYZ':
+ x = dest[2];
+ y = dest[3];
+ scale = dest[4];
+ break;
+ case 'Fit':
+ case 'FitB':
+ scale = 'page-fit';
+ break;
+ case 'FitH':
+ case 'FitBH':
+ y = dest[2];
+ scale = 'page-width';
+ break;
+ case 'FitV':
+ case 'FitBV':
+ x = dest[2];
+ scale = 'page-height';
+ break;
+ case 'FitR':
+ x = dest[2];
+ y = dest[3];
+ width = dest[4] - x;
+ height = dest[5] - y;
+ widthScale = (this.container.clientWidth - kScrollbarPadding) /
+ width / kCssUnits;
+ heightScale = (this.container.clientHeight - kScrollbarPadding) /
+ height / kCssUnits;
+ scale = Math.min(widthScale, heightScale);
+ break;
+ default:
+ return;
+ }
+
+ if (scale && scale !== PDFView.currentScale)
+ PDFView.parseScale(scale, true);
+ else if (PDFView.currentScale === kUnknownScale)
+ PDFView.parseScale(kDefaultScale, true);
+
+ var boundingRect = [
+ this.viewport.convertToViewportPoint(x, y),
+ this.viewport.convertToViewportPoint(x + width, y + height)
+ ];
+ setTimeout(function pageViewScrollIntoViewRelayout() {
+ // letting page to re-layout before scrolling
+ var scale = PDFView.currentScale;
+ var x = Math.min(boundingRect[0][0], boundingRect[1][0]);
+ var y = Math.min(boundingRect[0][1], boundingRect[1][1]);
+ var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]);
+ var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]);
+
+ // using temporary div to scroll it into view
+ var tempDiv = document.createElement('div');
+ tempDiv.style.position = 'absolute';
+ tempDiv.style.left = Math.floor(x) + 'px';
+ tempDiv.style.top = Math.floor(y) + 'px';
+ tempDiv.style.width = Math.ceil(width) + 'px';
+ tempDiv.style.height = Math.ceil(height) + 'px';
+ div.appendChild(tempDiv);
+ tempDiv.scrollIntoView(true);
+ div.removeChild(tempDiv);
+ }, 0);
+ };
+
+ this.drawingRequired = function() {
+ return !div.querySelector('canvas');
+ };
+
+ this.draw = function pageviewDraw(callback) {
+ if (!this.drawingRequired()) {
+ this.updateStats();
+ callback();
+ return;
+ }
+
+ var canvas = document.createElement('canvas');
+ canvas.id = 'page' + this.id;
+ canvas.mozOpaque = true;
+ div.appendChild(canvas);
+ this.canvas = canvas;
+
+ var textLayerDiv = null;
+ if (!PDFJS.disableTextLayer) {
+ textLayerDiv = document.createElement('div');
+ textLayerDiv.className = 'textLayer';
+ div.appendChild(textLayerDiv);
+ }
+ var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null;
+
+ var scale = this.scale, viewport = this.viewport;
+ canvas.width = viewport.width;
+ canvas.height = viewport.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.save();
+ ctx.fillStyle = 'rgb(255, 255, 255)';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.restore();
+
+ // Rendering area
+
+ var self = this;
+ function pageViewDrawCallback(error) {
+ if (self.loadingIconDiv) {
+ div.removeChild(self.loadingIconDiv);
+ delete self.loadingIconDiv;
+ }
+
+ if (error) {
+ PDFView.error(mozL10n.get('rendering_error', null,
+ 'An error occurred while rendering the page.'), error);
+ }
+
+ self.stats = pdfPage.stats;
+ self.updateStats();
+ if (self.onAfterDraw)
+ self.onAfterDraw();
+
+ cache.push(self);
+ callback();
+ }
+
+ var renderContext = {
+ canvasContext: ctx,
+ viewport: this.viewport,
+ textLayer: textLayer
+ };
+ this.pdfPage.render(renderContext).then(
+ function pdfPageRenderCallback() {
+ pageViewDrawCallback(null);
+ },
+ function pdfPageRenderError(error) {
+ pageViewDrawCallback(error);
+ }
+ );
+
+ setupAnnotations(this.pdfPage, this.viewport);
+ div.setAttribute('data-loaded', true);
+ };
+
+ this.updateStats = function pageViewUpdateStats() {
+ if (PDFJS.pdfBug && Stats.enabled) {
+ var stats = this.stats;
+ Stats.add(this.id, stats);
+ }
+ };
+};
+
+var ThumbnailView = function thumbnailView(container, pdfPage, id) {
+ var anchor = document.createElement('a');
+ anchor.href = PDFView.getAnchorUrl('#page=' + id);
+ anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}');
+ anchor.onclick = function stopNavigation() {
+ PDFView.page = id;
+ return false;
+ };
+
+ var viewport = pdfPage.getViewport(1);
+ var pageWidth = this.width = viewport.width;
+ var pageHeight = this.height = viewport.height;
+ var pageRatio = pageWidth / pageHeight;
+ this.id = id;
+
+ var canvasWidth = 98;
+ var canvasHeight = canvasWidth / this.width * this.height;
+ var scaleX = this.scaleX = (canvasWidth / pageWidth);
+ var scaleY = this.scaleY = (canvasHeight / pageHeight);
+
+ var div = document.createElement('div');
+ div.id = 'thumbnailContainer' + id;
+ div.className = 'thumbnail';
+
+ anchor.appendChild(div);
+ container.appendChild(anchor);
+
+ this.hasImage = false;
+
+ function getPageDrawContext() {
+ var canvas = document.createElement('canvas');
+ canvas.id = 'thumbnail' + id;
+ canvas.mozOpaque = true;
+
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+ canvas.className = 'thumbnailImage';
+ canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas',
+ {page: id}, 'Thumbnail of Page {{page}}'));
+
+ div.setAttribute('data-loaded', true);
+
+ var ring = document.createElement('div');
+ ring.className = 'thumbnailSelectionRing';
+ ring.appendChild(canvas);
+ div.appendChild(ring);
+
+ var ctx = canvas.getContext('2d');
+ ctx.save();
+ ctx.fillStyle = 'rgb(255, 255, 255)';
+ ctx.fillRect(0, 0, canvasWidth, canvasHeight);
+ ctx.restore();
+ return ctx;
+ }
+
+ this.drawingRequired = function thumbnailViewDrawingRequired() {
+ return !this.hasImage;
+ };
+
+ this.draw = function thumbnailViewDraw(callback) {
+ if (this.hasImage) {
+ callback();
+ return;
+ }
+
+ var ctx = getPageDrawContext();
+ var drawViewport = pdfPage.getViewport(scaleX);
+ var renderContext = {
+ canvasContext: ctx,
+ viewport: drawViewport
+ };
+ pdfPage.render(renderContext).then(
+ function pdfPageRenderCallback() {
+ callback();
+ },
+ function pdfPageRenderError(error) {
+ callback();
+ }
+ );
+ this.hasImage = true;
+ };
+
+ this.setImage = function thumbnailViewSetImage(img) {
+ if (this.hasImage || !img)
+ return;
+
+ var ctx = getPageDrawContext();
+ ctx.drawImage(img, 0, 0, img.width, img.height,
+ 0, 0, ctx.canvas.width, ctx.canvas.height);
+
+ this.hasImage = true;
+ };
+};
+
+var DocumentOutlineView = function documentOutlineView(outline) {
+ var outlineView = document.getElementById('outlineView');
+// while (outlineView.firstChild)
+// outlineView.removeChild(outlineView.firstChild);
+
+ function bindItemLink(domObj, item) {
+ domObj.href = PDFView.getDestinationHash(item.dest);
+ domObj.onclick = function documentOutlineViewOnclick(e) {
+ PDFView.navigateTo(item.dest);
+ return false;
+ };
+ }
+
+ if (!outline) {
+ var noOutline = document.createElement('div');
+ noOutline.classList.add('noOutline');
+ //noOutline.textContent = mozL10n.get('no_outline', null,
+ // 'No Outline Available');
+ noOutline.textContent = 'No Outline Available';
+ //outlineView.appendChild(noOutline);
+ return;
+ }
+
+ var queue = [{parent: outlineView, items: outline}];
+ while (queue.length > 0) {
+ var levelData = queue.shift();
+ var i, n = levelData.items.length;
+ for (i = 0; i < n; i++) {
+ var item = levelData.items[i];
+ var div = document.createElement('div');
+ div.className = 'outlineItem';
+ var a = document.createElement('a');
+ bindItemLink(a, item);
+ a.textContent = item.title;
+ div.appendChild(a);
+
+ if (item.items.length > 0) {
+ var itemsDiv = document.createElement('div');
+ itemsDiv.className = 'outlineItems';
+ div.appendChild(itemsDiv);
+ queue.push({parent: itemsDiv, items: item.items});
+ }
+
+ levelData.parent.appendChild(div);
+ }
+ }
+};
+
+// optimised CSS custom property getter/setter
+var CustomStyle = (function CustomStyleClosure() {
+
+ // As noted on: http://www.zachstronaut.com/posts/2009/02/17/
+ // animate-css-transforms-firefox-webkit.html
+ // in some versions of IE9 it is critical that ms appear in this list
+ // before Moz
+ var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
+ var _cache = { };
+
+ function CustomStyle() {
+ }
+
+ CustomStyle.getProp = function get(propName, element) {
+ // check cache only when no element is given
+ if (arguments.length == 1 && typeof _cache[propName] == 'string') {
+ return _cache[propName];
+ }
+
+ element = element || document.documentElement;
+ var style = element.style, prefixed, uPropName;
+
+ // test standard property first
+ if (typeof style[propName] == 'string') {
+ return (_cache[propName] = propName);
+ }
+
+ // capitalize
+ uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
+
+ // test vendor specific properties
+ for (var i = 0, l = prefixes.length; i < l; i++) {
+ prefixed = prefixes[i] + uPropName;
+ if (typeof style[prefixed] == 'string') {
+ return (_cache[propName] = prefixed);
+ }
+ }
+
+ //if all fails then set to undefined
+ return (_cache[propName] = 'undefined');
+ }
+
+ CustomStyle.setProp = function set(propName, element, str) {
+ var prop = this.getProp(propName);
+ if (prop != 'undefined')
+ element.style[prop] = str;
+ }
+
+ return CustomStyle;
+})();
+
+var TextLayerBuilder = function textLayerBuilder(textLayerDiv) {
+ this.textLayerDiv = textLayerDiv;
+
+ this.beginLayout = function textLayerBuilderBeginLayout() {
+ this.textDivs = [];
+ this.textLayerQueue = [];
+ };
+
+ this.endLayout = function textLayerBuilderEndLayout() {
+ var self = this;
+ var textDivs = this.textDivs;
+ var textLayerDiv = this.textLayerDiv;
+ var renderTimer = null;
+ var renderingDone = false;
+ var renderInterval = 0;
+ var resumeInterval = 500; // in ms
+
+ // Render the text layer, one div at a time
+ function renderTextLayer() {
+ if (textDivs.length === 0) {
+ clearInterval(renderTimer);
+ renderingDone = true;
+ return;
+ }
+ var textDiv = textDivs.shift();
+ if (textDiv.dataset.textLength > 0) {
+ textLayerDiv.appendChild(textDiv);
+
+ if (textDiv.dataset.textLength > 1) { // avoid div by zero
+ // Adjust div width to match canvas text
+ // Due to the .offsetWidth calls, this is slow
+ // This needs to come after appending to the DOM
+ var textScale = textDiv.dataset.canvasWidth / textDiv.offsetWidth;
+ CustomStyle.setProp('transform' , textDiv,
+ 'scale(' + textScale + ', 1)');
+ CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
+ }
+ } // textLength > 0
+ }
+ renderTimer = setInterval(renderTextLayer, renderInterval);
+
+ // Stop rendering when user scrolls. Resume after XXX milliseconds
+ // of no scroll events
+ var scrollTimer = null;
+ function textLayerOnScroll() {
+ if (renderingDone) {
+ window.removeEventListener('scroll', textLayerOnScroll, false);
+ return;
+ }
+
+ // Immediately pause rendering
+ clearInterval(renderTimer);
+
+ clearTimeout(scrollTimer);
+ scrollTimer = setTimeout(function textLayerScrollTimer() {
+ // Resume rendering
+ renderTimer = setInterval(renderTextLayer, renderInterval);
+ }, resumeInterval);
+ }; // textLayerOnScroll
+
+ window.addEventListener('scroll', textLayerOnScroll, false);
+ }; // endLayout
+
+ this.appendText = function textLayerBuilderAppendText(text,
+ fontName, fontSize) {
+ var textDiv = document.createElement('div');
+
+ // vScale and hScale already contain the scaling to pixel units
+ var fontHeight = fontSize * text.geom.vScale;
+ textDiv.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
+ textDiv.dataset.fontName = fontName;
+
+ textDiv.style.fontSize = fontHeight + 'px';
+ textDiv.style.left = text.geom.x + 'px';
+ textDiv.style.top = (text.geom.y - fontHeight) + 'px';
+ textDiv.textContent = PDFJS.bidi(text, -1);
+ textDiv.dir = text.direction;
+ textDiv.dataset.textLength = text.length;
+ this.textDivs.push(textDiv);
+ };
+};
+
+window.addEventListener('load', function webViewerLoad(evt) {
+ PDFView.initialize();
+ var params = PDFView.parseQueryString(document.location.search.substring(1));
+
+ var file = PDFJS.isFirefoxExtension ?
+ window.location.toString() : params.file || kDefaultURL;
+
+/* if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader ||
+ !window.FileList || !window.Blob) {
+ document.getElementById('openFile').setAttribute('hidden', 'true');
+ } else {
+ document.getElementById('fileInput').value = null;
+ }
+*/
+ // Special debugging flags in the hash section of the URL.
+ var hash = document.location.hash.substring(1);
+ var hashParams = PDFView.parseQueryString(hash);
+
+ if ('disableWorker' in hashParams)
+ PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
+
+/* if (!PDFJS.isFirefoxExtension) {
+ var locale = navigator.language;
+ if ('locale' in hashParams)
+ locale = hashParams['locale'];
+ mozL10n.language.code = locale;
+ }
+*/
+ if ('disableTextLayer' in hashParams)
+ PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true');
+
+ if ('pdfBug' in hashParams &&
+ (!PDFJS.isFirefoxExtension || FirefoxCom.requestSync('pdfBugEnabled'))) {
+ PDFJS.pdfBug = true;
+ var pdfBug = hashParams['pdfBug'];
+ var enabled = pdfBug.split(',');
+ PDFBug.enable(enabled);
+ PDFBug.init();
+ }
+
+/* if (!PDFJS.isFirefoxExtension ||
+ (PDFJS.isFirefoxExtension && FirefoxCom.requestSync('searchEnabled'))) {
+ document.querySelector('#viewSearch').classList.remove('hidden');
+ }
+*/
+ // Listen for warnings to trigger the fallback UI. Errors should be caught
+ // and call PDFView.error() so we don't need to listen for those.
+ PDFJS.LogManager.addLogger({
+ warn: function() {
+ PDFView.fallback();
+ }
+ });
+
+// var thumbsView = document.getElementById('thumbnailView');
+// thumbsView.addEventListener('scroll', updateThumbViewArea, true);
+/*
+ var mainContainer = document.getElementById('mainContainer');
+ var outerContainer = document.getElementById('outerContainer');
+ mainContainer.addEventListener('transitionend', function(e) {
+ if (e.target == mainContainer) {
+ var event = document.createEvent('UIEvents');
+ event.initUIEvent('resize', false, false, window, 0);
+ window.dispatchEvent(event);
+ outerContainer.classList.remove('sidebarMoving');
+ }
+ }, true);
+
+ document.getElementById('sidebarToggle').addEventListener('click',
+ function() {
+ this.classList.toggle('toggled');
+ outerContainer.classList.add('sidebarMoving');
+ outerContainer.classList.toggle('sidebarOpen');
+ updateThumbViewArea();
+ });
+
+ PDFView.open(file, 0);
+*/
+}, true);
+
+/**
+ * Render the next not yet visible page already such that it is
+ * hopefully ready once the user scrolls to it.
+ */
+function preDraw() {
+ var pages = PDFView.pages;
+ var visible = PDFView.getVisiblePages();
+ var last = visible[visible.length - 1];
+ // PageView.id is the actual page number, which is + 1 compared
+ // to the index in `pages`. That means, pages[last.id] is the next
+ // PageView instance.
+ if (pages[last.id] && pages[last.id].drawingRequired()) {
+ renderingQueue.enqueueDraw(pages[last.id]);
+ return;
+ }
+ // If there is nothing to draw on the next page, maybe the user
+ // is scrolling up, so, let's try to render the next page *before*
+ // the first visible page
+ if (pages[visible[0].id - 2]) {
+ renderingQueue.enqueueDraw(pages[visible[0].id - 2]);
+ }
+}
+
+function updateViewarea() {
+ if (!PDFView.initialized)
+ return;
+ var container = document.getElementById('viewer');
+ if (!container)
+ return;
+
+ var visiblePages = PDFView.getVisiblePages();
+ var pageToDraw;
+ for (var i = 0; i < visiblePages.length; i++) {
+ var page = visiblePages[i];
+ var pageObj = PDFView.pages[page.id - 1];
+
+ pageToDraw |= pageObj.drawingRequired();
+ renderingQueue.enqueueDraw(pageObj);
+ }
+
+ if (!visiblePages.length)
+ return;
+
+ // If there is no need to draw a page that is currenlty visible, preDraw the
+ // next page the user might scroll to.
+ if (!pageToDraw) {
+ preDraw();
+ }
+
+ updateViewarea.inProgress = true; // used in "set page"
+ var currentId = PDFView.page;
+ var firstPage = visiblePages[0];
+ PDFView.page = firstPage.id;
+ updateViewarea.inProgress = false;
+
+ var currentScale = PDFView.currentScale;
+ var currentScaleValue = PDFView.currentScaleValue;
+ var normalizedScaleValue = currentScaleValue == currentScale ?
+ currentScale * 100 : currentScaleValue;
+
+ var pageNumber = firstPage.id;
+ var pdfOpenParams = '#page=' + pageNumber;
+ pdfOpenParams += '&zoom=' + normalizedScaleValue;
+ var currentPage = PDFView.pages[pageNumber - 1];
+ var topLeft = currentPage.getPagePoint(PDFView.container.scrollLeft,
+ (PDFView.container.scrollTop - firstPage.y));
+ pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]);
+
+ var store = PDFView.store;
+ store.set('exists', true);
+ store.set('page', pageNumber);
+ store.set('zoom', normalizedScaleValue);
+ store.set('scrollLeft', Math.round(topLeft[0]));
+ store.set('scrollTop', Math.round(topLeft[1]));
+// var href = PDFView.getAnchorUrl(pdfOpenParams);
+// document.getElementById('viewBookmark').href = href;
+}
+
+window.addEventListener('scroll', function webViewerScroll(evt) {
+ updateViewarea();
+}, true);
+
+var thumbnailTimer;
+
+function updateThumbViewArea() {
+ // Only render thumbs after pausing scrolling for this amount of time
+ // (makes UI more responsive)
+ var delay = 50; // in ms
+
+ if (thumbnailTimer)
+ clearTimeout(thumbnailTimer);
+
+ thumbnailTimer = setTimeout(function() {
+ var visibleThumbs = PDFView.getVisibleThumbs();
+ for (var i = 0; i < visibleThumbs.length; i++) {
+ var thumb = visibleThumbs[i];
+ renderingQueue.enqueueDraw(PDFView.thumbnails[thumb.id - 1]);
+ }
+ }, delay);
+}
+
+window.addEventListener('resize', function webViewerResize(evt) {
+ if (PDFView.initialized &&
+ (document.getElementById('pageWidthOption').selected ||
+ document.getElementById('pageFitOption').selected ||
+ document.getElementById('pageAutoOption').selected))
+ PDFView.parseScale(document.getElementById('scaleSelect').value);
+ updateViewarea();
+});
+
+window.addEventListener('hashchange', function webViewerHashchange(evt) {
+ PDFView.setHash(document.location.hash.substring(1));
+});
+
+window.addEventListener('change', function webViewerChange(evt) {
+ var files = evt.target.files;
+ if (!files || files.length == 0)
+ return;
+
+ // Read the local file into a Uint8Array.
+ var fileReader = new FileReader();
+ fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
+ var data = evt.target.result;
+ var buffer = new ArrayBuffer(data.length);
+ var uint8Array = new Uint8Array(buffer);
+
+ for (var i = 0; i < data.length; i++)
+ uint8Array[i] = data.charCodeAt(i);
+
+ PDFView.open(uint8Array, 0);
+ };
+
+ // Read as a binary string since "readAsArrayBuffer" is not yet
+ // implemented in Firefox.
+ var file = files[0];
+ fileReader.readAsBinaryString(file);
+ document.title = file.name;
+
+ // URL does not reflect proper document location - hiding some icons.
+ document.getElementById('viewBookmark').setAttribute('hidden', 'true');
+ document.getElementById('download').setAttribute('hidden', 'true');
+}, true);
+
+function selectScaleOption(value) {
+ var options = document.getElementById('scaleSelect').options;
+ var predefinedValueFound = false;
+ for (var i = 0; i < options.length; i++) {
+ var option = options[i];
+ if (option.value != value) {
+ option.selected = false;
+ continue;
+ }
+ option.selected = true;
+ predefinedValueFound = true;
+ }
+ return predefinedValueFound;
+}
+
+window.addEventListener('localized', function localized(evt) {
+ document.getElementsByTagName('html')[0].dir = mozL10n.language.direction;
+}, true);
+
+window.addEventListener('scalechange', function scalechange(evt) {
+ var customScaleOption = document.getElementById('customScaleOption');
+ customScaleOption.selected = false;
+
+ if (!evt.resetAutoSettings &&
+ (document.getElementById('pageWidthOption').selected ||
+ document.getElementById('pageFitOption').selected ||
+ document.getElementById('pageAutoOption').selected)) {
+ updateViewarea();
+ return;
+ }
+
+ var predefinedValueFound = selectScaleOption('' + evt.scale);
+ if (!predefinedValueFound) {
+ customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
+ customScaleOption.selected = true;
+ }
+
+ updateViewarea();
+}, true);
+
+window.addEventListener('pagechange', function pagechange(evt) {
+ var page = evt.pageNumber;
+ if (document.getElementById('pageNumber').value != page) {
+ document.getElementById('pageNumber').value = page;
+ var selected = document.querySelector('.thumbnail.selected');
+ if (selected)
+ selected.classList.remove('selected');
+/*
+ var thumbnail = document.getElementById('thumbnailContainer' + page);
+ thumbnail.classList.add('selected');
+ var visibleThumbs = PDFView.getVisibleThumbs();
+ var numVisibleThumbs = visibleThumbs.length;
+ // If the thumbnail isn't currently visible scroll it into view.
+ if (numVisibleThumbs > 0) {
+ var first = visibleThumbs[0].id;
+ // Account for only one thumbnail being visible.
+ var last = numVisibleThumbs > 1 ?
+ visibleThumbs[numVisibleThumbs - 1].id : first;
+ if (page <= first || page >= last)
+ thumbnail.scrollIntoView();
+ }
+*/
+ }
+ document.getElementById('previous').disabled = (page <= 1);
+ document.getElementById('next').disabled = (page >= PDFView.pages.length);
+}, true);
+
+// Firefox specific event, so that we can prevent browser from zooming
+window.addEventListener('DOMMouseScroll', function(evt) {
+ if (evt.ctrlKey) {
+ evt.preventDefault();
+
+ var ticks = evt.detail;
+ var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn';
+ for (var i = 0, length = Math.abs(ticks); i < length; i++)
+ PDFView[direction]();
+ }
+}, false);
+
+window.addEventListener('keydown', function keydown(evt) {
+ var handled = false;
+ var cmd = (evt.ctrlKey ? 1 : 0) |
+ (evt.altKey ? 2 : 0) |
+ (evt.shiftKey ? 4 : 0) |
+ (evt.metaKey ? 8 : 0);
+
+ // First, handle the key bindings that are independent whether an input
+ // control is selected or not.
+ if (cmd == 1 || cmd == 8) { // either CTRL or META key.
+ switch (evt.keyCode) {
+ case 61: // FF/Mac '='
+ case 107: // FF '+' and '='
+ case 187: // Chrome '+'
+ PDFView.zoomIn();
+ handled = true;
+ break;
+ case 109: // FF '-'
+ case 189: // Chrome '-'
+ PDFView.zoomOut();
+ handled = true;
+ break;
+ case 48: // '0'
+ PDFView.parseScale(kDefaultScale, true);
+ handled = true;
+ break;
+ }
+ }
+
+ if (handled) {
+ evt.preventDefault();
+ return;
+ }
+
+ // Some shortcuts should not get handled if a control/input element
+ // is selected.
+ var curElement = document.activeElement;
+ if (curElement && curElement.tagName == 'INPUT')
+ return;
+ var controlsElement = document.getElementById('controls');
+ while (curElement) {
+ if (curElement === controlsElement)
+ return; // ignoring if the 'controls' element is focused
+ curElement = curElement.parentNode;
+ }
+
+ if (cmd == 0) { // no control key pressed at all.
+ switch (evt.keyCode) {
+ case 37: // left arrow
+ case 75: // 'k'
+ case 80: // 'p'
+ PDFView.page--;
+ handled = true;
+ break;
+ case 39: // right arrow
+ case 74: // 'j'
+ case 78: // 'n'
+ PDFView.page++;
+ handled = true;
+ break;
+ }
+ }
+
+ if (handled) {
+ evt.preventDefault();
+ }
+});
diff --git a/apps/files_pdfviewer/js/viewer.js b/apps/files_pdfviewer/js/viewer.js
index 85bbf09362e..d98bedc5c09 100644
--- a/apps/files_pdfviewer/js/viewer.js
+++ b/apps/files_pdfviewer/js/viewer.js
@@ -24,21 +24,9 @@ function showPDFviewer(dir,filename){
var oldcontent = $("#content").html();
$("#content").html(oldcontent+'<div id="loading">Loading... 0%</div><div id="viewer"></div>');
showPDFviewer.lastTitle = document.title;
- if(!showPDFviewer.loaded){
- OC.addScript( 'files_pdfviewer', 'pdfjs/build/pdf',function(){
- OC.addScript( 'files_pdfviewer', 'pdfview',function(){
- showPDFviewer.loaded=true;
- PDFJS.workerSrc = OC.filePath('files_pdfviewer','js','pdfjs/build/pdf.js');
- PDFView.Ptitle = filename;
- PDFView.open(url,1.00);
- PDFView.active=true;
- });
- });
- }else{
- PDFView.Ptitle = filename;
- PDFView.open(url,1.00);
- PDFView.active=true;
- }
+ PDFView.Ptitle = filename;
+ PDFView.open(url,1.00);
+ PDFView.active=true;
$("#pageWidthOption").attr("selected","selected");
showPDFviewer.shown = true;
}
@@ -46,7 +34,6 @@ function showPDFviewer(dir,filename){
showPDFviewer.shown=false;
showPDFviewer.oldCode='';
showPDFviewer.lastTitle='';
-showPDFviewer.loaded=false;
$(document).ready(function(){
if(!$.browser.msie){//doesnt work on IE
diff --git a/apps/files_sharing/appinfo/database.xml b/apps/files_sharing/appinfo/database.xml
index 3378b6b09e5..c5cb632d4fe 100644
--- a/apps/files_sharing/appinfo/database.xml
+++ b/apps/files_sharing/appinfo/database.xml
@@ -3,7 +3,7 @@
<name>*dbname*</name>
<create>true</create>
<overwrite>false</overwrite>
- <charset>latin1</charset>
+ <charset>utf8</charset>
<table>
<name>*dbprefix*sharing</name>
<declaration>
diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php
index cf5456d7042..4abf80ae19c 100644
--- a/apps/files_sharing/lib_share.php
+++ b/apps/files_sharing/lib_share.php
@@ -104,10 +104,6 @@ class OC_Share {
$counter++;
}
}
- if (isset($gid)) {
- $uid = $uid."@".$gid;
- }
- $query->execute(array($uid_owner, $uid, $source, $target, $permissions));
// Update mtime of shared folder to invoke a file cache rescan
$rootView=new OC_FilesystemView('/');
if (!$rootView->is_dir($sharedFolder)) {
@@ -119,6 +115,10 @@ class OC_Share {
$rootView->mkdir($sharedFolder);
}
$rootView->touch($sharedFolder);
+ if (isset($gid)) {
+ $uid = $uid."@".$gid;
+ }
+ $query->execute(array($uid_owner, $uid, $source, $target, $permissions));
}
}
}
@@ -276,7 +276,7 @@ class OC_Share {
$userDirectory = substr($target, 0, strpos($target, "files") + 5);
$target = dirname($target);
$result = array();
- while ($target != "" && $target != "/" && $target != "." && $target != $userDirectory) {
+ while ($target != "" && $target != "/" && $target != "." && $target != $userDirectory && $target != "\\") {
// Check if the parent directory of this target location is shared
$result = $query->execute(array($target))->fetchAll();
if (count($result) > 0) {
@@ -495,7 +495,7 @@ class OC_Share {
$result = $query->execute(array($gid))->fetchAll();
if (count($result) > 0) {
$lastSource = '';
- for ($i = 0; $i < count($result) - 1; $i++) {
+ for ($i = 0; $i < count($result); $i++) {
if ($result[$i]['source'] != $lastSource) {
new OC_Share($result[$i]['source'], $arguments['gid'], $result[$i]['permissions']);
$lastSource = $result[$i]['source'];
diff --git a/apps/files_texteditor/appinfo/app.php b/apps/files_texteditor/appinfo/app.php
index a08077ebb67..c745170018e 100644
--- a/apps/files_texteditor/appinfo/app.php
+++ b/apps/files_texteditor/appinfo/app.php
@@ -1,5 +1,6 @@
<?php
//load the required files
+OCP\Util::addStyle( 'files_texteditor', 'DroidSansMono/stylesheet' );
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/css/DroidSansMono/DroidSansMono-webfont.eot b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.eot
new file mode 100644
index 00000000000..bc2d524aa76
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.eot
Binary files differ
diff --git a/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.svg b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.svg
new file mode 100644
index 00000000000..4ca5fc20dc5
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.svg
@@ -0,0 +1,630 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Digitized data copyright 2006 Google Corporation
+Foundry : Ascender Corporation
+Foundry URL : httpwwwascendercorpcom
+</metadata>
+<defs>
+<font id="webfontq63XZdUr" horiz-adv-x="1228" >
+<font-face units-per-em="2048" ascent="1638" descent="-410" />
+<missing-glyph horiz-adv-x="500" />
+<glyph unicode=" " />
+<glyph unicode="!" d="M487 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM504 1462h223l-51 -1048h-121z" />
+<glyph unicode="&#x22;" d="M285 1462h237l-41 -528h-155zM707 1462h237l-41 -528h-155z" />
+<glyph unicode="#" d="M45 428v137h244l65 328h-233v137h258l82 432h147l-82 -432h293l84 432h144l-84 -432h221v-137h-248l-64 -328h240v-137h-266l-82 -428h-148l84 428h-290l-82 -428h-144l78 428h-217zM436 565h291l64 328h-291z" />
+<glyph unicode="$" d="M182 172v172q197 -92 365 -92v434q-197 66 -271 145q-78 84 -77 220q0 131 92 217q90 84 256 106v180h137v-176q182 -8 336 -78l-66 -145q-143 63 -270 72v-422q199 -68 279 -148q82 -82 81 -211q0 -281 -360 -335v-230h-137v221q-228 0 -365 70zM375 1049q0 -76 41 -121 q41 -43 131 -74v369q-172 -27 -172 -174zM684 262q184 28 184 184q0 127 -184 189v-373z" />
+<glyph unicode="%" d="M0 1133q0 164 80 256q78 90 215 90q131 0 211 -92.5t80 -253.5q0 -166 -78 -256q-80 -92 -217 -93q-131 0 -211 95q-80 96 -80 254zM152 1133q0 -229 141 -230q139 0 139 230q0 225 -139 225q-141 0 -141 -225zM170 0l729 1462h158l-729 -1462h-158zM643 330 q0 164 80 256q78 90 215 90q131 0 211 -92t80 -254q0 -164 -78 -254q-82 -94 -217 -94q-131 0 -211 94q-80 96 -80 254zM795 330q0 -229 141 -230q139 0 139 230q0 225 -139 225q-141 0 -141 -225z" />
+<glyph unicode="&#x26;" d="M61 381q0 133 64 229q63 98 235 199q-164 193 -163 356q0 147 96 233.5t274 86.5q168 0 260.5 -86t92.5 -234q0 -203 -318 -389l281 -348q70 119 104 266h184q-53 -236 -178 -403l234 -291h-217l-131 166q-174 -186 -412 -186q-190 0 -297 106q-109 109 -109 295z M252 387q0 -104 67 -176q68 -70 160 -70q162 0 299 146l-323 401q-203 -123 -203 -301zM375 1165q0 -117 133 -268q133 80 184 139q49 57 49 133q0 72 -49 119q-51 47 -131 47q-86 0 -137 -45q-49 -43 -49 -125z" />
+<glyph unicode="'" d="M496 1462h237l-41 -528h-155z" />
+<glyph unicode="(" d="M295 567q0 532 444 895h193q-449 -375 -449 -893q0 -522 447 -893h-191q-444 352 -444 891z" />
+<glyph unicode=")" d="M297 1462h192q444 -362 445 -895q0 -541 -445 -891h-190q446 373 446 893q1 518 -448 893z" />
+<glyph unicode="*" d="M133 1081l29 193l391 -111l-43 393h205l-43 -393l397 111l27 -193l-379 -28l246 -326l-179 -96l-176 358l-157 -358l-185 96l242 326z" />
+<glyph unicode="+" d="M152 647v150h387v389h149v-389h387v-150h-387v-385h-149v385h-387z" />
+<glyph unicode="," d="M440 -289q76 322 111 551h219l16 -24q-59 -229 -194 -527h-152z" />
+<glyph unicode="-" d="M285 465v168h659v-168h-659z" />
+<glyph unicode="." d="M463 135q0 166 151.5 166t151.5 -166t-151.5 -166t-151.5 166z" />
+<glyph unicode="/" d="M211 0l627 1462h178l-627 -1462h-178z" />
+<glyph unicode="0" d="M147 733q0 752 465 752q231 0 350 -192.5t119 -559.5q0 -754 -469 -753q-231 0 -348 194q-117 193 -117 559zM332 733q0 -317 67 -459q68 -139 213 -139q147 0 215 141q70 145 70 457q0 309 -70 455q-68 141 -215 141q-145 0 -213 -139q-67 -138 -67 -457z" />
+<glyph unicode="1" d="M225 1163l383 299h150v-1462h-176v913q0 147 8 361q-43 -47 -121 -113l-147 -121z" />
+<glyph unicode="2" d="M158 0v156l350 381q201 219 258 317q61 104 61 231q0 115 -63 179q-66 66 -172 65q-162 0 -318 -137l-102 119q190 172 422 172q197 0 305 -107q113 -109 113 -284q0 -115 -59.5 -244t-290.5 -375l-281 -299v-8h688v-166h-911z" />
+<glyph unicode="3" d="M131 59v170q186 -96 383 -96q354 0 354 289q0 258 -381 258h-133v151h133q160 0 248 76t88 201q0 104 -67 162q-70 59 -183 59q-176 0 -344 -121l-92 125q186 150 436 150q205 0 322 -99q115 -96 115 -264q0 -141 -82 -231q-86 -94 -234 -119v-6q360 -45 361 -348 q0 -203 -137 -320q-138 -117 -400 -116q-243 -1 -387 79z" />
+<glyph unicode="4" d="M61 328v159l664 983h188v-976h213v-166h-213v-328h-176v328h-676zM240 494h497v356q0 178 13 432h-9q-41 -111 -90 -180z" />
+<glyph unicode="5" d="M172 59v172q145 -96 360 -96q336 0 336 314q0 295 -344 294q-78 0 -231 -26l-90 57l55 688h690v-166h-532l-39 -419q102 20 209 20q209 0 340 -115q129 -114 129 -313q0 -233 -137 -363q-135 -127 -390 -126q-224 -1 -356 79z" />
+<glyph unicode="6" d="M154 625q0 858 639 858q104 0 172 -19v-155q-71 25 -166 24q-221 0 -336 -141t-123 -447h12q96 170 307 170q195 0 306 -118q111 -120 110 -326q0 -227 -121 -360q-119 -131 -323 -131q-219 0 -348 170t-129 475zM336 506q0 -150 82 -262q80 -111 211 -111q129 0 198 88 q72 90 72 250q0 147 -68 223q-68 78 -196 78q-125 0 -213 -82q-86 -80 -86 -184z" />
+<glyph unicode="7" d="M143 1296v166h940v-145l-555 -1317h-194l563 1296h-754z" />
+<glyph unicode="8" d="M156 373q0 258 282 393q-236 150 -235 369q0 160 116 256q115 94 295 94q184 0 297 -94q115 -96 115 -258q0 -229 -262 -359q309 -160 309 -393q0 -180 -127 -291q-126 -111 -332 -110q-217 0 -337.5 104.5t-120.5 288.5zM334 371q0 -240 276 -240q135 0 211 66 q74 66 74 182q0 90 -63.5 159.5t-213.5 143.5l-30 14q-254 -118 -254 -325zM381 1126q0 -92 49 -153q47 -57 186 -125q231 104 232 278q0 102 -64 154q-66 53 -172 53q-104 0 -167.5 -53.5t-63.5 -153.5z" />
+<glyph unicode="9" d="M154 991q0 227 120 361q119 131 324 131q221 0 348 -170q129 -172 129 -475q0 -858 -639 -858q-104 0 -172 18v156q68 -25 166 -25q221 0 336 141.5t123 446.5h-12q-96 -170 -308 -170q-193 0 -305 119q-110 116 -110 325zM330 991q0 -143 69 -223q68 -78 195 -78 q129 0 213 82q86 84 86 184q0 152 -80 262.5t-213 110.5q-127 0 -198.5 -88t-71.5 -250z" />
+<glyph unicode=":" d="M487 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM487 987q0 139 127 139t127 -139t-127 -139t-127 139z" />
+<glyph unicode=";" d="M410 -264q66 276 100 502h199l14 -23q-55 -209 -176 -479h-137zM494 987q0 139 127 139t127 -139t-127 -139t-127 139z" />
+<glyph unicode="&#x3c;" d="M152 672v102l923 451v-160l-715 -342l715 -342v-160z" />
+<glyph unicode="=" d="M152 442v150h923v-150h-923zM152 852v149h923v-149h-923z" />
+<glyph unicode="&#x3e;" d="M152 221v160l714 342l-714 342v160l923 -451v-102z" />
+<glyph unicode="?" d="M168 1386q205 96 426 97q217 0 340 -97q125 -98 125 -262q0 -133 -53 -217q-52 -83 -197 -190q-119 -88 -151.5 -141.5t-32.5 -143.5v-18h-160v37q0 119 47 194.5t160 157.5q131 100 172 155.5t41 157.5q0 92 -74 150q-72 57 -207 57q-172 0 -371 -90zM426 110.5 q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5z" />
+<glyph unicode="@" d="M31 602q0 395 168 629q166 231 454 231q248 0 396 -196q150 -199 149 -535q0 -236 -63 -371q-66 -139 -179 -139q-131 0 -157 180h-4q-74 -180 -230 -180q-120 0 -190 105q-70 102 -70 280q0 209 96 332q98 127 256 127q133 0 256 -47l-22 -416q-2 -25 -2 -70v-6 q0 -176 72 -176q100 0 100 383q0 279 -110.5 436.5t-299.5 157.5q-225 0 -352 -192.5t-127 -526.5q0 -311 129 -483q127 -170 369 -170q178 0 346 78v-133q-156 -82 -352 -82q-295 0 -465 207q-168 204 -168 577zM465 602q0 -252 127 -252q131 0 145 312l15 253 q-53 20 -103 21q-90 0 -137 -94.5t-47 -239.5z" />
+<glyph unicode="A" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183z" />
+<glyph unicode="B" d="M135 0v1462h440q272 0 398 -88q123 -86 123 -282q0 -129 -78 -213t-213 -103v-10q332 -55 332 -342q0 -199 -127 -311.5t-348 -112.5h-527zM322 158h307q311 0 311 274q0 254 -324 254h-294v-528zM322 842h284q157 0 228 55q72 55 71 182q0 121 -75.5 172.5t-243.5 51.5 h-264v-461z" />
+<glyph unicode="C" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557z" />
+<glyph unicode="D" d="M135 0v1462h342q319 0 494 -188q176 -193 176 -529q0 -365 -182 -552q-186 -193 -529 -193h-301zM322 160h96q532 0 532 579q0 563 -493 564h-135v-1143z" />
+<glyph unicode="E" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842z" />
+<glyph unicode="F" d="M244 0v1462h841v-164h-655v-516h617v-164h-617v-618h-186z" />
+<glyph unicode="G" d="M117 733q0 352 161.5 551t446.5 199q193 0 346 -86l-72 -162q-150 84 -280 84q-193 0 -299.5 -155.5t-106.5 -432.5q0 -588 394 -588q94 0 202 29v436h-237v164h422v-717q-199 -76 -420 -75q-262 0 -410 200q-147 200 -147 553z" />
+<glyph unicode="H" d="M135 0v1462h187v-616h585v616h187v-1462h-187v682h-585v-682h-187z" />
+<glyph unicode="I" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776z" />
+<glyph unicode="J" d="M137 39v166q162 -61 309 -62q162 0 254.5 80t92.5 226v1013h186v-1011q0 -215 -141 -345q-139 -127 -377 -126q-215 0 -324 59z" />
+<glyph unicode="K" d="M211 0v1462h186v-731l121 168l453 563h209l-521 -637l539 -825h-211l-450 698l-140 -114v-584h-186z" />
+<glyph unicode="L" d="M233 0v1462h187v-1296h635v-166h-822z" />
+<glyph unicode="M" d="M113 0v1462h247l248 -1192h6l250 1192h252v-1462h-153v887q0 121 14 391h-8l-283 -1278h-154l-278 1280h-8q18 -268 18 -406v-874h-151z" />
+<glyph unicode="N" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172z" />
+<glyph unicode="O" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588z" />
+<glyph unicode="P" d="M176 0v1462h404q514 0 514 -428q0 -219 -137.5 -342t-403.5 -123h-191v-569h-186zM362 727h170q195 0 283 72q86 70 86 225q0 279 -338 279h-201v-576z" />
+<glyph unicode="Q" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -526 -285 -694q86 -180 279 -311l-121 -142q-238 172 -328 400q-37 -6 -76 -6q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588z" />
+<glyph unicode="R" d="M186 0v1462h357q520 0 520 -415q0 -287 -289 -392l397 -655h-219l-350 604h-229v-604h-187zM373 762h164q170 0 251.5 65.5t81.5 210.5q0 141 -79.5 203t-258.5 62h-159v-541z" />
+<glyph unicode="S" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69z" />
+<glyph unicode="T" d="M102 1298v164h1022v-164h-417v-1298h-187v1298h-418z" />
+<glyph unicode="U" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540z" />
+<glyph unicode="V" d="M33 1462h196l295 -927q45 -143 88 -334q33 152 93 340l292 921h199l-489 -1462h-187z" />
+<glyph unicode="W" d="M2 1462h170l88 -663q18 -145 39 -377q18 -203 18 -242q27 162 70 312l141 516h177l145 -521q57 -205 72 -307q6 92 65 619l70 663h170l-187 -1462h-190l-168 580q-43 147 -66 282q-31 -168 -65 -284l-156 -578h-190z" />
+<glyph unicode="X" d="M53 0l453 764l-422 698h199l331 -559l334 559h191l-422 -692l457 -770h-211l-355 635l-366 -635h-189z" />
+<glyph unicode="Y" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559z" />
+<glyph unicode="Z" d="M102 0v145l793 1151h-772v166h981v-145l-793 -1151h813v-166h-1022z" />
+<glyph unicode="[" d="M412 -324v1786h528v-149h-346v-1487h346v-150h-528z" />
+<glyph unicode="\" d="M211 1462h178l627 -1462h-178z" />
+<glyph unicode="]" d="M289 -174h346v1487h-346v149h528v-1786h-528v150z" />
+<glyph unicode="^" d="M111 549l424 924h102l481 -924h-162l-368 735l-318 -735h-159z" />
+<glyph unicode="_" d="M-16 -184h1259v-140h-1259v140z" />
+<glyph unicode="`" d="M418 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="a" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164z" />
+<glyph unicode="b" d="M158 0v1556h182v-376q0 -96 -8 -226h8q109 164 322 164q203 0 315 -149q115 -152 115 -418q0 -268 -115 -419.5t-315 -151.5q-207 0 -322 159h-12l-37 -139h-133zM340 551q0 -229 70 -324q72 -96 221 -96q272 0 272 422q0 414 -274 414q-154 0 -221.5 -94.5t-67.5 -321.5 z" />
+<glyph unicode="c" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418z" />
+<glyph unicode="d" d="M137 547q0 268 115 419.5t315 151.5q205 0 322 -160h12q-12 129 -12 162v436h182v-1556h-147l-27 147h-8q-115 -168 -322 -167q-203 0 -315 149q-115 152 -115 418zM326 545q0 -414 274 -414q152 0 219 88q66 88 70 287v41q0 229 -70 323q-72 96 -221 97 q-272 0 -272 -422z" />
+<glyph unicode="e" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305z" />
+<glyph unicode="f" d="M156 961v110l317 33v96q0 195 90 281q88 86 299 86q125 0 252 -35l-41 -143q-109 29 -207 28q-123 0 -168 -51q-43 -49 -43 -164v-104h389v-137h-389v-961h-182v961h-317z" />
+<glyph unicode="g" d="M102 -186q0 212 240 270q-96 47 -96 154q0 113 133 192q-86 35 -139 123q-51 84 -52 186q0 182 106.5 280.5t303.5 98.5q88 0 150 -20h378v-113l-196 -27q66 -88 65 -213q0 -162 -106 -256q-109 -96 -297 -96q-55 0 -86 6q-100 -55 -100 -133q0 -84 161 -84h187 q172 0 266 -78q92 -76 92 -219q0 -377 -565 -377q-218 0 -332 80q-113 81 -113 226zM274 -180q0 -174 271 -174q395 0 395 223q0 88 -49 118.5t-199 30.5h-188q-230 1 -230 -198zM367 745q0 -227 227 -227q223 0 223 230q0 240 -225 239.5t-225 -242.5z" />
+<glyph unicode="h" d="M160 0v1556h182v-462l-8 -144h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182z" />
+<glyph unicode="i" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM526 1435.5q0 114.5 106.5 114.5t106.5 -114q0 -57 -32.5 -86t-73.5 -29q-107 0 -107 114.5z" />
+<glyph unicode="j" d="M135 -303q131 -39 289 -39q119 0 182 57q66 59 66 158v1081l-420 21v123h602v-1215q0 -180 -113 -278q-111 -96 -319 -97q-160 0 -287 35v154zM637 1435.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="k" d="M215 0v1556h180v-714l-16 -289h4l135 152l395 393h222l-494 -475l522 -623h-213l-426 504l-129 -82v-422h-180z" />
+<glyph unicode="l" d="M188 0v123l344 20v1270l-268 21v122h451v-1413l352 -20v-123h-879z" />
+<glyph unicode="m" d="M92 0v1098h127l27 -148h10q68 168 201 168q164 0 213 -182h6q78 182 219 182q129 0 186 -92q57 -90 58 -309v-717h-162v707q0 147 -27 202q-27 57 -88 58q-88 0 -127 -82q-39 -80 -39 -279v-606h-161v707q0 260 -125 260q-82 0 -119 -80t-37 -318v-569h-162z" />
+<glyph unicode="n" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182z" />
+<glyph unicode="o" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416z" />
+<glyph unicode="p" d="M158 -492v1590h147l27 -148h8q111 168 322 168q203 0 315 -149q115 -152 115 -418q0 -268 -115 -419.5t-315 -151.5q-207 0 -322 159h-12q12 -129 12 -162v-469h-182zM340 551q0 -229 70 -324q72 -96 221 -96q272 0 272 422q0 414 -274 414q-152 0 -219.5 -88t-69.5 -287 v-41z" />
+<glyph unicode="q" d="M137 547q0 268 115 419.5t315 151.5q209 0 322 -168h8l27 148h147v-1590h-182v469q0 41 12 170h-12q-115 -168 -322 -167q-203 0 -315 149q-115 152 -115 418zM326 545q0 -414 274 -414q152 0 219 88q66 88 70 287v41q0 229 -70 323q-72 96 -221 97q-272 0 -272 -422z " />
+<glyph unicode="r" d="M264 0v1098h148l22 -201h8q76 117 162 170q84 51 215 51q119 0 240 -45l-49 -166q-121 45 -224 45q-163 0 -251 -92q-88 -90 -89 -268v-592h-182z" />
+<glyph unicode="s" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69z" />
+<glyph unicode="t" d="M139 961v94l267 49l77 287h105v-293h438v-137h-438v-637q0 -195 192 -195q98 0 240 21v-138q-137 -33 -252 -32q-362 0 -362 344v637h-267z" />
+<glyph unicode="u" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401z" />
+<glyph unicode="v" d="M82 1098h188l240 -652q84 -225 100 -325h6q8 53 101 325l239 652h189l-416 -1098h-231z" />
+<glyph unicode="w" d="M-4 1098h162l98 -543q39 -215 57 -393h6q33 195 68 358l133 578h193l127 -578q43 -188 67 -358h6q29 225 60 393l102 543h158l-225 -1098h-195l-131 596l-68 330h-6l-65 -334l-135 -592h-189z" />
+<glyph unicode="x" d="M96 0l414 563l-393 535h207l290 -410l291 410h207l-395 -535l413 -563h-206l-310 436l-311 -436h-207z" />
+<glyph unicode="y" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150z" />
+<glyph unicode="z" d="M182 0v125l660 836h-627v137h811v-146l-647 -815h665v-137h-862z" />
+<glyph unicode="{" d="M225 492v155q338 0 338 189v333q0 287 438 293v-149q-147 -4 -200 -39q-55 -37 -56 -119v-332q0 -209 -233 -248v-12q233 -39 233 -248v-331q0 -82 56 -119q53 -35 200 -39v-150q-438 6 -438 293v334q0 189 -338 189z" />
+<glyph unicode="|" d="M539 -492v2048h149v-2048h-149z" />
+<glyph unicode="}" d="M227 -174q141 0 198.5 39t57.5 119v331q0 209 234 248v12q-233 39 -234 248v332q0 80 -57 119t-199 39v149q438 -6 439 -293v-333q0 -188 338 -189v-155q-338 0 -338 -189v-334q0 -287 -439 -293v150z" />
+<glyph unicode="~" d="M152 586v162q98 109 247 108q102 0 248 -63q129 -55 201 -56q106 0 227 121v-162q-98 -109 -248 -108q-102 0 -247 63q-133 55 -201 56q-106 0 -227 -121z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#xa1;" d="M487 979q0 139 127 139t127 -139t-127 -139t-127 139zM502 -373l51 1049h121l51 -1049h-223z" />
+<glyph unicode="&#xa2;" d="M172 743q0 494 434 568v172h137v-164q158 -2 318 -59l-62 -158q-147 57 -268 57q-371 0 -371 -414q0 -406 361 -405q152 0 321 61v-159q-123 -59 -299 -62v-200h-137v206q-434 68 -434 557z" />
+<glyph unicode="&#xa3;" d="M119 0v154q201 49 200 284v213h-198v137h198v324q0 166 109 268q106 100 289 101q193 0 346 -80l-66 -144q-143 72 -272 72q-223 0 -223 -246v-295h377v-137h-377v-211q0 -199 -140 -274h748v-166h-991z" />
+<glyph unicode="&#xa4;" d="M174 1065l98 98l127 -129q101 68 215 68q115 0 213 -68l129 129l99 -96l-129 -129q68 -101 67 -215q0 -120 -67 -215l127 -127l-97 -96l-129 127q-100 -66 -213 -66q-117 0 -215 68l-127 -127l-96 96l127 127q-66 96 -65 213q0 113 65 213zM375 723q0 -98 71 -170 q70 -70 168 -70q102 0 172 70q72 72 72 170q0 100 -71.5 172t-172 72t-170 -70t-69.5 -174z" />
+<glyph unicode="&#xa5;" d="M78 1462h192l342 -739l346 739h191l-385 -768h240v-137h-302v-158h302v-137h-302v-262h-178v262h-301v137h301v158h-301v137h234z" />
+<glyph unicode="&#xa6;" d="M539 289h149v-781h-149v781zM539 776v780h149v-780h-149z" />
+<glyph unicode="&#xa7;" d="M244 55v158q170 -82 323 -82q240 0 240 141q0 55 -43 97q-45 41 -195 102q-197 82 -254 160q-55 74 -55 178q0 178 160 258q-160 80 -160 236q0 123 105 192q106 72 276 72q160 0 326 -72l-56 -139q-157 68 -276 67q-201 0 -201 -116q0 -53 49 -93q47 -37 197 -100 q158 -61 231 -139q74 -77 74 -191q0 -180 -145 -270q145 -80 145 -225q0 -139 -110.5 -219t-307.5 -80q-202 -1 -323 65zM414 831q0 -74 57 -126q55 -51 207 -117l35 -15q115 78 114 185q0 90 -73 145q-68 51 -207 103q-133 -50 -133 -175z" />
+<glyph unicode="&#xa8;" d="M330 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xa9;" d="M6 731q0 342 160 547t448 205q283 0 447 -203q162 -201 162 -549t-162 -549q-164 -203 -447 -202q-285 0 -446.5 204.5t-161.5 546.5zM115 731q0 -301 129 -473q127 -170 370 -170q242 0 369 170q131 174 131 473t-131 473q-127 170 -368.5 170t-370.5 -172t-129 -471z M248 733q0 209 110.5 332t300.5 123q127 0 254 -62l-61 -127q-106 53 -193 54q-123 0 -186 -86q-66 -88 -65 -236q0 -324 251 -323q98 0 215 45v-131q-108 -49 -221 -50q-197 0 -301 123t-104 338z" />
+<glyph unicode="&#xaa;" d="M276 989q0 117 84 168t277 57l125 5v10q0 133 -152 133q-117 0 -245 -51l-41 110q135 57 294 58q291 0 291 -238v-444h-110l-33 118q-104 -131 -268 -131q-222 0 -222 205zM428 987q0 -90 104 -90q106 0 168 55.5t62 145.5v20l-100 -2q-111 -2 -175 -29q-59 -24 -59 -100 z" />
+<glyph unicode="&#xab;" d="M197 526v27l309 414l117 -78l-238 -348l238 -348l-117 -78zM604 526v27l309 414l117 -78l-237 -348l237 -348l-117 -78z" />
+<glyph unicode="&#xac;" d="M152 647v150h923v-535h-149v385h-774z" />
+<glyph unicode="&#xad;" d="M285 465v168h659v-168h-659z" />
+<glyph unicode="&#xae;" d="M6 731q0 342 160 547t448 205q283 0 447 -203q162 -201 162 -549t-162 -549q-164 -203 -447 -202q-285 0 -446.5 204.5t-161.5 546.5zM115 731q0 -301 129 -473q127 -170 370 -170q242 0 369 170q131 174 131 473t-131 473q-127 170 -368.5 170t-370.5 -172t-129 -471z M348 285v893h234q326 0 325 -265q0 -163 -159 -233l237 -395h-178l-207 352h-94v-352h-158zM506 768h72q170 0 170 141q0 74 -41 103q-43 31 -132 30h-69v-274z" />
+<glyph unicode="&#xaf;" d="M-20 1556v140h1269v-140h-1269z" />
+<glyph unicode="&#xb0;" d="M299 1167q0 129 92 222q94 94 223 94q127 0 221.5 -94.5t94.5 -221.5q0 -129 -92.5 -221t-223.5 -92t-223 92t-92 221zM422 1167q0 -80 55 -135t137 -55q78 0 135.5 55t57.5 135t-57.5 137.5t-135.5 57.5q-80 0 -135 -57q-57 -62 -57 -138z" />
+<glyph unicode="&#xb1;" d="M152 0v150h923v-150h-923zM152 647v150h387v389h149v-389h387v-150h-387v-385h-149v385h-387z" />
+<glyph unicode="&#xb2;" d="M348 672v102l187 199q106 113 141 168q31 49 31 108q0 115 -111 115q-82 0 -164 -76l-78 86q115 102 248 103q121 0 182 -60q66 -61 66 -164q0 -66 -35 -135q-33 -66 -164 -196l-135 -136h363v-114h-531z" />
+<glyph unicode="&#xb3;" d="M342 705v124q113 -66 203 -65q150 0 149 137q0 125 -147 125h-72v104h70q123 0 123 127q0 111 -97 111q-74 0 -161 -70l-66 86q111 92 238 93q113 0 174 -54q63 -55 63 -149q0 -139 -149 -189q176 -41 176 -186q0 -117 -74 -180q-72 -63 -215 -64q-132 1 -215 50z" />
+<glyph unicode="&#xb4;" d="M418 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xb5;" d="M180 -492v1590h182v-707q0 -260 218 -260q152 0 217 90q70 94 69 307v570h183v-1098h-148l-27 147h-10q-96 -168 -295 -167q-139 0 -213 88q6 -154 6 -240v-320h-182z" />
+<glyph unicode="&#xb6;" d="M66 1042q0 256 108 388q106 127 342 126h563v-1816h-121v1657h-206v-1657h-121v819q-61 -18 -146 -18q-419 -1 -419 501z" />
+<glyph unicode="&#xb7;" d="M487 723q0 139 127 139t127 -139t-127 -139t-127 139z" />
+<glyph unicode="&#xb8;" d="M428 -375q34 -6 80 -6q152 0 151 92q0 72 -172 113l91 176h120l-57 -115q160 -37 160 -172q0 -205 -291 -205q-39 0 -82 9v108z" />
+<glyph unicode="&#xb9;" d="M367 1309l219 151h135v-788h-146v465q0 84 9 200q-43 -45 -74 -65l-70 -51z" />
+<glyph unicode="&#xba;" d="M281 1133q0 160 90 253q88 92 245 93q145 0 238 -93q94 -94 94 -253q0 -164 -92 -256.5t-244 -92.5q-145 0 -237 93q-94 94 -94 256zM432 1133q0 -229 182 -230q180 0 181 230q0 225 -181 225q-182 0 -182 -225z" />
+<glyph unicode="&#xbb;" d="M197 193l237 348l-237 348l116 78l310 -414v-27l-310 -411zM604 193l238 348l-238 348l117 78l309 -414v-27l-309 -411z" />
+<glyph unicode="&#xbc;" d="M23 1309l219 151h135v-788h-146v465q0 84 9 200q-43 -45 -74 -65l-70 -51zM170 0l729 1462h158l-729 -1462h-158zM606 174v98l377 523h141v-508h84v-113h-84v-174h-143v174h-375zM751 287h230v176q0 83 6 172q-37 -70 -80 -131z" />
+<glyph unicode="&#xbd;" d="M2 1309l219 151h135v-788h-146v465q0 84 9 200q-43 -45 -74 -65l-70 -51zM104 0l729 1462h158l-729 -1462h-158zM694 0v102l187 199q106 113 141 168q31 49 31 108q0 115 -111 115q-82 0 -164 -76l-78 86q115 102 248 103q121 0 182 -60q66 -61 66 -164q0 -66 -35 -135 q-33 -66 -164 -196l-135 -136h363v-114h-531z" />
+<glyph unicode="&#xbe;" d="M20 705v124q113 -66 203 -65q150 0 149 137q0 125 -147 125h-72v104h70q123 0 123 127q0 111 -97 111q-74 0 -161 -70l-66 86q111 92 238 93q113 0 174 -54q63 -55 63 -149q0 -139 -149 -189q176 -41 176 -186q0 -117 -74 -180q-72 -63 -215 -64q-132 1 -215 50zM223 0 l729 1462h158l-729 -1462h-158zM627 174v98l377 523h141v-508h84v-113h-84v-174h-143v174h-375zM772 287h230v176q0 83 6 172q-37 -70 -80 -131z" />
+<glyph unicode="&#xbf;" d="M168 -35q0 133 53 217q52 83 197 191q113 80 151 141q33 51 33 143v19h160v-37q0 -115 -45 -193q-45 -76 -162 -159q-127 -96 -170 -156q-43 -57 -43 -158q0 -94 74 -149q76 -57 207 -57q178 0 370 90l62 -144q-215 -106 -422 -106q-217 0 -340 98q-125 100 -125 260z M547 979q0 139 127 139t127 -139t-127 -139t-127 139z" />
+<glyph unicode="&#xc0;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM340 1886v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xc1;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM520 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xc2;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM283 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xc3;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM254 1579q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56 q-82 0 -107 -115h-104z" />
+<glyph unicode="&#xc4;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM330 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xc5;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM387 1581q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158z M498 1581q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31q-49 0 -80 -31q-32 -33 -32 -82z" />
+<glyph unicode="&#xc6;" d="M0 0l338 1462h872v-164h-477v-452h438v-162h-438v-520h477v-164h-653v453h-289l-96 -453h-172zM305 618h252v680h-106z" />
+<glyph unicode="&#xc7;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557zM508 -375q34 -6 80 -6q152 0 151 92 q0 72 -172 113l91 176h120l-57 -115q160 -37 160 -172q0 -205 -291 -205q-39 0 -82 9v108z" />
+<glyph unicode="&#xc8;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM344 1886v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xc9;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM481 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xca;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM318 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xcb;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM355 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM730 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xcc;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM309 1886v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xcd;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM537 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xce;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM283 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xcf;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xd0;" d="M0 659v162h135v641h342q319 0 494 -188q176 -193 176 -529q0 -365 -182 -552q-186 -193 -529 -193h-301v659h-135zM322 160h96q532 0 532 579q0 563 -493 564h-135v-482h380v-162h-380v-499z" />
+<glyph unicode="&#xd1;" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172zM258 1579q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#xd2;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM336 1886v21h219q88 -182 174 -301v-27h-121 q-163 139 -272 307z" />
+<glyph unicode="&#xd3;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM508 1579v27q92 127 174 301h219v-21 q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xd4;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM283 1579v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xd5;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM262 1579q25 264 211 264q57 0 162 -55 q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#xd6;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM332 1732.5q0 102.5 96 102.5t96 -102.5 t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xd7;" d="M190 1042l105 105l317 -318l322 318l104 -103l-321 -321l319 -320l-102 -102l-322 317l-317 -315l-102 103l315 317z" />
+<glyph unicode="&#xd8;" d="M80 2l121 197q-117 184 -117 536q0 750 534 750q186 0 310 -105l92 152l137 -78l-125 -201q115 -188 115 -520q0 -362 -137 -557q-138 -197 -394 -196q-193 0 -307 94l-92 -150zM281 733q0 -205 38 -342l515 836q-80 94 -216 94q-337 0 -337 -588zM403 229 q80 -86 213 -86q174 0 254 145.5t80 444.5q0 205 -35 328z" />
+<glyph unicode="&#xd9;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM348 1886v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xda;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM494 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xdb;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM283 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xdc;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xdd;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM494 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xde;" d="M176 0v1462h186v-252h218q514 0 514 -428q0 -219 -137.5 -342t-403.5 -123h-191v-317h-186zM362 475h170q195 0 283 72q86 72 86 225q0 279 -338 279h-201v-576z" />
+<glyph unicode="&#xdf;" d="M164 0v1200q0 367 424 367q195 0 303 -80t108 -227q0 -131 -133 -248q-80 -72 -108 -107q-25 -31 -25 -63q0 -37 29 -70q27 -29 151 -110q144 -95 191 -173t47 -176q0 -162 -100.5 -247.5t-282.5 -85.5q-178 0 -289 69v166q143 -86 277 -86q213 0 213 174q0 80 -45 131 t-144 113q-125 78 -174 139.5t-49 147.5q0 117 129 223q129 108 129 196q0 164 -227 164q-242 0 -242 -215v-1202h-182z" />
+<glyph unicode="&#xe0;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM332 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xe1;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM502 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xe2;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM291 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xe3;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM264 1241q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#xe4;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM342 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM717 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xe5;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM387 1456q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158zM498 1456q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31 q-49 0 -80 -31q-32 -33 -32 -82z" />
+<glyph unicode="&#xe6;" d="M45 307q0 334 328 348l149 7v69q0 236 -139 236q-109 0 -211 -82l-57 137q133 96 276 96q187 0 246 -178q77 178 240 178q137 0 223 -135t86 -356v-113h-496q3 -190 68 -283q66 -92 168 -92q113 0 233 76v-162q-106 -74 -241 -73q-221 0 -316 229q-104 -229 -301 -229 q-117 0 -186 86q-70 83 -70 241zM215 305q0 -82 33 -131q31 -47 86 -47q84 0 135 82t51 229v99l-88 -7q-217 -18 -217 -225zM694 662h316q0 137 -41 223q-39 82 -111 82q-66 0 -113 -78q-45 -75 -51 -227z" />
+<glyph unicode="&#xe7;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418zM477 -375q34 -6 80 -6q152 0 151 92q0 72 -172 113l91 176h120l-57 -115 q160 -37 160 -172q0 -205 -291 -205q-39 0 -82 9v108z" />
+<glyph unicode="&#xe8;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM375 1548v21h219q88 -182 174 -301v-27h-121 q-163 139 -272 307z" />
+<glyph unicode="&#xe9;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM500 1241v27q92 127 174 301h219v-21 q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xea;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM299 1241v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xeb;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM348 1394.5q0 102.5 96 102.5t96 -102.5 t-96 -102.5t-96 102.5zM723 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xec;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM332 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xed;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM531 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xee;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM283 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xef;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM330 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xf0;" d="M135 477.5q0 233.5 121 364.5q121 129 334 129q211 0 299 -119l8 4q-57 225 -242 391l-256 -153l-73 114l217 131q-113 76 -172 109l69 123q135 -66 246 -148l227 138l74 -113l-194 -117q301 -291 301 -758q0 -279 -129 -436t-353 -157q-213 0 -346 133 q-131 131 -131 364.5zM328 471q0 -340 288 -340q152 0 222 100q68 98 67 295q0 129 -77.5 213t-213.5 84q-286 0 -286 -352z" />
+<glyph unicode="&#xf1;" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182zM260 1241q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115 h-104z" />
+<glyph unicode="&#xf2;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM377 1548v21h219q88 -182 174 -301v-27h-121 q-163 139 -272 307z" />
+<glyph unicode="&#xf3;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM498 1241v27q92 127 174 301h219v-21 q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xf4;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM279 1241v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xf5;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM254 1241q25 264 211 264q57 0 162 -55 q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#xf6;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM324 1394.5q0 102.5 96 102.5t96 -102.5 t-96 -102.5t-96 102.5zM699 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#xf7;" d="M152 647v150h923v-150h-923zM498 373q0 125 114.5 125t114.5 -125t-114.5 -125t-114.5 125zM498 1071q0 125 114.5 125t114.5 -125t-114.5 -125t-114.5 125z" />
+<glyph unicode="&#xf8;" d="M115 551q0 264 133 415.5t368 151.5q129 0 236 -57l76 119l131 -84l-84 -131q137 -156 137 -414q0 -272 -135 -421.5t-367 -149.5q-127 0 -233 53l-76 -119l-131 84l84 131q-139 158 -139 422zM303 551q0 -178 53 -275l406 656q-66 35 -156 35q-162 0 -231 -103 q-72 -106 -72 -313zM467 164q59 -33 154 -33q162 0 233 105q70 102 70 315q0 166 -52 266z" />
+<glyph unicode="&#xf9;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM340 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#xfa;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM500 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xfb;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM291 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#xfc;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM332 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z " />
+<glyph unicode="&#xfd;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150zM494 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#xfe;" d="M158 -492v2048h182v-458l-8 -148h8q111 168 322 168q203 0 315 -149q115 -152 115 -418q0 -268 -115 -419.5t-315 -151.5q-207 0 -322 159h-12q12 -129 12 -162v-469h-182zM340 551q0 -229 70 -324q72 -96 221 -96q272 0 272 422q0 414 -274 414q-152 0 -219.5 -88 t-69.5 -287v-41z" />
+<glyph unicode="&#xff;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150zM338 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM713 1394.5 q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x100;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM326 1579v150h575v-150h-575z" />
+<glyph unicode="&#x101;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM318 1241v150h575v-150h-575z" />
+<glyph unicode="&#x102;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM311 1856h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x103;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM303 1518h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x104;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM813 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x105;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM705 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x106;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557zM660 1579v27q92 127 174 301h219v-21 q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x107;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418zM578 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x108;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557zM443 1579v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x109;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418zM367 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121 q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x10a;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557zM672 1732.5q0 114.5 106.5 114.5 t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x10b;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418zM592 1394.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5 t-106.5 114.5z" />
+<glyph unicode="&#x10c;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557zM437 1880v27h120q82 -55 211 -187 q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x10d;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418zM375 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67 q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x10e;" d="M135 0v1462h342q319 0 494 -188q176 -193 176 -529q0 -365 -182 -552q-186 -193 -529 -193h-301zM322 160h96q532 0 532 579q0 563 -493 564h-135v-1143zM275 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z " />
+<glyph unicode="&#x10f;" d="M80 547q0 268 115 419.5t315 151.5q205 0 322 -160h12q-12 129 -12 162v436h182v-1556h-147l-27 147h-8q-115 -168 -322 -167q-203 0 -315 149q-115 152 -115 418zM269 545q0 -414 274 -414q152 0 219 88q66 88 70 287v41q0 229 -70 323q-72 96 -221 97q-272 0 -272 -422 zM1074 1229v26l26 107q27 127 35 194h180v-20q0 -14 -43 -113q-49 -111 -102 -194h-96z" />
+<glyph unicode="&#x110;" d="M0 659v162h135v641h342q319 0 494 -188q176 -193 176 -529q0 -365 -182 -552q-186 -193 -529 -193h-301v659h-135zM322 160h96q532 0 532 579q0 563 -493 564h-135v-482h380v-162h-380v-499z" />
+<glyph unicode="&#x111;" d="M137 526q0 260 115 405.5t315 145.5q207 0 322 -159h12q-12 127 -12 161v158h-379v137h379v182h182v-182h156v-137h-156v-1237h-147l-27 147h-8q-115 -168 -322 -167q-201 0 -315.5 145t-114.5 401zM326 524q0 -393 274 -393q150 0 217 82q70 84 72 274v39q0 217 -70 308 q-71 92 -221 92q-272 -1 -272 -402z" />
+<glyph unicode="&#x112;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM336 1579v150h575v-150h-575z" />
+<glyph unicode="&#x113;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM346 1241v150h575v-150h-575z" />
+<glyph unicode="&#x114;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM342 1856h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x115;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM329 1518h109q6 -76 47 -101q39 -25 143 -24 q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x116;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM543 1703.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x117;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM531 1394.5q0 114.5 106.5 114.5 t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x118;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM619 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x119;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM641 -221q0 144 190 252h131 q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x11a;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM318 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x11b;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM308 1542v27h120q82 -55 211 -187 q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x11c;" d="M117 733q0 352 161.5 551t446.5 199q193 0 346 -86l-72 -162q-150 84 -280 84q-193 0 -299.5 -155.5t-106.5 -432.5q0 -588 394 -588q94 0 202 29v436h-237v164h422v-717q-199 -76 -420 -75q-262 0 -410 200q-147 200 -147 553zM363 1579v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x11d;" d="M102 -186q0 212 240 270q-96 47 -96 154q0 113 133 192q-86 35 -139 123q-51 84 -52 186q0 182 106.5 280.5t303.5 98.5q88 0 150 -20h378v-113l-196 -27q66 -88 65 -213q0 -162 -106 -256q-109 -96 -297 -96q-55 0 -86 6q-100 -55 -100 -133q0 -84 161 -84h187 q172 0 266 -78q92 -76 92 -219q0 -377 -565 -377q-218 0 -332 80q-113 81 -113 226zM274 -180q0 -174 271 -174q395 0 395 223q0 88 -49 118.5t-199 30.5h-188q-230 1 -230 -198zM367 745q0 -227 227 -227q223 0 223 230q0 240 -225 239.5t-225 -242.5zM275 1241v27l59 67 q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x11e;" d="M117 733q0 352 161.5 551t446.5 199q193 0 346 -86l-72 -162q-150 84 -280 84q-193 0 -299.5 -155.5t-106.5 -432.5q0 -588 394 -588q94 0 202 29v436h-237v164h422v-717q-199 -76 -420 -75q-262 0 -410 200q-147 200 -147 553zM411 1856h109q6 -76 47 -101 q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x11f;" d="M102 -186q0 212 240 270q-96 47 -96 154q0 113 133 192q-86 35 -139 123q-51 84 -52 186q0 182 106.5 280.5t303.5 98.5q88 0 150 -20h378v-113l-196 -27q66 -88 65 -213q0 -162 -106 -256q-109 -96 -297 -96q-55 0 -86 6q-100 -55 -100 -133q0 -84 161 -84h187 q172 0 266 -78q92 -76 92 -219q0 -377 -565 -377q-218 0 -332 80q-113 81 -113 226zM274 -180q0 -174 271 -174q395 0 395 223q0 88 -49 118.5t-199 30.5h-188q-230 1 -230 -198zM367 745q0 -227 227 -227q223 0 223 230q0 240 -225 239.5t-225 -242.5zM301 1518h109 q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x120;" d="M117 733q0 352 161.5 551t446.5 199q193 0 346 -86l-72 -162q-150 84 -280 84q-193 0 -299.5 -155.5t-106.5 -432.5q0 -588 394 -588q94 0 202 29v436h-237v164h422v-717q-199 -76 -420 -75q-262 0 -410 200q-147 200 -147 553zM617 1732.5q0 114.5 106.5 114.5 t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x121;" d="M102 -186q0 212 240 270q-96 47 -96 154q0 113 133 192q-86 35 -139 123q-51 84 -52 186q0 182 106.5 280.5t303.5 98.5q88 0 150 -20h378v-113l-196 -27q66 -88 65 -213q0 -162 -106 -256q-109 -96 -297 -96q-55 0 -86 6q-100 -55 -100 -133q0 -84 161 -84h187 q172 0 266 -78q92 -76 92 -219q0 -377 -565 -377q-218 0 -332 80q-113 81 -113 226zM274 -180q0 -174 271 -174q395 0 395 223q0 88 -49 118.5t-199 30.5h-188q-230 1 -230 -198zM367 745q0 -227 227 -227q223 0 223 230q0 240 -225 239.5t-225 -242.5zM508 1394.5 q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x122;" d="M117 733q0 352 161.5 551t446.5 199q193 0 346 -86l-72 -162q-150 84 -280 84q-193 0 -299.5 -155.5t-106.5 -432.5q0 -588 394 -588q94 0 202 29v436h-237v164h422v-717q-199 -76 -420 -75q-262 0 -410 200q-147 200 -147 553zM540 -426q63 145 84 301h178v-20 q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x123;" d="M102 -186q0 212 240 270q-96 47 -96 154q0 113 133 192q-86 35 -139 123q-51 84 -52 186q0 182 106.5 280.5t303.5 98.5q88 0 150 -20h378v-113l-196 -27q66 -88 65 -213q0 -162 -106 -256q-109 -96 -297 -96q-55 0 -86 6q-100 -55 -100 -133q0 -84 161 -84h187 q172 0 266 -78q92 -76 92 -219q0 -377 -565 -377q-218 0 -332 80q-113 81 -113 226zM274 -180q0 -174 271 -174q395 0 395 223q0 88 -49 118.5t-199 30.5h-188q-230 1 -230 -198zM367 745q0 -227 227 -227q223 0 223 230q0 240 -225 239.5t-225 -242.5zM528 1241v21 q0 20 45 118q45 100 119 189h98v-27q-61 -145 -83 -301h-179z" />
+<glyph unicode="&#x124;" d="M135 0v1462h187v-616h585v616h187v-1462h-187v682h-585v-682h-187zM283 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x125;" d="M160 0v1556h182v-462l-8 -144h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182zM297 1634v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x126;" d="M0 1069v150h135v243h187v-243h585v243h187v-243h135v-150h-135v-1069h-187v682h-585v-682h-187v1069h-135zM322 846h585v223h-585v-223z" />
+<glyph unicode="&#x127;" d="M4 1237v137h156v182h184v-182h418v-137h-420v-184l-10 -144h10q106 168 346 168q190 0 287 -96q94 -94 94 -305v-676h-182v666q0 260 -236 260q-160 0 -235 -95q-74 -92 -74 -303v-528h-182v1237h-156z" />
+<glyph unicode="&#x128;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM254 1579q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#x129;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM252 1241q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#x12a;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM328 1579v150h575v-150h-575z" />
+<glyph unicode="&#x12b;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM326 1241v150h575v-150h-575z" />
+<glyph unicode="&#x12c;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM313 1856h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x12d;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM338 1518h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x12e;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM422 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x12f;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM526 1435.5q0 114.5 106.5 114.5t106.5 -114q0 -57 -32.5 -86t-73.5 -29q-107 0 -107 114.5zM439 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23 q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x130;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM508 1732.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x131;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878z" />
+<glyph unicode="&#x132;" d="M156 0v1462h186v-1462h-186zM492 23v163q90 -45 186 -45q195 0 194 283v1038h187v-1026q0 -457 -365 -456q-134 0 -202 43z" />
+<glyph unicode="&#x133;" d="M188 1435.5q0 114.5 106.5 114.5t106.5 -114q0 -57 -32.5 -86t-73.5 -29q-107 0 -107 114.5zM203 0v1098h182v-1098h-182zM502 -303q86 -39 190 -39q164 0 164 215v1081l-215 21v123h397v-1215q0 -182 -86 -278.5t-235 -96.5q-121 0 -215 35v154zM821 1435.5 q0 114.5 106.5 114.5t106.5 -114q0 -58 -30 -86q-33 -29 -76 -29q-107 0 -107 114.5z" />
+<glyph unicode="&#x134;" d="M137 39v166q162 -61 309 -62q162 0 254.5 80t92.5 226v1013h186v-1011q0 -215 -141 -345q-139 -127 -377 -126q-215 0 -324 59zM551 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x135;" d="M303 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120zM135 -303q131 -39 289 -39q119 0 182 57q66 59 66 158v1081l-420 21v123h602v-1215q0 -180 -113 -278q-111 -96 -319 -97q-160 0 -287 35v154z" />
+<glyph unicode="&#x136;" d="M211 0v1462h186v-731l121 168l453 563h209l-521 -637l539 -825h-211l-450 698l-140 -114v-584h-186zM510 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x137;" d="M215 0v1556h180v-714l-16 -289h4l135 152l395 393h222l-494 -475l522 -623h-213l-426 504l-129 -82v-422h-180zM485 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x138;" d="M215 0v1098h180v-291l-16 -299h4l137 166l402 424h213l-494 -510l522 -588h-213l-426 469l-129 -82v-387h-180z" />
+<glyph unicode="&#x139;" d="M233 0v1462h187v-1296h635v-166h-822zM262 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x13a;" d="M188 0v123l344 20v1270l-268 21v122h451v-1413l352 -20v-123h-879zM496 1636v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x13b;" d="M233 0v1462h187v-1296h635v-166h-822zM491 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x13c;" d="M188 0v123l344 20v1270l-268 21v122h451v-1413l352 -20v-123h-879zM460 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x13d;" d="M233 0v1462h187v-1296h635v-166h-822zM750 1137v26l26 107q27 127 35 194h180v-20q0 -14 -43 -113q-49 -111 -102 -194h-96z" />
+<glyph unicode="&#x13e;" d="M188 0v123l344 20v1270l-268 21v122h451v-1413l352 -20v-123h-879zM865 1229v26l26 107q27 127 35 194h180v-20q0 -14 -43 -113q-49 -111 -102 -194h-96z" />
+<glyph unicode="&#x13f;" d="M233 0v1462h187v-1296h635v-166h-822zM750 773.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x140;" d="M188 0v123l344 20v1270l-268 21v122h451v-1413l352 -20v-123h-879zM866 681.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x141;" d="M72 539l198 125v798h187v-680l299 189l78 -125l-377 -238v-442h635v-166h-822v492l-125 -78z" />
+<glyph unicode="&#x142;" d="M188 0v123l344 20v449l-141 -92l-78 121l219 143v649l-268 21v122h451v-673l164 108l77 -121l-241 -159v-568l352 -20v-123h-879z" />
+<glyph unicode="&#x143;" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172zM516 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x144;" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182zM529 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x145;" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172zM434 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x146;" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182zM454 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x147;" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172zM281 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x148;" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-717h-182v707q0 260 -238 260q-307 0 -307 -398v-569h-182zM295 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x149;" d="M-16 961q59 231 100 501h199l14 -22q-47 -190 -176 -479h-137zM262 0v1098h148l26 -148h10q43 77 129 123q84 45 189 45q367 0 366 -401v-717h-182v707q0 260 -219 260q-285 0 -285 -398v-569h-182z" />
+<glyph unicode="&#x14a;" d="M135 0v1462h213l578 -1128h10q-18 272 -18 403v725h174v-1442q0 -201 -101 -303q-102 -106 -286 -106q-94 0 -156 24v160q74 -20 158 -20q211 0 211 225l-621 1210h-8q18 -276 18 -417v-793h-172z" />
+<glyph unicode="&#x14b;" d="M160 0v1098h147l27 -148h10q104 168 336 168q389 0 389 -401v-875q0 -334 -291 -334q-82 0 -133 25v148q53 -20 115 -21q127 0 127 170v877q0 260 -238 260q-307 0 -307 -398v-569h-182z" />
+<glyph unicode="&#x14c;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM330 1579v150h575v-150h-575z" />
+<glyph unicode="&#x14d;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM326 1241v150h575v-150h-575z" />
+<glyph unicode="&#x14e;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM313 1856h109q6 -76 47 -101q39 -25 143 -24 q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x14f;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM313 1518h109q6 -76 47 -101q39 -25 143 -24 q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x150;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM326 1579v27q92 127 174 301h198v-21 q-109 -168 -272 -307h-100zM688 1579v27q92 125 174 301h199v-21q-109 -168 -272 -307h-101z" />
+<glyph unicode="&#x151;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM328 1241v27q92 127 174 301h198v-21 q-109 -168 -272 -307h-100zM690 1241v27q92 125 174 301h199v-21q-109 -168 -272 -307h-101z" />
+<glyph unicode="&#x152;" d="M20 735q0 750 512 750q80 0 154 -23h541v-164h-398v-452h359v-162h-359v-520h398v-164h-574l-49 -10q-57 -10 -96 -10q-488 -1 -488 755zM209 733q0 -590 309 -590q70 0 133 33v1112q-57 33 -131 33q-311 0 -311 -588z" />
+<glyph unicode="&#x153;" d="M57 551q0 268 88 417.5t242 149.5q172 0 260 -217q82 217 242 217q131 0 209 -133q76 -131 76 -358v-113h-439q2 -375 189 -375q111 0 204 76v-162q-96 -74 -217 -73q-88 0 -159 59q-70 57 -101 162q-90 -221 -266 -221q-145 0 -238 153q-90 150 -90 418zM227 551 q0 -213 39 -315q41 -104 131 -105q168 0 168 410q0 426 -170 426q-90 0 -129 -102.5t-39 -313.5zM737 662h260q0 305 -123 305q-125 0 -137 -305z" />
+<glyph unicode="&#x154;" d="M186 0v1462h357q520 0 520 -415q0 -287 -289 -392l397 -655h-219l-350 604h-229v-604h-187zM373 762h164q170 0 251.5 65.5t81.5 210.5q0 141 -79.5 203t-258.5 62h-159v-541zM447 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x155;" d="M264 0v1098h148l22 -201h8q76 117 162 170q84 51 215 51q119 0 240 -45l-49 -166q-121 45 -224 45q-163 0 -251 -92q-88 -90 -89 -268v-592h-182zM510 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x156;" d="M186 0v1462h357q520 0 520 -415q0 -287 -289 -392l397 -655h-219l-350 604h-229v-604h-187zM373 762h164q170 0 251.5 65.5t81.5 210.5q0 141 -79.5 203t-258.5 62h-159v-541zM481 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x157;" d="M264 0v1098h148l22 -201h8q76 117 162 170q84 51 215 51q119 0 240 -45l-49 -166q-121 45 -224 45q-163 0 -251 -92q-88 -90 -89 -268v-592h-182zM186 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x158;" d="M186 0v1462h357q520 0 520 -415q0 -287 -289 -392l397 -655h-219l-350 604h-229v-604h-187zM373 762h164q170 0 251.5 65.5t81.5 210.5q0 141 -79.5 203t-258.5 62h-159v-541zM252 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234 h-193q-33 74 -176 234z" />
+<glyph unicode="&#x159;" d="M264 0v1098h148l22 -201h8q76 117 162 170q84 51 215 51q119 0 240 -45l-49 -166q-121 45 -224 45q-163 0 -251 -92q-88 -90 -89 -268v-592h-182zM295 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x15a;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69zM514 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x15b;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69zM512 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x15c;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69zM303 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x15d;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69zM306 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x15e;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69zM405 -375q34 -6 80 -6q152 0 151 92q0 72 -172 113l91 176h120l-57 -115q160 -37 160 -172q0 -205 -291 -205q-39 0 -82 9v108z" />
+<glyph unicode="&#x15f;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69zM420 -375q34 -6 80 -6q152 0 151 92q0 72 -172 113l91 176h120l-57 -115q160 -37 160 -172q0 -205 -291 -205q-39 0 -82 9v108z" />
+<glyph unicode="&#x160;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69zM314 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x161;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69zM293 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x162;" d="M102 1298v164h1022v-164h-417v-1298h-187v1298h-418zM448 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x163;" d="M139 961v94l267 49l77 287h105v-293h438v-137h-438v-637q0 -195 192 -195q98 0 240 21v-138q-137 -33 -252 -32q-362 0 -362 344v637h-267zM489 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x164;" d="M102 1298v164h1022v-164h-417v-1298h-187v1298h-418zM283 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x165;" d="M139 961v94l267 49l77 287h105v-293h438v-137h-438v-637q0 -195 192 -195q98 0 240 21v-138q-137 -33 -252 -32q-362 0 -362 344v637h-267zM799 1229v26l26 107q27 127 35 194h180v-20q0 -14 -43 -113q-49 -111 -102 -194h-96z" />
+<glyph unicode="&#x166;" d="M102 1298v164h1022v-164h-417v-479h294v-149h-294v-670h-187v670h-297v149h297v479h-418z" />
+<glyph unicode="&#x167;" d="M139 961v94l267 49l77 287h105v-293h438v-137h-438v-248h307v-138h-307v-251q0 -195 192 -195q98 0 240 21v-138q-137 -33 -252 -32q-362 0 -362 344v251h-162v138h162v248h-267z" />
+<glyph unicode="&#x168;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM260 1579q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56 q-82 0 -107 -115h-104z" />
+<glyph unicode="&#x169;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM256 1241q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56 q-82 0 -107 -115h-104z" />
+<glyph unicode="&#x16a;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM326 1579v150h575v-150h-575z" />
+<glyph unicode="&#x16b;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM328 1241v150h575v-150h-575z" />
+<glyph unicode="&#x16c;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM313 1856h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x16d;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM313 1518h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x16e;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM389 1794q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158z M500 1794q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31q-49 0 -80 -31q-32 -33 -32 -82z" />
+<glyph unicode="&#x16f;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM385 1456q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57 q-62 58 -62 158zM496 1456q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31q-49 0 -80 -31q-32 -33 -32 -82z" />
+<glyph unicode="&#x170;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM322 1579v27q92 127 174 301h198v-21q-109 -168 -272 -307h-100zM684 1579v27q92 125 174 301h199v-21q-109 -168 -272 -307h-101z" />
+<glyph unicode="&#x171;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM326 1241v27q92 127 174 301h198v-21q-109 -168 -272 -307h-100zM688 1241v27q92 125 174 301h199v-21q-109 -168 -272 -307h-101z " />
+<glyph unicode="&#x172;" d="M125 520v942h186v-932q0 -387 307 -387q293 0 300 389v932h186v-948q0 -260 -125 -397q-127 -139 -371 -139q-483 -1 -483 540zM441 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x173;" d="M160 381v717h182v-707q0 -260 236 -260q162 0 235.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-106 -168 -334 -167q-391 0 -391 401zM723 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54 q-63 55 -63 149z" />
+<glyph unicode="&#x174;" d="M2 1462h170l88 -663q18 -145 39 -377q18 -203 18 -242q27 162 70 312l141 516h177l145 -521q57 -205 72 -307q6 92 65 619l70 663h170l-187 -1462h-190l-168 580q-43 147 -66 282q-31 -168 -65 -284l-156 -578h-190zM285 1579v27l59 67q141 156 176 234h193 q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x175;" d="M-4 1098h162l98 -543q39 -215 57 -393h6q33 195 68 358l133 578h193l127 -578q43 -188 67 -358h6q29 225 60 393l102 543h158l-225 -1098h-195l-131 596l-68 330h-6l-65 -334l-135 -592h-189zM281 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121 q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x176;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM283 1579v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x177;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150zM285 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121 q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x178;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x179;" d="M102 0v145l793 1151h-772v166h981v-145l-793 -1151h813v-166h-1022zM475 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x17a;" d="M182 0v125l660 836h-627v137h811v-146l-647 -815h665v-137h-862zM496 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x17b;" d="M102 0v145l793 1151h-772v166h981v-145l-793 -1151h813v-166h-1022zM524 1732.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x17c;" d="M182 0v125l660 836h-627v137h811v-146l-647 -815h665v-137h-862zM524 1394.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x17d;" d="M102 0v145l793 1151h-772v166h981v-145l-793 -1151h813v-166h-1022zM283 1880v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x17e;" d="M182 0v125l660 836h-627v137h811v-146l-647 -815h665v-137h-862zM295 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x17f;" d="M356 0v1200q0 188 90 279q88 88 299 88q121 0 273 -35l-41 -143q-109 29 -227.5 28.5t-163.5 -49.5q-47 -51 -47 -166v-1202h-183z" />
+<glyph unicode="&#x192;" d="M215 -324q59 -18 115 -18q92 0 123 51q33 55 32 164v963h-194v75l194 68v137q0 190 76 278.5t256 88.5q96 0 197 -37l-47 -141q-82 29 -144 28q-92 0 -123 -51q-33 -55 -32 -164v-145h245v-137h-245v-961q0 -190 -76 -278.5t-256 -88.5q-55 0 -121 15v153z" />
+<glyph unicode="&#x1f0;" d="M135 -303q131 -39 289 -39q119 0 182 57q66 59 66 158v1081l-420 21v123h602v-1215q0 -180 -113 -278q-111 -96 -319 -97q-160 0 -287 35v154zM275 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x1fa;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM389 1581q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158z M500 1581q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31q-49 0 -80 -31q-32 -33 -32 -82zM490 1835v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1fb;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM387 1456q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158zM498 1456q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31 q-49 0 -80 -31q-32 -33 -32 -82zM512 1720v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1fc;" d="M0 0l338 1462h872v-164h-477v-452h438v-162h-438v-520h477v-164h-653v453h-289l-96 -453h-172zM305 618h252v680h-106zM631 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1fd;" d="M45 307q0 334 328 348l149 7v69q0 236 -139 236q-109 0 -211 -82l-57 137q133 96 276 96q187 0 246 -178q77 178 240 178q137 0 223 -135t86 -356v-113h-496q3 -190 68 -283q66 -92 168 -92q113 0 233 76v-162q-106 -74 -241 -73q-221 0 -316 229q-104 -229 -301 -229 q-117 0 -186 86q-70 83 -70 241zM215 305q0 -82 33 -131q31 -47 86 -47q84 0 135 82t51 229v99l-88 -7q-217 -18 -217 -225zM694 662h316q0 137 -41 223q-39 82 -111 82q-66 0 -113 -78q-45 -75 -51 -227zM531 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z " />
+<glyph unicode="&#x1fe;" d="M80 2l121 197q-117 184 -117 536q0 750 534 750q186 0 310 -105l92 152l137 -78l-125 -201q115 -188 115 -520q0 -362 -137 -557q-138 -197 -394 -196q-193 0 -307 94l-92 -150zM281 733q0 -205 38 -342l515 836q-80 94 -216 94q-337 0 -337 -588zM403 229 q80 -86 213 -86q174 0 254 145.5t80 444.5q0 205 -35 328zM475 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1ff;" d="M115 551q0 264 133 415.5t368 151.5q129 0 236 -57l76 119l131 -84l-84 -131q137 -156 137 -414q0 -272 -135 -421.5t-367 -149.5q-127 0 -233 53l-76 -119l-131 84l84 131q-139 158 -139 422zM303 551q0 -178 53 -275l406 656q-66 35 -156 35q-162 0 -231 -103 q-72 -106 -72 -313zM467 164q59 -33 154 -33q162 0 233 105q70 102 70 315q0 166 -52 266zM498 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x218;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69zM483 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x219;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69zM454 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph unicode="&#x2bc;" d="M446 961q61 254 101 501h219l14 -22q-53 -207 -176 -479h-158z" />
+<glyph unicode="&#x2c6;" d="M283 1241v27l59 67q141 156 176 234h193q35 -78 176 -234l59 -67v-27h-121q-78 49 -211 186q-133 -137 -211 -186h-120z" />
+<glyph unicode="&#x2c7;" d="M283 1542v27h120q82 -55 211 -187q123 129 211 187h121v-27l-59 -67q-143 -160 -176 -234h-193q-33 74 -176 234z" />
+<glyph unicode="&#x2c9;" d="M326 1241v150h575v-150h-575z" />
+<glyph unicode="&#x2d8;" d="M313 1518h109q6 -76 47 -101q39 -25 143 -24q182 0 191 125h112q-10 -127 -90 -201q-82 -76 -215 -76q-279 1 -297 277z" />
+<glyph unicode="&#x2d9;" d="M508 1394.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x2da;" d="M387 1456q0 100 62 158q59 57 161 57q100 0 166 -59q63 -57 64 -154q0 -100 -64 -158q-66 -59 -166 -59q-102 0 -161 57q-62 58 -62 158zM498 1456q0 -113 112 -113q53 0 82 29q31 31 31 84q0 51 -30.5 82t-82.5 31q-49 0 -80 -31q-32 -33 -32 -82z" />
+<glyph unicode="&#x2db;" d="M414 -252q0 144 190 252h131q-170 -127 -170 -238q0 -96 127 -96q68 0 123 15v-113q-78 -23 -156 -23q-121 0 -182 54q-63 55 -63 149z" />
+<glyph unicode="&#x2dc;" d="M254 1241q25 264 211 264q57 0 162 -55q104 -57 135 -57q82 0 106 114h105q-27 -264 -211 -264q-57 0 -158 57q-100 55 -139 56q-82 0 -107 -115h-104z" />
+<glyph unicode="&#x2dd;" d="M246 1241v27q92 127 174 301h198v-21q-109 -168 -272 -307h-100zM608 1241v27q92 125 174 301h199v-21q-109 -168 -272 -307h-101z" />
+<glyph unicode="&#x2f3;" d="M387 -340q0 47 16 90q16 41 46 68q31 29 69 43q37 14 92 14q49 0 90 -14q39 -14 72 -43t49 -66q18 -39 19 -90q0 -57 -17 -92q-18 -40 -49 -67.5t-74 -43.5q-41 -14 -90 -14q-55 0 -92 14q-39 14 -69 43q-29 27 -46 68q-16 43 -16 90zM498 -340q0 -51 28 -84 q27 -29 84 -29q53 0 82 29q31 31 31 84t-31 84q-29 29 -82 29q-51 0 -80 -29q-32 -33 -32 -84z" />
+<glyph unicode="&#x384;" d="M479 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x385;" d="M299 1394.5q0 102.5 96.5 102.5t96.5 -102q0 -49 -27 -76t-70 -27q-96 0 -96 102.5zM532 1389v26q53 147 91 301h206v-20q-92 -163 -215 -307h-82zM735 1394.5q0 102.5 96.5 102.5t96.5 -102.5t-96.5 -102.5t-96.5 102.5z" />
+<glyph unicode="&#x386;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM37 1137v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x387;" d="M487 723q0 139 127 139t127 -139t-127 -139t-127 139z" />
+<glyph unicode="&#x388;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM-115 1137v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x389;" d="M135 0v1462h187v-616h585v616h187v-1462h-187v682h-585v-682h-187zM-156 1137v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x38a;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM-92 1137v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x38c;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM-131 1137v27l31 106q29 106 39 195h199v-21 q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x38e;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM-238 1137v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x38f;" d="M74 0v164h266q-254 233 -254 661q0 313 139 486q141 174 391 174q248 0 390 -174q141 -176 141 -486q0 -428 -256 -661h268v-164h-469v147q260 229 260 674q0 500 -335.5 500t-335.5 -500q0 -442 262 -674v-147h-467zM-133 1137v27l31 106q29 106 39 195h199v-21 q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x390;" d="M428 324v774h182v-774q0 -195 193 -195q117 0 213 21v-138q-98 -33 -225 -32q-363 0 -363 344zM242 1394.5q0 102.5 96.5 102.5t96.5 -102q0 -49 -27 -76t-70 -27q-96 0 -96 102.5zM475 1389v26q53 147 91 301h206v-20q-92 -163 -215 -307h-82zM678 1394.5 q0 102.5 96.5 102.5t96.5 -102.5t-96.5 -102.5t-96.5 102.5z" />
+<glyph unicode="&#x391;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183z" />
+<glyph unicode="&#x392;" d="M135 0v1462h440q272 0 398 -88q123 -86 123 -282q0 -129 -78 -213t-213 -103v-10q332 -55 332 -342q0 -199 -127 -311.5t-348 -112.5h-527zM322 158h307q311 0 311 274q0 254 -324 254h-294v-528zM322 842h284q157 0 228 55q72 55 71 182q0 121 -75.5 172.5t-243.5 51.5 h-264v-461z" />
+<glyph unicode="&#x393;" d="M233 0v1462h826v-166h-639v-1296h-187z" />
+<glyph unicode="&#x394;" d="M68 0v133l450 1329h187l454 -1337v-125h-1091zM268 166h686l-252 752q-51 150 -92 339q-53 -231 -88 -333z" />
+<glyph unicode="&#x395;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842z" />
+<glyph unicode="&#x396;" d="M102 0v145l793 1151h-772v166h981v-145l-793 -1151h813v-166h-1022z" />
+<glyph unicode="&#x397;" d="M135 0v1462h187v-616h585v616h187v-1462h-187v682h-585v-682h-187z" />
+<glyph unicode="&#x398;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM410 664v161h411v-161h-411z" />
+<glyph unicode="&#x399;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776z" />
+<glyph unicode="&#x39a;" d="M211 0v1462h186v-731l121 168l453 563h209l-521 -637l539 -825h-211l-450 698l-140 -114v-584h-186z" />
+<glyph unicode="&#x39b;" d="M33 0l487 1462h187l489 -1462h-199l-292 922q-55 172 -93 340q-47 -207 -88 -334l-295 -928h-196z" />
+<glyph unicode="&#x39c;" d="M113 0v1462h247l248 -1192h6l250 1192h252v-1462h-153v887q0 121 14 391h-8l-283 -1278h-154l-278 1280h-8q18 -268 18 -406v-874h-151z" />
+<glyph unicode="&#x39d;" d="M135 0v1462h213l578 -1204h6q-14 285 -14 404v800h174v-1462h-215l-580 1210h-8q18 -276 18 -417v-793h-172z" />
+<glyph unicode="&#x39e;" d="M111 0v164h1005v-164h-1005zM152 1298v164h923v-164h-923zM233 684v162h760v-162h-760z" />
+<glyph unicode="&#x39f;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588z" />
+<glyph unicode="&#x3a0;" d="M135 0v1462h959v-1462h-187v1298h-585v-1298h-187z" />
+<glyph unicode="&#x3a1;" d="M176 0v1462h404q514 0 514 -428q0 -219 -137.5 -342t-403.5 -123h-191v-569h-186zM362 727h170q195 0 283 72q86 70 86 225q0 279 -338 279h-201v-576z" />
+<glyph unicode="&#x3a3;" d="M131 0v152l414 614l-402 549v147h893v-164h-680l389 -530l-409 -604h760v-164h-965z" />
+<glyph unicode="&#x3a4;" d="M102 1298v164h1022v-164h-417v-1298h-187v1298h-418z" />
+<glyph unicode="&#x3a5;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559z" />
+<glyph unicode="&#x3a6;" d="M27 758q0 238 122.5 391.5t335.5 153.5h47v180h166v-180h47q213 0 336 -154t123 -391q0 -233 -127 -396q-125 -158 -354 -157h-25v-225h-166v225h-24q-230 0 -356 160q-125 157 -125 393zM199 762q0 -184 86 -293q86 -106 241 -107h6v781h-32q-141 0 -221 -104.5 t-80 -276.5zM698 362h7q156 0 241 107q86 109 86 293q0 172 -80 276.5t-221 104.5h-33v-781z" />
+<glyph unicode="&#x3a7;" d="M53 0l453 764l-422 698h199l331 -559l334 559h191l-422 -692l457 -770h-211l-355 635l-366 -635h-189z" />
+<glyph unicode="&#x3a8;" d="M57 979v483h172v-479q0 -229 70 -305q68 -74 217 -74h16v858h166v-858h17q150 0 217 72q70 74 69 303v483h173v-479q0 -289 -115 -412q-117 -125 -344 -125h-17v-446h-166v446h-16q-231 0 -344 125q-115 127 -115 408z" />
+<glyph unicode="&#x3a9;" d="M74 0v164h266q-254 233 -254 661q0 313 139 486q141 174 391 174q248 0 390 -174q141 -176 141 -486q0 -428 -256 -661h268v-164h-469v147q260 229 260 674q0 500 -335.5 500t-335.5 -500q0 -442 262 -674v-147h-467z" />
+<glyph unicode="&#x3aa;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x3ab;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x3ac;" d="M121 547q0 270 115 422q113 150 321 149q211 0 305 -168h12q29 100 68 148h143q-51 -162 -51 -439v-419q0 -111 84 -111q25 0 60 10v-133q-57 -27 -115 -26q-158 0 -199 167h-12q-109 -168 -313 -167q-193 0 -305.5 149.5t-112.5 417.5zM309 545q0 -414 264 -414 q147 0 211 92q66 92 68 309v15q0 227 -67.5 323.5t-213.5 96.5q-262 0 -262 -422zM495 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3ad;" d="M201 299q0 195 237 268v11q-203 66 -202 249q0 135 112.5 213t300.5 78q219 0 383 -76l-63 -147q-162 72 -316 72q-244 0 -243 -154q0 -166 276 -166h154v-153h-160q-301 0 -301 -185q0 -180 283 -180q199 0 366 86v-160q-139 -76 -377 -75q-211 0 -332 83 q-118 82 -118 236zM575 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3ae;" d="M160 0v1098h147l27 -148h10q100 168 336 168q389 0 389 -401v-1209h-182v1199q0 260 -238 260q-307 0 -307 -398v-569h-182zM559 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3af;" d="M428 324v774h182v-774q0 -195 193 -195q117 0 213 21v-138q-98 -33 -225 -32q-363 0 -363 344zM471 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3b0;" d="M160 498v600h182v-590q0 -379 274 -379q150 0 217.5 116.5t67.5 362.5q0 242 -63 490h182q63 -242 63 -498q0 -317 -114.5 -468.5t-358.5 -151.5q-450 0 -450 518zM297 1394.5q0 102.5 96.5 102.5t96.5 -102q0 -49 -27 -76t-70 -27q-96 0 -96 102.5zM530 1389v26 q53 147 91 301h206v-20q-92 -163 -215 -307h-82zM733 1394.5q0 102.5 96.5 102.5t96.5 -102.5t-96.5 -102.5t-96.5 102.5z" />
+<glyph unicode="&#x3b1;" d="M121 547q0 270 115 422q113 150 321 149q211 0 305 -168h12q29 100 68 148h143q-51 -162 -51 -439v-419q0 -111 84 -111q25 0 60 10v-133q-57 -27 -115 -26q-158 0 -199 167h-12q-109 -168 -313 -167q-193 0 -305.5 149.5t-112.5 417.5zM309 545q0 -414 264 -414 q147 0 211 92q66 92 68 309v15q0 227 -67.5 323.5t-213.5 96.5q-262 0 -262 -422z" />
+<glyph unicode="&#x3b2;" d="M158 -492v1588q0 227 118 348q121 123 328 123q199 0 316 -105q119 -106 118 -288q0 -135 -80 -228q-76 -88 -235 -117v-6q381 -49 381 -409q0 -206 -123 -320q-125 -115 -338 -114q-188 0 -303 63v-535h-182zM340 209q135 -80 289 -80q293 0 293 299q0 147 -94.5 229 t-254.5 82h-94v152h70q141 0 223 76q80 74 80 200q0 119 -68 185q-70 66 -180 65q-264 0 -264 -330v-878z" />
+<glyph unicode="&#x3b3;" d="M82 1098h192l242 -592q70 -174 107 -320h6q18 82 98 295l229 617h189l-406 -1035q-111 -281 -110 -555h-191q0 209 101 504z" />
+<glyph unicode="&#x3b4;" d="M135 438q0 371 422 500q-254 143 -254 348q0 135 90 207q92 74 252 74q199 0 393 -109l-73 -145q-168 106 -328 106q-74 0 -117 -36.5t-43 -100.5q0 -66 41 -115q39 -49 215 -151q360 -205 361 -518q0 -246 -129 -381q-131 -137 -355 -137q-209 0 -344 124 q-131 123 -131 334zM328 434q0 -137 75 -219q78 -84 207 -84q295 0 295 350q0 244 -221 373q-356 -101 -356 -420z" />
+<glyph unicode="&#x3b5;" d="M201 299q0 195 237 268v11q-203 66 -202 249q0 135 112.5 213t300.5 78q219 0 383 -76l-63 -147q-162 72 -316 72q-244 0 -243 -154q0 -166 276 -166h154v-153h-160q-301 0 -301 -185q0 -180 283 -180q199 0 366 86v-160q-139 -76 -377 -75q-211 0 -332 83 q-118 82 -118 236z" />
+<glyph unicode="&#x3b6;" d="M162 469q0 254 162 477q160 223 536 469q-215 -12 -352 -12h-285v153h838v-141q-396 -289 -553 -485q-158 -199 -158 -453q0 -154 82 -217q83 -65 313 -104q168 -31 246 -80q76 -49 76 -162q0 -147 -121 -315h-170q121 164 121 260q0 57 -51 90q-52 34 -246 61 q-227 33 -334 146q-104 110 -104 313z" />
+<glyph unicode="&#x3b7;" d="M160 0v1098h147l27 -148h10q100 168 336 168q389 0 389 -401v-1209h-182v1199q0 260 -238 260q-307 0 -307 -398v-569h-182z" />
+<glyph unicode="&#x3b8;" d="M147 729q0 381 113 563.5t352 182.5q230 0 351 -191q119 -188 118 -555q0 -750 -469 -749q-229 0 -348 192q-117 190 -117 557zM332 670q6 -276 71.5 -407.5t209 -131.5t208.5 127q68 129 74 412h-563zM332 807h563q-6 258 -73.5 387t-209.5 129q-139 0 -206 -125 q-64 -121 -74 -391z" />
+<glyph unicode="&#x3b9;" d="M428 324v774h182v-774q0 -195 193 -195q117 0 213 21v-138q-98 -33 -225 -32q-363 0 -363 344z" />
+<glyph unicode="&#x3ba;" d="M215 0v1098h180v-291l-16 -299h4l137 166l402 424h213l-494 -510l522 -588h-213l-426 469l-129 -82v-387h-180z" />
+<glyph unicode="&#x3bb;" d="M61 0l504 1083l-53 160q-33 100 -78 139q-43 37 -115 37q-55 0 -104 -12v145q57 16 127 17q141 0 213 -67.5t141 -278.5l326 -983q37 -111 102 -111q25 0 60 10v-133q-53 -27 -115 -26q-80 0 -125 40q-43 41 -72 127l-135 418q-74 238 -94 336h-6q-37 -141 -119 -321 l-268 -580h-189z" />
+<glyph unicode="&#x3bc;" d="M160 -492v1590h182v-707q0 -260 238 -260q160 0 233.5 92t73.5 305v570h182v-1098h-147l-27 147h-10q-100 -168 -301 -167q-174 0 -248 88q6 -154 6 -240v-320h-182z" />
+<glyph unicode="&#x3bd;" d="M61 1098h189l223 -586q106 -276 121 -358h6q156 162 235.5 368.5t79.5 575.5h183q0 -367 -100.5 -610.5t-325.5 -487.5h-187z" />
+<glyph unicode="&#x3be;" d="M172 422q0 137 76 240q78 104 207 147v12q-215 59 -215 279q0 113 75 188q74 74 260 127q-174 -12 -280 -12h-62v153h764v-153h-69q-217 0 -364.5 -80t-147.5 -219q0 -114 92 -166q90 -51 287 -51h190v-137h-201q-209 0 -315 -82q-109 -84 -109 -230q0 -90 37 -143 q39 -55 109 -82q76 -31 248 -59q158 -27 237 -78q76 -49 76 -162q0 -147 -121 -315h-170q121 164 121 262q0 52 -49 86q-49 33 -238 61q-438 68 -438 414z" />
+<glyph unicode="&#x3bf;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416z" />
+<glyph unicode="&#x3c0;" d="M14 944v74l138 80h1062v-154h-210v-690q0 -125 90 -125q49 0 90 21v-144q-57 -27 -137 -26q-225 0 -226 262v702h-403v-944h-182v944h-222z" />
+<glyph unicode="&#x3c1;" d="M158 -492v1043q0 264 127 415.5t344 151.5q207 0 329 -153q125 -156 125 -414q0 -268 -122.5 -419.5t-339.5 -151.5q-166 0 -281 90h-6q6 -176 6 -271v-291h-182zM340 231q109 -100 283 -100q144 0 208 105q63 102 64 315q0 207 -66 313q-63 102 -208 103 q-281 0 -281 -396v-340z" />
+<glyph unicode="&#x3c2;" d="M172 516q0 602 567 602q162 0 322 -59l-62 -158q-154 57 -272 57q-367 0 -367 -440q0 -186 78 -254q78 -70 269 -102q358 -63 358 -252q0 -143 -125 -311h-166q121 164 121 262q0 59 -66 90q-59 29 -229 57q-428 72 -428 508z" />
+<glyph unicode="&#x3c3;" d="M129 524q0 573 555 574h490v-154h-267q178 -195 178 -440q0 -233 -129 -378.5t-352 -145.5t-348 143q-127 145 -127 401zM317 524q0 -186 76 -288q78 -104 219 -105q137 0 211 96.5t74 268.5q0 270 -154 448h-59q-200 0 -283 -98q-84 -101 -84 -322z" />
+<glyph unicode="&#x3c4;" d="M106 944v74l134 80h841v-154h-475v-606q0 -215 209 -215q111 0 191 20v-135q-86 -35 -220 -35q-362 0 -362 344v627h-318z" />
+<glyph unicode="&#x3c5;" d="M160 498v600h182v-590q0 -379 274 -379q150 0 217.5 116.5t67.5 362.5q0 242 -63 490h182q63 -242 63 -498q0 -317 -114.5 -468.5t-358.5 -151.5q-450 0 -450 518z" />
+<glyph unicode="&#x3c6;" d="M74 547q0 311 207 559l120 -90q-98 -129 -131 -232q-35 -109 -34 -237q0 -383 288 -416v606q0 381 281 381q166 0 258 -147.5t92 -399.5q0 -264 -125 -419.5t-348 -169.5v-474h-158v474q-450 24 -450 565zM682 131q305 29 305 438q0 397 -176 398q-129 0 -129 -228v-608z " />
+<glyph unicode="&#x3c7;" d="M43 -492l475 830l-180 446q-68 168 -152 168q-27 0 -63 -10v143q47 16 129 17q80 0 135 -55.5t111 -192.5l139 -348l311 592h178l-417 -776l186 -461q47 -115 86 -158q41 -45 104 -45q47 0 80 8v-139q-63 -18 -118 -19q-104 0 -170 46q-68 47 -138 221l-147 377 l-354 -644h-195z" />
+<glyph unicode="&#x3c8;" d="M80 555v543h172v-529q0 -424 272 -438v1423h158v-1421q301 28 301 436q0 254 -63 529h172q63 -272 63 -523q0 -569 -473 -593v-474h-158v474q-233 10 -338 143q-106 137 -106 430z" />
+<glyph unicode="&#x3c9;" d="M90 532q0 301 105 566h165q-104 -261 -104 -566q0 -401 139 -401q68 0 105 72q37 71 37 196v306h157v-306q0 -133 39 -198q41 -70 103 -70q139 0 139 401q0 303 -105 566h166q104 -258 105 -566q0 -553 -289 -552q-182 0 -231 178h-11q-49 -178 -231 -178 q-289 -1 -289 552z" />
+<glyph unicode="&#x3ca;" d="M428 324v774h182v-774q0 -195 193 -195q117 0 213 21v-138q-98 -33 -225 -32q-363 0 -363 344zM258 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM633 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x3cb;" d="M160 498v600h182v-590q0 -379 274 -379q150 0 217.5 116.5t67.5 362.5q0 242 -63 490h182q63 -242 63 -498q0 -317 -114.5 -468.5t-358.5 -151.5q-450 0 -450 518zM330 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1394.5q0 102.5 96 102.5t96 -102.5 t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x3cc;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416zM551 1241v27l31 106q29 106 39 195h199v-21 q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3cd;" d="M160 498v600h182v-590q0 -379 274 -379q150 0 217.5 116.5t67.5 362.5q0 242 -63 490h182q63 -242 63 -498q0 -317 -114.5 -468.5t-358.5 -151.5q-450 0 -450 518zM518 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3ce;" d="M90 532q0 301 105 566h165q-104 -261 -104 -566q0 -401 139 -401q68 0 105 72q37 71 37 196v306h157v-306q0 -133 39 -198q41 -70 103 -70q139 0 139 401q0 303 -105 566h166q104 -258 105 -566q0 -553 -289 -552q-182 0 -231 178h-11q-49 -178 -231 -178 q-289 -1 -289 552zM530 1241v27l31 106q29 106 39 195h199v-21q0 -16 -50 -121q-47 -102 -110 -186h-109z" />
+<glyph unicode="&#x3d1;" d="M10 825q29 14 86.5 28.5t104.5 14.5q53 0 84 -14q39 -18 57 -39q20 -25 31 -59q10 -37 10 -74q0 -49 -4 -78q-2 -25 -6 -48.5t-6 -41.5q-2 -16 -5.5 -47t-5.5 -47q-4 -33 -4 -94q0 -37 10 -78q8 -37 35 -66q23 -25 64 -41q43 -16 96 -16q163 0 246 154q82 152 82 456v53 q0 23 -4 52q-178 4 -295 39q-125 39 -197 98q-76 63 -108.5 137t-32.5 158q0 61 20 123q18 59 60 98q43 43 104 63q68 23 152 23q104 0 184 -43q82 -45 139 -119q59 -78 97 -190q37 -111 55 -250h143v-137h-137q2 -14 2 -52q0 -8 1 -28.5t1 -30.5q0 -150 -33 -297 q-29 -133 -96 -237q-63 -98 -162 -158q-96 -57 -229 -57q-109 0 -184 28q-70 27 -115 74q-41 45 -62 111q-16 55 -16 131q0 55 4 86q2 10 4 29.5t4 34.5t4 28l11 82q4 25 4 61q0 47 -15 62q-16 16 -47 16q-14 0 -51 -8q-25 -6 -43 -17zM426 1272q0 -53 23 -109 q23 -53 76 -94t139 -65q94 -27 210 -27q-10 90 -43 192q-29 90 -65 144q-41 59 -84 88q-47 31 -94 31q-76 0 -119 -43t-43 -117z" />
+<glyph unicode="&#x3d2;" d="M31 1462h202l379 -731q29 86 62 160q18 41 78 164q39 80 75 147l32.5 63.5t27.5 49.5q16 31 45 71q22 31 49 50q29 20 59 28q35 10 74 11q27 0 55 -5q20 -2 39 -12v-145q-8 2 -28 6q-10 2 -29 2q-31 0 -59 -23q-35 -29 -66 -84q-6 -8 -9 -15t-10.5 -19.5t-15.5 -28.5 l-21.5 -37t-31.5 -59l-61 -119q-39 -72 -66 -133q-41 -90 -59 -135q-35 -82 -47 -127v-541h-187v559z" />
+<glyph unicode="&#x3d6;" d="M18 944v74l134 80h1052v-154h-155q12 -33 41 -123q18 -61 30 -112q8 -39 17 -113q4 -39 4 -125q0 -121 -14.5 -205t-51.5 -153q-33 -63 -90 -98t-133 -35q-94 0 -150 43q-57 45 -81 135h-11q-25 -90 -82 -135q-55 -43 -149 -43q-76 0 -133.5 34.5t-89.5 98.5 q-34 65 -50 153q-16 94 -16 205q0 86 4 125q8 74 17 113q16 74 28 112q18 58 43 123h-164zM256 471q0 -98 8 -156q10 -74 25 -104q20 -43 44.5 -61.5t61.5 -18.5t64 21q23 18 43 57q18 35 26 84q8 43 9 106v203h157v-203q0 -133 39 -198q41 -70 103 -70q37 0 61.5 18.5 t44.5 61.5q14 31 25 104q8 57 8 156q0 80 -4 119q-8 74 -17 112q-12 59 -30 115l-41 127h-535q-23 -61 -43 -127q-10 -35 -29 -115q-8 -39 -16 -112q-4 -39 -4 -119z" />
+<glyph unicode="&#x401;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842zM355 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM730 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x402;" d="M23 1298v164h841v-164h-356v-401h264q184 0 291 -96q102 -94 102 -275v-137q0 -197 -94 -303t-266 -106q-89 0 -141 24v160q63 -20 135 -21q180 0 180 226v133q0 231 -227 231h-244v-733h-186v1298h-299z" />
+<glyph unicode="&#x403;" d="M233 0v1462h826v-166h-639v-1296h-187zM508 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x404;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-188 0 -314 -125q-123 -125 -151 -348h629v-162h-635q23 -541 471 -541q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557z" />
+<glyph unicode="&#x405;" d="M141 49v178q211 -86 414 -86q350 0 350 240q0 104 -71 160q-74 57 -285 133q-211 74 -299 174q-90 102 -90 264q0 174 129 272.5t352 98.5q225 0 416 -78l-64 -164q-197 78 -360 78q-293 0 -293 -209q0 -102 66 -164q66 -63 270 -133q244 -88 327.5 -182t83.5 -240 q0 -190 -139 -301q-138 -111 -393 -110q-258 -1 -414 69z" />
+<glyph unicode="&#x406;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776z" />
+<glyph unicode="&#x407;" d="M225 0v123l295 20v1176l-295 20v123h776v-123l-294 -20v-1176l294 -20v-123h-776zM332 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM707 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x408;" d="M137 39v166q162 -61 309 -62q162 0 254.5 80t92.5 226v1013h186v-1011q0 -215 -141 -345q-139 -127 -377 -126q-215 0 -324 59z" />
+<glyph unicode="&#x409;" d="M0 -2v145q29 -14 68 -14q33 0 61 35q27 33 39 127q10 80 33 524q23 434 24 647h498v-616h39q446 0 446 -418q0 -207 -114.5 -317.5t-329.5 -110.5h-207v1298h-182l-21 -548q-23 -580 -82 -672q-63 -98 -176 -98q-55 0 -96 18zM723 160h45q268 0 268 268q0 131 -69 195 q-66 59 -224 59h-20v-522z" />
+<glyph unicode="&#x40a;" d="M66 0v1462h165v-616h318v616h166v-616h39q221 0 333.5 -106.5t112.5 -311.5q0 -207 -114.5 -317.5t-329.5 -110.5h-207v682h-318v-682h-165zM715 160h45q268 0 268 268q0 131 -70 195q-66 59 -223 59h-20v-522z" />
+<glyph unicode="&#x40b;" d="M23 1298v164h841v-164h-356v-401h264q184 0 291 -96q102 -94 102 -275v-526h-186v502q0 231 -227 231h-244v-733h-186v1298h-299z" />
+<glyph unicode="&#x40c;" d="M211 0v1462h186v-708l566 708h206l-565 -702l594 -760h-219l-582 741v-741h-186zM574 1579v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x40e;" d="M27 1462h204l383 -809q2 -4 21 -47l7 -21.5t9 -23.5h2l39 109l312 792h196l-428 -1030q-80 -190 -135 -268q-61 -86 -150 -135t-215 -49q-104 0 -178 30v185q84 -45 178 -45q111 0 170 51q59 49 115 174zM237 1897h170q10 -104 50 -144q43 -43 161 -43q193 0 211 187h174 q-20 -317 -389 -318q-195 0 -281 74t-96 244z" />
+<glyph unicode="&#x40f;" d="M135 0v1462h187v-1296h585v1296h187v-1462h-394v-385h-176v385h-389z" />
+<glyph unicode="&#x410;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183z" />
+<glyph unicode="&#x411;" d="M135 0v1462h912v-164h-725v-452h272q541 0 541 -418q0 -207 -131.5 -317.5t-382.5 -110.5h-486zM322 160h282q338 0 338 268q0 131 -86 192.5t-283 61.5h-251v-522z" />
+<glyph unicode="&#x412;" d="M135 0v1462h440q272 0 398 -88q123 -86 123 -282q0 -129 -78 -213t-213 -103v-10q332 -55 332 -342q0 -199 -127 -311.5t-348 -112.5h-527zM322 158h307q311 0 311 274q0 254 -324 254h-294v-528zM322 842h284q157 0 228 55q72 55 71 182q0 121 -75.5 172.5t-243.5 51.5 h-264v-461z" />
+<glyph unicode="&#x413;" d="M233 0v1462h826v-166h-639v-1296h-187z" />
+<glyph unicode="&#x414;" d="M6 166h113q133 246 217 594q86 360 98 702h592v-1296h195v-551h-177v385h-862v-385h-176v551zM311 166h529v1130h-242q-18 -281 -98 -596q-85 -339 -189 -534z" />
+<glyph unicode="&#x415;" d="M217 0v1462h842v-164h-656v-452h617v-162h-617v-520h656v-164h-842z" />
+<glyph unicode="&#x416;" d="M0 0l373 754l-361 708h178l349 -708v708h155v-708l342 708h178l-356 -708l371 -754h-185l-350 741v-741h-155v741l-357 -741h-182z" />
+<glyph unicode="&#x417;" d="M139 59v170q186 -96 383 -96q354 0 355 283q0 264 -394 264h-190v151h176q178 0 281 74q100 74 100 199q0 102 -70 164q-72 61 -188 61q-184 0 -354 -121l-93 125q193 150 455 150q209 0 326 -99q119 -100 118 -264q0 -135 -90 -229t-252 -121v-6q176 -20 273 -115 q96 -92 96 -233q0 -203 -141.5 -319.5t-403.5 -116.5q-243 -1 -387 79z" />
+<glyph unicode="&#x418;" d="M137 0v1462h174v-800q0 -106 -8 -254l-6 -150h6l578 1204h213v-1462h-172v793q0 141 18 417h-8l-580 -1210h-215z" />
+<glyph unicode="&#x419;" d="M137 0v1462h174v-800q0 -106 -8 -254l-6 -150h6l578 1204h213v-1462h-172v793q0 141 18 417h-8l-580 -1210h-215zM231 1897h170q10 -104 50 -144q43 -43 161 -43q193 0 211 187h174q-20 -317 -389 -318q-195 0 -281 74t-96 244z" />
+<glyph unicode="&#x41a;" d="M211 0v1462h186v-708l566 708h206l-565 -702l594 -760h-219l-582 741v-741h-186z" />
+<glyph unicode="&#x41b;" d="M4 2v150q57 -25 113 -25q102 0 157 180q53 176 181 1155h639v-1462h-187v1298h-297q-117 -979 -204 -1148q-89 -172 -265 -173q-71 0 -137 25z" />
+<glyph unicode="&#x41c;" d="M113 0v1462h247l248 -1192h6l250 1192h252v-1462h-153v887q0 121 14 391h-8l-283 -1278h-154l-278 1280h-8q18 -268 18 -406v-874h-151z" />
+<glyph unicode="&#x41d;" d="M135 0v1462h187v-616h585v616h187v-1462h-187v682h-585v-682h-187z" />
+<glyph unicode="&#x41e;" d="M84 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM281 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588z" />
+<glyph unicode="&#x41f;" d="M135 0v1462h959v-1462h-187v1298h-585v-1298h-187z" />
+<glyph unicode="&#x420;" d="M176 0v1462h404q514 0 514 -428q0 -219 -137.5 -342t-403.5 -123h-191v-569h-186zM362 727h170q195 0 283 72q86 70 86 225q0 279 -338 279h-201v-576z" />
+<glyph unicode="&#x421;" d="M129 733q0 344 178 547t490 203q219 0 383 -86l-78 -156q-156 78 -305 78q-215 0 -342 -158q-129 -160 -129 -430q0 -287 120 -438q119 -150 351 -150q135 0 327 58v-162q-150 -59 -358 -59q-310 0 -473 196q-164 199 -164 557z" />
+<glyph unicode="&#x422;" d="M102 1298v164h1022v-164h-417v-1298h-187v1298h-418z" />
+<glyph unicode="&#x423;" d="M27 1462h204l383 -809q2 -4 21 -47l7 -21.5t9 -23.5h2l39 109l312 792h196l-428 -1030q-80 -190 -135 -268q-61 -86 -150 -135t-215 -49q-104 0 -178 30v185q84 -45 178 -45q111 0 170 51q59 49 115 174z" />
+<glyph unicode="&#x424;" d="M27 758q0 238 122.5 391.5t335.5 153.5h47v180h166v-180h47q213 0 336 -154t123 -391q0 -233 -127 -396q-125 -158 -354 -157h-25v-225h-166v225h-24q-230 0 -356 160q-125 157 -125 393zM199 762q0 -184 86 -293q86 -106 241 -107h6v781h-32q-141 0 -221 -104.5 t-80 -276.5zM698 362h7q156 0 241 107q86 109 86 293q0 172 -80 276.5t-221 104.5h-33v-781z" />
+<glyph unicode="&#x425;" d="M53 0l453 764l-422 698h199l331 -559l334 559h191l-422 -692l457 -770h-211l-355 635l-366 -635h-189z" />
+<glyph unicode="&#x426;" d="M135 0v1462h187v-1296h526v1296h186v-1296h176v-551h-176v385h-899z" />
+<glyph unicode="&#x427;" d="M135 879v583h187v-559q0 -131 51 -180q55 -51 162 -51q154 0 372 80v710h187v-1462h-187v598q-229 -90 -393 -90q-379 0 -379 371z" />
+<glyph unicode="&#x428;" d="M121 0v1462h166v-1296h245v1296h166v-1296h246v1296h166v-1462h-989z" />
+<glyph unicode="&#x429;" d="M61 0v1462h166v-1296h246v1296h166v-1296h246v1296h166v-1296h178v-551h-176v385h-992z" />
+<glyph unicode="&#x42a;" d="M27 1298v164h485v-616h68q270 0 415.5 -108.5t145.5 -309.5q0 -203 -137.5 -315.5t-397.5 -112.5h-280v1298h-299zM512 160h98q338 0 338 268q0 131 -86 192.5t-282 61.5h-68v-522z" />
+<glyph unicode="&#x42b;" d="M96 0v1462h166v-616h47q541 0 541 -418q0 -207 -131 -317q-133 -111 -383 -111h-240zM262 160h78q338 0 338 268q0 131 -86 192.5t-283 61.5h-47v-522zM967 0v1462h166v-1462h-166z" />
+<glyph unicode="&#x42c;" d="M176 0v1462h186v-616h191q541 0 541 -418q0 -207 -131.5 -317.5t-382.5 -110.5h-404zM362 160h201q338 0 338 268q0 131 -86 192.5t-283 61.5h-170v-522z" />
+<glyph unicode="&#x42d;" d="M68 1397q160 86 383 86q305 0 477 -194.5t172 -530.5q0 -375 -170 -576q-172 -203 -488 -202q-209 0 -358 59v162q193 -57 328 -58q473 0 489 541h-629v162h625q-18 223 -137 348t-309 125q-150 0 -306 -78z" />
+<glyph unicode="&#x42e;" d="M98 0v1462h166v-616h144q18 346 106 493q86 145 270 146q190 0 283 -176q92 -174 92 -576q0 -397 -92 -575t-285 -178q-190 0 -280 157q-88 156 -99 545h-139v-682h-166zM580 733q0 -346 47 -469q47 -121 155 -121t154 117q47 119 47 473q0 365 -47 473q-49 115 -154 115 q-111 0 -155 -119q-47 -123 -47 -469z" />
+<glyph unicode="&#x42f;" d="M57 0l381 655q-272 98 -272 408q0 399 504 399h372v-1462h-186v604h-246l-334 -604h-219zM358 1047q0 -137 82 -211q84 -74 236 -74h180v541h-188q-310 0 -310 -256z" />
+<glyph unicode="&#x430;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164z" />
+<glyph unicode="&#x431;" d="M143 659q0 212 31 357q31 143 82 231q49 84 123 142q72 55 170 81q90 25 491 101l33 -160q-408 -70 -500 -100q-102 -35 -165 -140q-61 -104 -72 -319h12q117 170 336 170q186 0 292.5 -131t106.5 -361q0 -262 -125 -405q-127 -145 -346 -145t-344 180t-125 499zM332 655 q0 -524 293 -524q266 0 266 375q0 365 -240 364q-96 0 -184 -63q-90 -66 -135 -152z" />
+<glyph unicode="&#x432;" d="M176 0v1098h510q387 0 387 -277q0 -197 -229 -239v-7q264 -34 264 -258q0 -152 -107 -233q-109 -84 -313 -84h-512zM358 150h318q254 0 254 180q0 92 -66 129q-61 35 -192 35h-314v-344zM358 647h293q135 0 191 35q57 37 57 121q0 141 -217 141h-324v-297z" />
+<glyph unicode="&#x433;" d="M291 0v1098h747v-154h-565v-944h-182z" />
+<glyph unicode="&#x434;" d="M33 154h86q264 393 266 944h592v-944h151v-535h-174v381h-747v-381h-174v535zM311 154h484v804h-250q-37 -481 -234 -804z" />
+<glyph unicode="&#x435;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305z" />
+<glyph unicode="&#x436;" d="M0 1098h184l351 -533v533h159v-533l350 533h185l-367 -533l365 -565h-195l-338 557v-557h-159v557l-338 -557h-195l367 565z" />
+<glyph unicode="&#x437;" d="M201 1042q158 76 370 76q205 0 315.5 -73.5t110.5 -215.5q0 -184 -192 -243v-11q227 -63 227 -272q0 -152 -121 -237q-120 -86 -344 -86q-233 0 -362 69v166q180 -86 366 -86q283 0 283 180q0 184 -311 185h-150v153h113q172 0 244 39q74 39 73 127q0 154 -250 154 q-131 0 -309 -72z" />
+<glyph unicode="&#x438;" d="M160 0v1098h172v-668l-13 -252l517 920h233v-1098h-172v647l10 271l-514 -918h-233z" />
+<glyph unicode="&#x439;" d="M160 0v1098h172v-668l-13 -252l517 920h233v-1098h-172v647l10 271l-514 -918h-233zM268 1559h170q10 -104 50 -144q43 -43 161 -43q193 0 211 187h174q-20 -317 -389 -318q-195 0 -281 74t-96 244z" />
+<glyph unicode="&#x43a;" d="M215 0v1098h180v-533l518 533h222l-527 -527l566 -571h-232l-547 557v-557h-180z" />
+<glyph unicode="&#x43b;" d="M31 -2v131q22 -6 49 -6q111 0 178 237q68 237 104 738h678v-1098h-182v944h-340q-37 -487 -127 -725q-88 -233 -268 -233q-61 0 -92 12z" />
+<glyph unicode="&#x43c;" d="M115 0v1098h211l215 -656q23 -72 73 -268q2 4 54 191q10 47 20 73l219 660h207v-1098h-151v897q-8 -23 -33 -127q-18 -74 -35 -123l-213 -647h-135l-213 647q-2 6 -10.5 35t-24.5 91.5l-33 123.5v-897h-151z" />
+<glyph unicode="&#x43d;" d="M160 0v1098h182v-455h545v455h182v-1098h-182v489h-545v-489h-182z" />
+<glyph unicode="&#x43e;" d="M115 551q0 264 135 415.5t366 151.5q217 0 356.5 -155.5t139.5 -411.5q0 -266 -137 -418q-139 -154 -365 -153q-219 0 -356 155q-139 158 -139 416zM303 551q0 -420 311 -420q309 0 310 420q0 416 -312 416q-309 0 -309 -416z" />
+<glyph unicode="&#x43f;" d="M160 0v1098h909v-1098h-182v944h-545v-944h-182z" />
+<glyph unicode="&#x440;" d="M158 -492v1590h147l27 -148h8q111 168 322 168q203 0 315 -149q115 -152 115 -418q0 -268 -115 -419.5t-315 -151.5q-207 0 -322 159h-12q12 -129 12 -162v-469h-182zM340 551q0 -229 70 -324q72 -96 221 -96q272 0 272 422q0 414 -274 414q-152 0 -219.5 -88t-69.5 -287 v-41z" />
+<glyph unicode="&#x441;" d="M172 543q0 279 145 428q145 147 408 147q176 0 336 -59l-62 -158q-147 57 -268 57q-371 0 -371 -413q0 -406 361 -406q160 0 321 62v-160q-135 -61 -329 -61q-258 0 -400 145q-141 145 -141 418z" />
+<glyph unicode="&#x442;" d="M121 944v154h985v-154h-401v-944h-183v944h-401z" />
+<glyph unicode="&#x443;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150z" />
+<glyph unicode="&#x444;" d="M74 551q0 524 463 563v442h157v-442q459 -49 459 -563q0 -524 -459 -567v-476h-157v476q-463 45 -463 567zM242 551q0 -385 295 -416v828q-295 -28 -295 -412zM694 135q291 33 291 416q0 377 -291 410v-826z" />
+<glyph unicode="&#x445;" d="M96 0l414 563l-393 535h207l290 -410l291 410h207l-395 -535l413 -563h-206l-310 436l-311 -436h-207z" />
+<glyph unicode="&#x446;" d="M152 0v1098h182v-944h504v944h182v-944h160v-535h-183v381h-845z" />
+<glyph unicode="&#x447;" d="M152 676v422h182v-410q0 -174 205 -174q170 0 340 115v469h182v-1098h-182v489q-182 -127 -381 -127q-160 0 -252 87q-94 88 -94 227z" />
+<glyph unicode="&#x448;" d="M125 0v1098h162v-944h248v944h161v-944h248v944h162v-1098h-981z" />
+<glyph unicode="&#x449;" d="M109 0v1098h161v-944h248v944h162v-944h248v944h162v-944h118v-535h-161v381h-938z" />
+<glyph unicode="&#x44a;" d="M43 944v154h543v-451h153q416 0 416 -311q0 -336 -420 -336h-332v944h-360zM586 150h137q254 0 254 172q0 90 -59.5 131t-198.5 41h-133v-344z" />
+<glyph unicode="&#x44b;" d="M113 0v1098h161v-451h134q416 0 415 -311q0 -336 -420 -336h-290zM274 150h138q254 0 254 172q0 90 -59.5 131t-198.5 41h-134v-344zM952 0v1098h162v-1098h-162z" />
+<glyph unicode="&#x44c;" d="M217 0v1098h182v-451h277q416 0 416 -311q0 -336 -420 -336h-455zM399 150h260q254 0 254 172q0 90 -59 131t-199 41h-256v-344z" />
+<glyph unicode="&#x44d;" d="M184 1059q156 59 332 59q268 0 406 -145q139 -150 139 -430q0 -270 -143 -416q-143 -147 -408 -147q-187 0 -320 61v160q162 -61 316 -62q350 0 368 348h-538v154h536q-29 317 -364 317q-111 0 -262 -57z" />
+<glyph unicode="&#x44e;" d="M123 0v1098h162v-455h151q33 475 367 475q172 0 266 -147q96 -150 96 -420q0 -571 -368 -571q-335 0 -363 509h-149v-489h-162zM602 551q0 -219 47 -319.5t151.5 -100.5t149.5 98q47 100 47 322q0 217 -47 317q-45 98 -151 99q-102 0 -150 -97q-47 -98 -47 -319z" />
+<glyph unicode="&#x44f;" d="M115 0l291 461q-233 68 -234 315q0 150 102.5 236t274.5 86h485v-1098h-182v432h-285l-254 -432h-198zM346 772q0 -186 238 -186h268v358h-295q-211 0 -211 -172z" />
+<glyph unicode="&#x451;" d="M133 541q0 266 135 421.5t363 155.5q212 0 338 -135q127 -137 127 -356v-113h-774q9 -375 344 -375q199 0 370 76v-160q-170 -76 -364 -75q-244 0 -391 149q-148 151 -148 412zM326 662h573q0 305 -272 305q-276 0 -301 -305zM348 1394.5q0 102.5 96 102.5t96 -102.5 t-96 -102.5t-96 102.5zM723 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x452;" d="M4 1237v137h156v182h182v-182h379v-137h-379v-184l-8 -144h10q106 168 334 168q391 0 391 -401v-834q0 -334 -291 -334q-82 0 -133 25v148q53 -20 115 -21q127 0 127 170v836q0 260 -236 260q-160 0 -235 -95q-74 -92 -74 -303v-528h-182v1237h-156z" />
+<glyph unicode="&#x453;" d="M291 0v1098h747v-154h-565v-944h-182zM522 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x454;" d="M172 543q0 281 145 430q143 145 414 145q176 0 330 -59l-62 -158q-147 57 -262 57q-346 0 -377 -317h537v-154h-539q23 -348 369 -348q154 0 315 62v-160q-132 -61 -319 -61q-264 0 -408 147q-143 146 -143 416z" />
+<glyph unicode="&#x455;" d="M203 49v166q195 -86 370 -86q274 0 275 162q0 55 -49 98t-226 107q-233 86 -294 159q-59 72 -60 172q0 135 111 213q113 78 309.5 78t368.5 -74l-60 -149q-184 72 -319 72q-236 0 -236 -133q0 -57 51.5 -96.5t231.5 -102.5q207 -76 280 -152q70 -72 70 -182 q0 -150 -116.5 -235.5t-331.5 -85.5q-246 -1 -375 69z" />
+<glyph unicode="&#x456;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM526 1435.5q0 114.5 106.5 114.5t106.5 -114q0 -57 -32.5 -86t-73.5 -29q-107 0 -107 114.5z" />
+<glyph unicode="&#x457;" d="M197 0v123l344 20v811l-269 21v123h451v-955l352 -20v-123h-878zM330 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x458;" d="M135 -303q131 -39 289 -39q119 0 182 57q66 59 66 158v1081l-420 21v123h602v-1215q0 -180 -113 -278q-111 -96 -319 -97q-160 0 -287 35v154zM637 1435.5q0 114.5 106.5 114.5t106.5 -114.5t-106.5 -114.5t-106.5 114.5z" />
+<glyph unicode="&#x459;" d="M0 -2v131q22 -6 49 -6q41 0 66 43q27 45 47 231q27 233 57 701h494v-451h51q416 0 416 -311q0 -336 -420 -336h-209v944h-186q-33 -463 -60 -663q-25 -188 -72 -241.5t-141 -53.5q-61 0 -92 12zM713 150h55q254 0 254 172q0 90 -59.5 131t-198.5 41h-51v-344z" />
+<glyph unicode="&#x45a;" d="M106 0v1098h162v-455h299v455h162v-451h51q416 0 416 -311q0 -336 -420 -336h-209v489h-299v-489h-162zM729 150h55q254 0 254 172q0 90 -59 131t-199 41h-51v-344z" />
+<glyph unicode="&#x45b;" d="M4 1237v137h156v182h184v-182h418v-137h-420v-184l-10 -144h10q106 168 346 168q190 0 287 -96q94 -94 94 -305v-676h-182v666q0 260 -236 260q-160 0 -235 -95q-74 -92 -74 -303v-528h-182v1237h-156z" />
+<glyph unicode="&#x45c;" d="M215 0v1098h180v-291l-16 -299h4l137 166l402 424h213l-494 -510l522 -588h-213l-426 469l-129 -82v-387h-180zM508 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x45e;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150zM241 1559h170q10 -104 50 -144q43 -43 161 -43q193 0 211 187h174 q-20 -317 -389 -318q-195 0 -281 74t-96 244z" />
+<glyph unicode="&#x45f;" d="M160 0v1098h182v-944h545v944h182v-1098h-354v-381h-183v381h-372z" />
+<glyph unicode="&#x490;" d="M233 0v1462h637v301h177v-467h-627v-1296h-187z" />
+<glyph unicode="&#x491;" d="M291 0v1098h545v319h182v-456h-545v-961h-182z" />
+<glyph unicode="&#x1e00;" d="M33 0l483 1468h195l485 -1468h-192l-144 453h-491l-146 -453h-190zM422 618h385l-133 424q-39 121 -62 226q-20 -88 -47 -183zM389 -340q0 47 16 90q16 41 46 68q31 29 69 43q37 14 92 14q49 0 90 -14q39 -14 72 -43t49 -66q18 -39 19 -90q0 -57 -17 -92 q-18 -40 -49 -67.5t-74 -43.5q-41 -14 -90 -14q-55 0 -92 14q-39 14 -69 43q-29 27 -46 68q-16 43 -16 90zM500 -340q0 -51 28 -84q27 -29 84 -29q53 0 82 29q31 31 31 84t-31 84q-29 29 -82 29q-51 0 -80 -29q-32 -33 -32 -84z" />
+<glyph unicode="&#x1e01;" d="M135 307q0 332 510 348l203 7v69q0 236 -244 236q-150 0 -328 -82l-63 137q199 96 383 96q223 0 328 -88q102 -86 102 -278v-752h-131l-37 152h-8q-74 -94 -158 -133t-209 -39q-164 0 -256 85.5t-92 241.5zM324 305q0 -178 200 -178q150 0 234 82q88 84 88 229v99 l-162 -7q-195 -8 -278 -61q-82 -51 -82 -164zM383 -340q0 47 16 90q16 41 46 68q31 29 69 43q37 14 92 14q49 0 90 -14q39 -14 72 -43t49 -66q18 -39 19 -90q0 -57 -17 -92q-18 -40 -49 -67.5t-74 -43.5q-41 -14 -90 -14q-55 0 -92 14q-39 14 -69 43q-29 27 -46 68 q-16 43 -16 90zM494 -340q0 -51 28 -84q27 -29 84 -29q53 0 82 29q31 31 31 84t-31 84q-29 29 -82 29q-51 0 -80 -29q-32 -33 -32 -84z" />
+<glyph unicode="&#x1e3e;" d="M113 0v1462h247l248 -1192h6l250 1192h252v-1462h-153v887q0 121 14 391h-8l-283 -1278h-154l-278 1280h-8q18 -268 18 -406v-874h-151zM518 1581v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1e3f;" d="M92 0v1098h127l27 -148h10q68 168 201 168q164 0 213 -182h6q78 182 219 182q129 0 186 -92q57 -90 58 -309v-717h-162v707q0 147 -27 202q-27 57 -88 58q-88 0 -127 -82q-39 -80 -39 -279v-606h-161v707q0 260 -125 260q-82 0 -119 -80t-37 -318v-569h-162zM545 1241v27 q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1e80;" d="M2 1462h170l88 -663q18 -145 39 -377q18 -203 18 -242q27 162 70 312l141 516h177l145 -521q57 -205 72 -307q6 92 65 619l70 663h170l-187 -1462h-190l-168 580q-43 147 -66 282q-31 -168 -65 -284l-156 -578h-190zM336 1886v21h219q88 -182 174 -301v-27h-121 q-163 139 -272 307z" />
+<glyph unicode="&#x1e81;" d="M-4 1098h162l98 -543q39 -215 57 -393h6q33 195 68 358l133 578h193l127 -578q43 -188 67 -358h6q29 225 60 393l102 543h158l-225 -1098h-195l-131 596l-68 330h-6l-65 -334l-135 -592h-189zM303 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#x1e82;" d="M2 1462h170l88 -663q18 -145 39 -377q18 -203 18 -242q27 162 70 312l141 516h177l145 -521q57 -205 72 -307q6 92 65 619l70 663h170l-187 -1462h-190l-168 580q-43 147 -66 282q-31 -168 -65 -284l-156 -578h-190zM500 1579v27q92 127 174 301h219v-21 q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1e83;" d="M-4 1098h162l98 -543q39 -215 57 -393h6q33 195 68 358l133 578h193l127 -578q43 -188 67 -358h6q29 225 60 393l102 543h158l-225 -1098h-195l-131 596l-68 330h-6l-65 -334l-135 -592h-189zM522 1241v27q92 127 174 301h219v-21q-109 -168 -272 -307h-121z" />
+<glyph unicode="&#x1e84;" d="M2 1462h170l88 -663q18 -145 39 -377q18 -203 18 -242q27 162 70 312l141 516h177l145 -521q57 -205 72 -307q6 92 65 619l70 663h170l-187 -1462h-190l-168 580q-43 147 -66 282q-31 -168 -65 -284l-156 -578h-190zM334 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5 t-96 102.5zM709 1732.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x1e85;" d="M-4 1098h162l98 -543q39 -215 57 -393h6q33 195 68 358l133 578h193l127 -578q43 -188 67 -358h6q29 225 60 393l102 543h158l-225 -1098h-195l-131 596l-68 330h-6l-65 -334l-135 -592h-189zM330 1394.5q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5zM705 1394.5 q0 102.5 96 102.5t96 -102.5t-96 -102.5t-96 102.5z" />
+<glyph unicode="&#x1ef2;" d="M33 1462h203l376 -739l381 739h201l-487 -893v-569h-187v559zM303 1886v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#x1ef3;" d="M82 1098h188l262 -654q82 -203 89 -290h6q20 106 90 292l239 652h189l-475 -1241q-70 -178 -156 -263q-89 -86 -246 -86q-94 0 -168 17v145q61 -12 136 -12q96 0 149 41t96 141l58 150zM314 1548v21h219q88 -182 174 -301v-27h-121q-163 139 -272 307z" />
+<glyph unicode="&#x1f4d;" d="M229 735q0 750 534 750q258 0 392 -195q137 -199 137 -557q0 -362 -137 -557q-138 -197 -394 -196q-532 -1 -532 755zM426 733q0 -590 335 -590q174 0 254 145.5t80 444.5q0 305 -82 445q-84 143 -250 143q-337 0 -337 -588zM-311 1255q0 78 59 136q61 57 183 88v-76 q-55 -18 -88 -45q-29 -23 -29 -47q0 -18 16 -29l33 -16q18 -10 33 -21q16 -12 16 -41q0 -39 -24.5 -57.5t-71.5 -18.5q-57 0 -92 35t-35 92zM-2 1135v26l23 68l24 76l25 81q4 16 10 44t8 32h207v-20l-43 -70l-51 -80q-6 -10 -59 -80q-31 -41 -62 -77h-82z" />
+<glyph unicode="&#x2000;" />
+<glyph unicode="&#x2001;" />
+<glyph unicode="&#x2002;" />
+<glyph unicode="&#x2003;" />
+<glyph unicode="&#x2004;" />
+<glyph unicode="&#x2005;" />
+<glyph unicode="&#x2006;" />
+<glyph unicode="&#x2007;" />
+<glyph unicode="&#x2008;" />
+<glyph unicode="&#x2009;" />
+<glyph unicode="&#x200a;" />
+<glyph unicode="&#x200b;" />
+<glyph unicode="&#x2010;" d="M285 465v168h659v-168h-659z" />
+<glyph unicode="&#x2011;" d="M285 465v168h659v-168h-659z" />
+<glyph unicode="&#x2012;" d="M285 465v168h659v-168h-659z" />
+<glyph unicode="&#x2013;" d="M184 465v168h860v-168h-860z" />
+<glyph unicode="&#x2014;" d="M-6 465v168h1241v-168h-1241z" />
+<glyph unicode="&#x2015;" d="M-6 465v168h1241v-168h-1241z" />
+<glyph unicode="&#x2017;" d="M-20 -45h1269v-139h-1269v139zM-20 -324h1269v-139h-1269v139z" />
+<glyph unicode="&#x2018;" d="M446 983q57 217 177 479h157q-66 -276 -100 -501h-219z" />
+<glyph unicode="&#x2019;" d="M446 961q61 254 101 501h219l14 -22q-53 -207 -176 -479h-158z" />
+<glyph unicode="&#x201a;" d="M457 -264q76 309 100 502h199l14 -23q-53 -207 -176 -479h-137z" />
+<glyph unicode="&#x201b;" d="M446 1440l15 22h219q41 -270 100 -501h-157q-126 278 -177 479z" />
+<glyph unicode="&#x201c;" d="M233 983q57 217 177 479h157q-66 -276 -100 -501h-219zM659 983q57 217 177 479h157q-66 -276 -100 -501h-219z" />
+<glyph unicode="&#x201d;" d="M233 961q61 254 101 501h219l14 -22q-53 -207 -176 -479h-158zM659 961q61 254 101 501h219l14 -22q-53 -207 -176 -479h-158z" />
+<glyph unicode="&#x201e;" d="M244 -264q76 309 100 502h199l14 -23q-53 -207 -176 -479h-137zM670 -264q76 309 100 502h199l14 -23q-55 -209 -176 -479h-137z" />
+<glyph unicode="&#x2020;" d="M240 989v180l311 -30l-55 417h217l-56 -417l332 30v-180l-332 31l56 -1020h-217l55 1020z" />
+<glyph unicode="&#x2021;" d="M229 346v180l332 -30l-47 290l47 275l-332 -31v180l332 -30l-55 376h217l-55 -376l331 30v-180l-331 31l47 -275l-47 -290l331 30v-180l-331 31l55 -377h-217l55 377z" />
+<glyph unicode="&#x2022;" d="M379 748q0 262 235.5 262t235.5 -262q0 -129 -64 -195q-65 -68 -172 -68q-113 0 -174 68t-61 195z" />
+<glyph unicode="&#x2026;" d="M78 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM487 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM897 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5z" />
+<glyph unicode="&#x202f;" horiz-adv-x="430" />
+<glyph unicode="&#x2030;" d="M4 655l698 289l41 -100l-698 -287zM20 1171q0 309 244 310q113 0 176 -80q63 -78 64 -230q0 -311 -244 -311q-113 0 -176.5 82t-63.5 229zM156 1171q0 -102 22.5 -153t84 -51t83.5 51q20 47 21 153q0 119 -23 158q-25 43 -82 43q-55 0 -82 -45q-24 -43 -24 -156zM195 311 q0 309 243 310q111 0 176 -80q63 -78 64 -230q0 -311 -244 -311q-115 0 -176 82q-63 86 -63 229zM330 311q0 -104 22 -155q20 -49 84 -49.5t84 49.5q20 47 21 155q0 119 -23 158q-25 43 -82 43q-55 0 -82 -45q-24 -43 -24 -156zM725 311q0 309 244 310q113 0 176 -80 q63 -78 63 -230q0 -311 -243 -311q-115 0 -177 82q-63 86 -63 229zM860 311q0 -104 23 -155q23 -49 84 -49.5t84 49.5q20 47 20 155q0 113 -22 158q-20 43 -82 43q-59 0 -84 -43q-23 -39 -23 -158z" />
+<glyph unicode="&#x2032;" d="M496 1462h237l-41 -528h-155z" />
+<glyph unicode="&#x2033;" d="M285 1462h237l-41 -528h-155zM707 1462h237l-41 -528h-155z" />
+<glyph unicode="&#x2039;" d="M401 526v27l310 414l116 -78l-237 -348l237 -348l-116 -78z" />
+<glyph unicode="&#x203a;" d="M401 193l238 348l-238 348l117 78l309 -414v-27l-309 -411z" />
+<glyph unicode="&#x203c;" d="M718 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM735 1462h223l-51 -1048h-121zM256 110.5q0 139.5 127 139.5t127 -139.5t-127 -139.5t-127 139.5zM273 1462h223l-51 -1048h-121z" />
+<glyph unicode="&#x2044;" d="M170 0l729 1462h158l-729 -1462h-158z" />
+<glyph unicode="&#x205f;" horiz-adv-x="538" />
+<glyph unicode="&#x207f;" d="M317 797v665h125l17 -104h8q68 121 207 121q109 0 174 -66q63 -63 63 -184v-432h-147v413q0 150 -127 150q-98 0 -135 -53q-37 -52 -37 -172v-338h-148z" />
+<glyph unicode="&#x20a3;" d="M129 262v137h176v1063h752v-164h-574v-516h535v-164h-535v-219h293v-137h-293v-262h-178v262h-176z" />
+<glyph unicode="&#x20a4;" d="M119 0v154q201 49 200 284v21h-198v137h198v158h-198v137h198v221q0 166 109 268q106 100 289 101q193 0 346 -80l-66 -144q-143 72 -272 72q-223 0 -223 -246v-192h377v-137h-377v-158h377v-137h-377v-19q0 -199 -140 -274h748v-166h-991z" />
+<glyph unicode="&#x20a7;" d="M82 0v1462h205q451 0 450 -428q0 -219 -114 -344q-113 -121 -342 -121h-41v-569h-158zM240 715h41q293 0 292 309q0 291 -268 291h-65v-600zM688 618v70l115 51l65 215h86v-211h209v-125h-209v-348q0 -154 113 -153q63 0 123 20v-125q-70 -33 -166 -32q-221 0 -221 282 v356h-115z" />
+<glyph unicode="&#x20ac;" d="M96 502v137h148l-2 39l2 119h-148v137h160q41 262 180 405q141 143 359 144q193 0 335 -92l-79 -146q-123 74 -242 74q-133 0 -234 -100q-96 -96 -133 -285h432v-137h-446q0 -6 -1 -14.5t-1 -14.5v-25v-61q0 -29 2 -43h385v-137h-367q74 -358 369 -359q139 0 268 58v-162 q-125 -59 -282 -59q-444 0 -541 522h-164z" />
+<glyph unicode="&#x2105;" d="M8 1126q0 168 90 258q88 88 252 89q100 0 182 -37l-32 -107q-80 33 -150 33q-199 0 -198 -234q0 -229 194 -229q104 0 176 33v-107q-74 -37 -182 -37q-156 0 -244 86t-88 252zM156 0l729 1462h157l-729 -1462h-157zM616 334q0 164 82 252q84 90 224 90q129 0 217 -94 q84 -90 84 -248q0 -160 -82 -250q-84 -92 -223 -92q-131 0 -218 92q-84 90 -84 250zM762 334q0 -233 158 -234q156 0 155 234q0 231 -155 231q-158 0 -158 -231z" />
+<glyph unicode="&#x2113;" d="M227 510v121q66 16 193 59v494q0 137 69 219q68 80 201 80q109 0 172.5 -82t63.5 -219q0 -354 -340 -541v-301q0 -221 145 -221q143 0 154 213h114q-18 -352 -286 -352q-138 0 -215 92q-78 94 -78 264v231q-105 -37 -193 -57zM586 770q207 121 207 406q0 188 -103 188 q-53 0 -78 -41q-27 -43 -26 -147v-406z" />
+<glyph unicode="&#x2116;" d="M25 0v1462h176l323 -1163h6q-14 285 -14 403v760h133v-1462h-174l-325 1169h-9q18 -252 19 -417v-752h-135zM705 623q0 346 253 346q115 0 182.5 -92.5t67.5 -253.5q0 -168 -65.5 -258.5t-188.5 -90.5q-115 0 -182 92.5t-67 256.5zM745 0v147h414v-147h-414zM844 623 q0 -111 24 -170q25 -57 88 -58q61 0 86 58q25 59 25 170q0 113 -24.5 168t-86.5 55q-63 0 -87.5 -55t-24.5 -168z" />
+<glyph unicode="&#x2122;" d="M0 1354v108h481v-108h-178v-613h-127v613h-176zM526 741v721h187l139 -534l149 534h179v-721h-127v342q0 74 10 207h-12l-154 -549h-100l-146 549h-12l10 -180v-369h-123z" />
+<glyph unicode="&#x2126;" d="M74 0v164h266q-254 233 -254 661q0 313 139 486q141 174 391 174q248 0 390 -174q141 -176 141 -486q0 -428 -256 -661h268v-164h-469v147q260 229 260 674q0 500 -335.5 500t-335.5 -500q0 -442 262 -674v-147h-467z" />
+<glyph unicode="&#x212e;" d="M82 530q0 260 154 414q152 152 376 152q229 0 381 -156q150 -152 150 -405v-5h-828v-356q123 -123 297 -123q254 0 396 234l71 -41q-98 -158 -207 -217q-111 -61 -260 -62q-242 0 -385 162q-145 163 -145 403zM315 616h596v277q-119 119 -301 119q-172 0 -295 -117v-279z " />
+<glyph unicode="&#x215b;" d="M19 1309l219 151h135v-788h-146v465q0 84 9 200q-43 -45 -74 -65l-70 -51zM115 0l729 1462h158l-729 -1462h-158zM647 211q0 131 139 204q-115 80 -114 193q0 90 71 145q70 55 184.5 55.5t182.5 -53.5q70 -55 70 -147q0 -117 -140 -184q166 -86 166 -207 q0 -104 -75.5 -166t-200.5 -62q-133 0 -209 60q-74 60 -74 162zM793 211q0 -117 131 -117q135 0 135 117q0 89 -135 147l-13 6q-118 -65 -118 -153zM819 606q0 -80 109 -133q106 49 106 133q0 96 -108 96q-107 0 -107 -96z" />
+<glyph unicode="&#x215c;" d="M10 705v124q113 -66 203 -65q150 0 149 137q0 125 -147 125h-72v104h70q123 0 123 127q0 111 -97 111q-74 0 -161 -70l-66 86q111 92 238 93q113 0 174 -54q63 -55 63 -149q0 -139 -149 -189q176 -41 176 -186q0 -117 -74 -180q-72 -63 -215 -64q-132 1 -215 50zM154 0 l729 1462h158l-729 -1462h-158zM667 211q0 131 139 204q-115 80 -114 193q0 90 71 145q70 55 184.5 55.5t182.5 -53.5q70 -55 70 -147q0 -117 -140 -184q166 -86 166 -207q0 -104 -75.5 -166t-200.5 -62q-133 0 -209 60q-74 60 -74 162zM813 211q0 -117 131 -117 q135 0 135 117q0 89 -135 147l-13 6q-118 -65 -118 -153zM839 606q0 -80 109 -133q106 49 106 133q0 96 -108 96q-107 0 -107 -96z" />
+<glyph unicode="&#x215d;" d="M25 705v129q102 -68 207 -68q162 0 162 147q0 145 -166 146q-59 0 -125 -17l-62 39l31 381h397v-110h-288l-17 -193q33 6 96 6q115 0 191 -65q74 -63 74 -174q0 -127 -74 -199q-72 -70 -221 -70q-129 1 -205 48zM154 0l729 1462h158l-729 -1462h-158zM667 211 q0 131 139 204q-115 80 -114 193q0 90 71 145q70 55 184.5 55.5t182.5 -53.5q70 -55 70 -147q0 -117 -140 -184q166 -86 166 -207q0 -104 -75.5 -166t-200.5 -62q-133 0 -209 60q-74 60 -74 162zM813 211q0 -117 131 -117q135 0 135 117q0 89 -135 147l-13 6 q-118 -65 -118 -153zM839 606q0 -80 109 -133q106 49 106 133q0 96 -108 96q-107 0 -107 -96z" />
+<glyph unicode="&#x215e;" d="M27 1341v121h548v-100l-309 -690h-155l309 669h-393zM88 0l729 1462h158l-729 -1462h-158zM667 211q0 131 139 204q-115 80 -114 193q0 90 71 145q70 55 184.5 55.5t182.5 -53.5q70 -55 70 -147q0 -117 -140 -184q166 -86 166 -207q0 -104 -75.5 -166t-200.5 -62 q-133 0 -209 60q-74 60 -74 162zM813 211q0 -117 131 -117q135 0 135 117q0 89 -135 147l-13 6q-118 -65 -118 -153zM839 606q0 -80 109 -133q106 49 106 133q0 96 -108 96q-107 0 -107 -96z" />
+<glyph unicode="&#x2202;" d="M121 375q0 250 137 442.5t383 192.5q184 0 283 -148l2 39q10 184 -58 303q-68 121 -219 121q-131 0 -258 -84v174q135 61 283 62q432 0 432 -543q0 -391 -168 -672q-169 -283 -455 -282q-362 0 -362 395zM309 369q0 -236 187 -236q137 0 247.5 153.5t147.5 393.5 q-20 84 -86 137t-139 53q-160 0 -258.5 -159.5t-98.5 -341.5z" />
+<glyph unicode="&#x2206;" d="M74 0v113l446 1349h187l448 -1351v-111h-1081zM274 164h678l-247 758q-57 176 -93 340q-47 -207 -88 -334z" />
+<glyph unicode="&#x220f;" d="M156 -492v1954h956v-1954h-186v1788h-584v-1788h-186z" />
+<glyph unicode="&#x2211;" d="M74 -377l583 914l-567 811v114h1014v-164h-754l529 -759l-555 -867h845v-164h-1095v115z" />
+<glyph unicode="&#x2212;" d="M152 647v150h923v-150h-923z" />
+<glyph unicode="&#x221a;" d="M23 764v143h296l230 -663l512 1452h145l-594 -1710h-133l-276 778h-180z" />
+<glyph unicode="&#x221e;" d="M70 723q0 133 75 225q74 90 193 90q166 0 274 -219q117 213 281 213q117 0 190.5 -86t73.5 -229q0 -133 -76 -223q-78 -92 -188 -93q-172 0 -283 220q-117 -213 -272 -213q-117 0 -192.5 88t-75.5 227zM205 721q0 -80 41 -131t106 -51q102 0 189 184q-83 184 -191 184 q-63 0 -104 -53t-41 -133zM684 717q86 -184 193 -185q66 0 104 54q41 57 41 133q0 82 -41 131q-43 51 -107 51q-104 0 -190 -184z" />
+<glyph unicode="&#x222b;" d="M236 -326q61 -25 116 -24q180 0 180 233v1319q0 354 330 354q88 0 131 -18v-147q-59 27 -114 26q-172 0 -172 -233v-1321q0 -176 -89 -264q-90 -90 -249 -91q-78 0 -133 19v147z" />
+<glyph unicode="&#x2248;" d="M152 379v162q98 109 247 108q102 0 248 -63q129 -55 201 -56q106 0 227 121v-162q-98 -109 -248 -108q-102 0 -247 63q-133 55 -201 56q-106 0 -227 -121zM152 788v162q98 109 247 109q100 0 248 -64q127 -55 201 -55q111 0 227 121v-162q-98 -109 -248 -108 q-102 0 -247 63q-129 55 -201 55q-112 0 -227 -121z" />
+<glyph unicode="&#x2260;" d="M152 442v150h317l121 260h-438v149h507l134 283l137 -59l-105 -224h250v-149h-319l-123 -260h442v-150h-512l-129 -278l-137 57l102 221h-247z" />
+<glyph unicode="&#x2264;" d="M152 0v150h923v-150h-923zM152 672v102l923 451v-160l-715 -342l715 -342v-160z" />
+<glyph unicode="&#x2265;" d="M152 0v150h923v-150h-923zM152 221v160l714 342l-714 342v160l923 -451v-102z" />
+<glyph unicode="&#x25ca;" d="M125 735l450 740h76l453 -738l-453 -737h-76zM309 737l305 -514l306 514l-306 512z" />
+<glyph unicode="&#xe000;" horiz-adv-x="1100" d="M0 1100h1100v-1100h-1100v1100z" />
+<glyph unicode="&#xfb01;" d="M49 961v75l195 68v96q0 190 75.5 278.5t255.5 88.5q96 0 197 -37l-47 -141q-82 29 -143 28q-90 0 -123 -51q-33 -53 -33 -164v-104h246v-137h-246v-961h-182v961h-195zM854 1394.5q0 114.5 106.5 114.5t106.5 -114q0 -58 -31 -86q-33 -29 -75 -29q-107 0 -107 114.5z M868 0v1098h183v-1098h-183z" />
+<glyph unicode="&#xfb02;" d="M49 961v75l195 68v96q0 190 75.5 278.5t255.5 88.5q96 0 197 -37l-47 -141q-82 29 -143 28q-90 0 -123 -51q-33 -53 -33 -164v-104h246v-137h-246v-961h-182v961h-195zM868 0v1556h183v-1556h-183z" />
+<glyph unicode="&#xfb03;" d="M66 971v65l100 62v82q0 109 20 176q23 76 58 112q37 39 96 60q55 18 127 18q57 0 92 -10q47 -14 78 -25q43 33 88 43q53 12 115 13q59 0 98 -11q49 -14 82 -26l-41 -131q-18 8 -64 20q-31 8 -71 8q-37 0 -66 -12q-27 -12 -45 -37q-16 -23 -26 -69q-8 -39 -9 -107v-104 h367v-1098h-164v971h-203v-971h-163v971h-205v-971h-164v971h-100zM330 1098h205v102q0 115 24 193q-29 8 -43 10q-29 4 -45 4q-39 0 -61 -10q-27 -12 -45 -37q-14 -18 -25 -70q-10 -47 -10 -108v-84z" />
+<glyph unicode="&#xfb04;" d="M66 971v65l100 62v82q0 109 20 176q23 76 58 112q37 39 96 60q55 18 127 18q57 0 92 -10q47 -14 78 -25q43 33 88 43q53 12 115 13q55 0 94 -11h131v-1556h-164v1421q-20 4 -29 4q-4 0 -14 1t-14 1q-37 0 -66 -12q-27 -12 -45 -37q-16 -23 -26 -69q-8 -39 -9 -107v-104 h142v-127h-142v-971h-163v971h-205v-971h-164v971h-100zM330 1098h205v102q0 115 24 193q-29 8 -43 10q-29 4 -45 4q-39 0 -61 -10q-27 -12 -45 -37q-14 -18 -25 -70q-10 -47 -10 -108v-84z" />
+<glyph unicode="&#xfeff;" />
+<glyph unicode="&#xfffc;" d="M55 39v270h111v-270h-111zM55 -80h111v-194h192v-109h-303v303zM55 430v272h111v-272h-111zM55 823v271h111v-271h-111zM55 1214v304h303v-111h-192v-193h-111zM254 1083.5q0 55.5 12 98.5q12 45 39 78q23 29 64 47t94 18t92 -18q45 -20 66 -47q27 -33 38 -78 q12 -43 12.5 -98.5t-12 -98.5t-38.5 -76q-25 -31 -66 -49q-39 -18 -92 -18t-94 18q-39 18 -64 49q-27 33 -39 76t-12 98.5zM354 1083.5q0 -75.5 27 -116.5t82 -41q59 0 82 41q27 47 26.5 116.5t-26.5 116.5q-23 41 -82 41q-55 0 -82 -41t-27 -116.5zM479 -274h271v-109h-271 v109zM479 1407v111h271v-111h-271zM535 326v469h137q92 0 133 -27q43 -28 43 -92q0 -40 -19 -68q-18 -27 -53 -33v-4q12 -2 33 -10q10 -4 27 -20q12 -12 18 -31q8 -25 8 -47q0 -63 -43 -100t-119 -37h-165zM633 408h59q37 0 53 18q14 16 15 47q0 27 -15 41q-16 16 -57 16 h-55v-122zM633 610h51q37 0 51.5 12.5t14.5 39t-16.5 39t-53.5 12.5h-47v-103zM709 -111q4 -2 15 -3t17 -1q12 -2 43 -2t47 15q20 16 21 55v244h-94v77h266v-77h-72v-242q0 -80 -45 -119q-43 -37 -112 -37q-37 0 -52 2q-25 4 -34 6v82zM870 -274h195v194h109v-303h-304v109z M870 1407v111h304v-304h-109v193h-195zM1065 39v270h109v-270h-109zM1065 430v272h109v-272h-109zM1065 823v271h109v-271h-109z" />
+<glyph unicode="&#xfffd;" d="M4 618l610 938l613 -938l-613 -937zM342 1014l66 -160q51 29 106 51q49 20 96 21q53 0 78 -27t25 -68q0 -25 -6.5 -47t-16.5 -36q-12 -18 -31 -37q-10 -10 -47 -43q-31 -29 -53 -54q-23 -27 -35 -53q-16 -39 -20 -55q-6 -31 -6 -66v-55h170v43q0 16 4 41q2 16 12 33 q6 10 29 33q27 27 45 40l61 62q25 23 45 59q18 29 27 66q8 33 8 82q0 125 -76 192q-78 68 -211 68q-35 0 -71 -6q-29 -4 -72 -21q-12 -4 -66 -28q-28 -12 -61 -35zM477 139.5q0 -67.5 33 -94.5q35 -29 82 -29q18 0 41 7q20 6 37 22q18 18 26 39q8 23 9 55q0 35 -9 58 q-8 20 -26 39q-14 14 -37 20t-41 6q-47 0 -82 -29q-33 -26 -33 -93.5z" />
+<glyph d="M231 1559h170q10 -104 50 -144q43 -43 161 -43q193 0 211 187h174q-20 -317 -389 -318q-195 0 -281 74t-96 244z" />
+<glyph d="M135 -303q131 -39 289 -39q119 0 182 57q66 59 66 158v1081l-420 21v123h602v-1215q0 -180 -113 -278q-111 -96 -319 -97q-160 0 -287 35v154z" />
+<glyph d="M494 1229v26l26 107q27 127 35 194h180v-20q0 -14 -43 -113q-49 -111 -102 -194h-96z" />
+<glyph d="M483 -426q63 145 84 301h178v-20q0 -22 -49 -123q-51 -109 -114 -185h-99v27z" />
+<glyph d="M483 1241v21q0 20 45 118q45 100 119 189h98v-27q-61 -145 -83 -301h-179z" />
+<glyph d="M313 1026q0 453 299 453q150 0 226 -117q78 -119 77 -336q0 -457 -303 -457q-141 0 -221 117q-78 115 -78 340zM461 1026q0 -326 151 -326q156 0 156 326q0 324 -156 324q-151 0 -151 -324z" />
+<glyph d="M293 854v98l377 523h141v-508h84v-113h-84v-174h-143v174h-375zM438 967h230v176q0 83 6 172q-37 -70 -80 -131z" />
+<glyph d="M336 705v129q102 -68 207 -68q162 0 162 147q0 145 -166 146q-59 0 -125 -17l-62 39l31 381h397v-110h-288l-17 -193q33 6 96 6q115 0 191 -65q74 -63 74 -174q0 -127 -74 -199q-72 -70 -221 -70q-129 1 -205 48z" />
+<glyph d="M313 913q0 408 484 580l45 -109q-329 -111 -381 -325h10q61 92 201 92q115 0 178 -76q66 -78 65 -205q0 -133 -83.5 -217t-215.5 -84q-137 0 -219 93q-84 93 -84 251zM455 889q0 -84 47 -141.5t121 -57.5q68 0 110 45q41 43 41 133q0 172 -147 172q-74 0 -123 -42.5 t-49 -108.5z" />
+<glyph d="M367 1341v121h548v-100l-309 -690h-155l309 669h-393z" />
+<glyph d="M305 877q0 131 139 204q-115 80 -114 193q0 90 71 145q70 55 184.5 55.5t182.5 -53.5q70 -55 70 -147q0 -117 -140 -184q166 -86 166 -207q0 -104 -75.5 -166t-200.5 -62q-133 0 -209 60q-74 60 -74 162zM451 877q0 -117 131 -117q135 0 135 117q0 89 -135 147l-13 6 q-118 -65 -118 -153zM477 1272q0 -80 109 -133q106 49 106 133q0 96 -108 96q-107 0 -107 -96z" />
+<glyph d="M313 1178q0 133 80 219q78 84 211 84q141 0 227 -103q84 -98 84 -288q0 -520 -413 -521q-66 0 -111 15v125q41 -23 101 -23q272 0 286 315h-8q-71 -98 -197 -98q-123 0 -190 74q-70 76 -70 201zM453 1180q0 -164 149 -164q72 0 121 43t49 100q0 78 -45 141 q-43 61 -121 62q-68 0 -110 -47q-43 -46 -43 -135z" />
+<glyph d="M158 547q0 268 112 422q111 150 305 149q203 0 314 -168h8l27 148h147v-1121q0 -225 -119 -346q-121 -123 -336 -123q-195 0 -352 76v170q186 -96 350 -96q274 0 275 309v10q0 41 12 170h-12q-109 -168 -314 -167q-193 0 -305 149.5t-112 417.5zM346 545q0 -414 264 -414 q147 0 211 88q66 90 68 287v41q0 227 -67.5 323.5t-213.5 96.5q-262 0 -262 -422z" />
+<glyph d="M-18 735q0 362 163 557q162 193 473 193q299 0 465 -199q166 -200 166 -553q0 -549 -379 -708l338 -373l-153 -109l-367 441q-41 -4 -72 -4q-309 0 -471 196q-163 199 -163 559zM178 733q0 -590 438 -590q436 0 437 590q0 588 -435 588q-440 0 -440 -588z" />
+<glyph d="M348 1163l383 299h150v-1462h-176v913q0 147 8 361q-43 -47 -121 -113l-148 -121z" />
+<glyph d="M346 946v193q236 111 369 323h166v-1462h-179v823l5 408q-119 -154 -361 -285z" />
+<glyph d="M371 1092v127l301 34l71 209h113v-1462h-176v909q0 111 8 183h-317z" />
+<glyph d="M301 1255q0 78 59 136q61 57 183 88v-76q-55 -18 -88 -45q-29 -23 -29 -47q0 -18 16 -29l33 -16q18 -10 33 -21q16 -12 16 -41q0 -39 -24.5 -57.5t-71.5 -18.5q-57 0 -92 35t-35 92zM610 1135v26l23 68l24 76l25 81q4 16 10 44t8 32h207v-20l-43 -70l-51 -80 q-6 -10 -59 -80q-31 -41 -62 -77h-82z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.ttf b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.ttf
new file mode 100644
index 00000000000..e125bc1f314
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.ttf
Binary files differ
diff --git a/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.woff b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.woff
new file mode 100644
index 00000000000..31d51be4a70
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.woff
Binary files differ
diff --git a/apps/files_texteditor/css/DroidSansMono/Google Android License.txt b/apps/files_texteditor/css/DroidSansMono/Google Android License.txt
new file mode 100644
index 00000000000..0a010886a1e
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/Google Android License.txt
@@ -0,0 +1,18 @@
+Copyright (C) 2008 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+##########
+
+This directory contains the fonts for the platform. They are licensed
+under the Apache 2 license.
diff --git a/apps/files_texteditor/css/DroidSansMono/demo.html b/apps/files_texteditor/css/DroidSansMono/demo.html
new file mode 100644
index 00000000000..e305598817d
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/demo.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+ <title>Font Face Demo</title>
+ <link rel="stylesheet" href="stylesheet.css" type="text/css" charset="utf-8">
+ <style type="text/css" media="screen">
+ h1.fontface {font: 60px/68px 'DroidSansMonoRegular', Arial, sans-serif;letter-spacing: 0;}
+
+ p.style1 {font: 18px/27px 'DroidSansMonoRegular', Arial, sans-serif;}
+
+ #container {
+ width: 800px;
+ margin-left: auto;
+ margin-right: auto;
+ }
+ </style>
+</head>
+
+<body>
+ <div id="container">
+ <h1 class="fontface">Font-face Demo for the Droid Sans Mono Font</h1>
+
+
+
+ <p class="style1">Droid Sans Mono Regular - 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.</p>
+
+ </div>
+</body>
+</html>
diff --git a/apps/files_texteditor/css/DroidSansMono/stylesheet.css b/apps/files_texteditor/css/DroidSansMono/stylesheet.css
new file mode 100644
index 00000000000..5bf9122ed7d
--- /dev/null
+++ b/apps/files_texteditor/css/DroidSansMono/stylesheet.css
@@ -0,0 +1,15 @@
+/* Generated by Font Squirrel (http://www.fontsquirrel.com) on June 13, 2012 02:50:54 PM America/New_York */
+
+
+
+@font-face {
+ font-family: 'Droid Sans Mono';
+ src: url('%appswebroot%/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.eot');
+ src: url('%appswebroot%/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.eot?#iefix') format('embedded-opentype'),
+ url('%appswebroot%/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.woff') format('woff'),
+ url('%appswebroot%/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.ttf') format('truetype'),
+ url('%appswebroot%/apps/files_texteditor/css/DroidSansMono/DroidSansMono-webfont.svg#DroidSansMonoRegular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+
+}
diff --git a/apps/files_texteditor/js/aceeditor/ace.js b/apps/files_texteditor/js/aceeditor/ace.js
index 6043589ac1f..679230926e9 100644
--- a/apps/files_texteditor/js/aceeditor/ace.js
+++ b/apps/files_texteditor/js/aceeditor/ace.js
@@ -1,4 +1,4 @@
-(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(){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",[],".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)
@@ -7,4 +7,3 @@
ace[key] = a[key];
});
})();
- \ No newline at end of file
diff --git a/apps/gallery/appinfo/app.php b/apps/gallery/appinfo/app.php
index e1db33eb314..e3a8dbd588b 100644
--- a/apps/gallery/appinfo/app.php
+++ b/apps/gallery/appinfo/app.php
@@ -26,6 +26,8 @@ OC::$CLASSPATH['OC_Gallery_Photo'] = 'apps/gallery/lib/photo.php';
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';
+OC::$CLASSPATH['Pictures_Managers'] = 'apps/gallery/lib/managers.php';
+OC::$CLASSPATH['Pictures_Tiles'] = 'apps/gallery/lib/tiles.php';
$l = OC_L10N::get('gallery');
@@ -48,6 +50,6 @@ class OC_GallerySearchProvider extends OC_Search_Provider{
}
}
-OC_Search::registerProvider('OC_GallerySearchProvider');
+//OC_Search::registerProvider('OC_GallerySearchProvider');
require_once('apps/gallery/lib/hooks_handlers.php');
diff --git a/apps/gallery/appinfo/database.xml b/apps/gallery/appinfo/database.xml
index d1ccd6b5a24..1683e0ca2c7 100644
--- a/apps/gallery/appinfo/database.xml
+++ b/apps/gallery/appinfo/database.xml
@@ -3,7 +3,7 @@
<name>*dbname*</name>
<create>true</create>
<overwrite>false</overwrite>
- <charset>latin1</charset>
+ <charset>utf8</charset>
<table>
<name>*dbprefix*pictures_images_cache</name>
<declaration>
diff --git a/apps/gallery/appinfo/update.php b/apps/gallery/appinfo/update.php
index dd248e21b3e..a0997ab5e86 100644
--- a/apps/gallery/appinfo/update.php
+++ b/apps/gallery/appinfo/update.php
@@ -1,9 +1,11 @@
<?php
-$stmt = OCP\DB::prepare('DROP TABLE IF EXISTS *PREFIX*gallery_photos');
-$stmt->execute();
-$stmt = OCP\DB::prepare('DROP TABLE IF EXISTS *PREFIX*gallery_albums');
-$stmt->execute();
-
-\OC_DB::createDbFromStructure('./database.xml');
+$currentVersion=OC_Appconfig::getValue('gallery', 'installed_version');
+if (version_compare($currentVersion, '0.5.0', '<')) {
+ $stmt = OCP\DB::prepare('DROP TABLE IF EXISTS *PREFIX*gallery_photos');
+ $stmt->execute();
+ $stmt = OCP\DB::prepare('DROP TABLE IF EXISTS *PREFIX*gallery_albums');
+ $stmt->execute();
+ \OC_DB::createDbFromStructure(OC::$APPSROOT.'/apps/'.$appid.'/appinfo/database.xml');
+}
diff --git a/apps/gallery/css/styles.css b/apps/gallery/css/styles.css
index fbf54e43db2..98d36515493 100644
--- a/apps/gallery/css/styles.css
+++ b/apps/gallery/css/styles.css
@@ -1,20 +1,6 @@
-div#gallery_list { margin: 4.5em 2em 0 2em; }
-div#gallery_list.leftcontent { padding-top: 15pt; margin: 0; position: absolute; bottom:0px; text-align: center; overflow: auto; }
-div.gallery_box { width: 200px; position:relative; text-align: center; border: 0; display: inline-block; margin: 5pt; vertical-align: top; padding: 5px 5px 5px 5px; position: relative; -webkit-transition: color 0.5s ease-in-out; -o-transition: color 0.5s ease-in-out; -moz-transition: color 0.5s ease-in-out;color: #BBB;}
-div.album {border: 1px solid #e0e0e0; border-radius: 7px;}
-div.gallery_box h1 { font-size: 9pt; font-family: Verdana; }
-div.gallery_album_decoration { width: 200px; position: absolute; border: 0; height: 20px; top: 5px; text-align:right; vertical-align:middle; background-color: #eee; opacity: 0; -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; }
-div.gallery_box:hover { color: black; }
-div.gallery_box:hover div.gallery_album_decoration { opacity: 0.7;}
-div.gallery_album_decoration a {padding: 0 4pt; cursor: pointer;}
-div.gallery_album_cover { width: 200px; height: 200px; border: 0; padding: 0; position:relative;}
-div.gallery_box:hover div.gallery_control_overlay { opacity:0.5 }
-div.gallery_control_overlay a { color:white; }
-#gallery_images.rightcontent { padding:10px 5px; bottom: 0px; overflow: auto; right:0px}
-#scan { position:absolute; right:13.5em; top:0em; }
-#scan #scanprogressbar { position:relative; display:inline-block; width:10em; height:1.5em; top:.4em; }
+#gallerycontent { margin-top: 2.8em; overflow: visible; }
#g-settings {position: absolute; left 13.5em; top: 0;}
-input[type=button] { -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; opacity: 1}
+div#controls input[type=button] { -webkit-transition: opacity 0.5s ease-in-out; -moz-transition: opacity 0.5s ease-in-out; -o-transition: opacity 0.5s ease-in-out; opacity: 1; position:absolute; right:13.5em; top:0em; }
input[type=button]:disabled { opacity: 0.5 }
.ui-dialog tr {background-color: #eee;}
.ui-dialog input {width: 90%;}
diff --git a/apps/gallery/index.php b/apps/gallery/index.php
index 9d4654a7cc5..b87d99bb6cc 100644
--- a/apps/gallery/index.php
+++ b/apps/gallery/index.php
@@ -27,6 +27,10 @@ OCP\User::checkLoggedIn();
OCP\App::checkAppEnabled('gallery');
OCP\App::setActiveNavigationEntry( 'gallery_index' );
+OCP\Util::addStyle('files', 'files');
+OCP\Util::addStyle('gallery', 'styles');
+OCP\Util::addScript('gallery', 'pictures');
+
$tmpl = new OCP\Template( 'gallery', 'index', 'user' );
$tmpl->printPage();
?>
diff --git a/apps/gallery/js/album_cover.js b/apps/gallery/js/album_cover.js
deleted file mode 100644
index 905034f6fd1..00000000000
--- a/apps/gallery/js/album_cover.js
+++ /dev/null
@@ -1,138 +0,0 @@
-var actual_cover;
-var paths = [];
-var crumbCount = 0;
-$(document).ready(returnToElement(0));
-
-function returnToElement(num) {
- while (crumbCount != num) {
- $('#g-album-navigation .last').remove();
- $('#g-album-navigation .crumb :last').parent().addClass('last');
- crumbCount--;
- paths.pop();
- }
- var p='';
- for (var i in paths) p += paths[i]+'/';
- $('#g-album-loading').show();
- $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'get_gallery', path: p }, albumClickHandler);
-}
-
-function albumClick(title) {
- paths.push(title);
- crumbCount++;
- var p = '';
- for (var i in paths) p += paths[i]+'/';
- $('#g-album-loading').show();
- $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'get_gallery', path: p }, function(r) {
- albumClickHandler(r);
- if ($('#g-album-navigation :last-child'))
- $('#g-album-navigation :last-child').removeClass('last');
- $('#g-album-navigation').append('<div class="crumb last real" style="background-image:url(\''+OC.imagePath('core','breadcrumb')+'\')"><a href=\"javascript:returnToElement('+crumbCount+');\">'+decodeURIComponent(escape(title))+'</a></div>');
- });
-}
-
-function constructSharingPath() {
- return document.location.protocol + '//' + document.location.host + OC.linkTo('', 'public.php') + '?service=gallery&token=' + Albums.token;
-}
-
-function shareGallery() {
- var existing_token = '';
- if (Albums.token)
- existing_token = constructSharingPath();
- var form_fields = [{text: 'Share', name: 'share', type: 'checkbox', value: Albums.shared},
- {text: 'Share recursive', name: 'recursive', type: 'checkbox', value: Albums.recursive},
- {text: 'Shared gallery address', name: 'address', type: 'text', value: existing_token}];
- OC.dialogs.form(form_fields, t('gallery', 'Share gallery'), function(values){
- var p = '';
- for (var i in paths) p += paths[i]+'/';
- if (p == '') p = '/';
- alert(p);
- $.getJSON(OC.filePath('gallery', 'ajax', 'galleryOp.php'), {operation: 'share', path: p, share: values[0].value, recursive: values[1].value}, function(r) {
- if (r.status == 'success') {
- Albums.shared = r.sharing;
- if (Albums.shared) {
- Albums.token = r.token;
- Albums.recursive = r.recursive;
- } else {
- Albums.token = '';
- Albums.recursive = false;
- }
- var actual_addr = '';
- if (Albums.token)
- actual_addr = constructSharingPath();
- $('input[name="address"]').val(actual_addr);
- } else {
- OC.dialogs.alert(t('gallery', 'Error: ') + r.cause, t('gallery', 'Internal error'));
- }
- });
- });
-}
-
-function albumClickHandler(r) {
- Albums.photos = [];
- Albums.albums = [];
- if (r.status == 'success') {
- for (var i in r.albums) {
- var a = r.albums[i];
- Albums.add(a.name, a.numOfItems, a.path, a.shared, a.recursive, a.token);
- }
- for (var i in r.photos) {
- Albums.photos.push(r.photos[i]);
- }
- Albums.shared = r.shared;
- if (Albums.shared) {
- Albums.recursive = r.recursive;
- Albums.token = r.token;
- } else {
- Albums.recursive = false;
- Albums.token = '';
- }
- $(document).ready(function(){
- var targetDiv = $('#gallery_list');
- targetDiv.html('');
- Albums.display(targetDiv);
- //$('#gallery_list').sortable({revert:true});
- $('.album').each(function(i, el) {
- $(el).click(albumClick.bind(null,$(el).attr('title')));
- //$(el).draggable({connectToSortable: '#gallery_list', handle: '.dummy'});
- });
- });
- } else {
- OC.dialogs.alert(t('gallery', 'Error: ') + r.cause, t('gallery', 'Internal error'));
- }
- $('#g-album-loading').hide();
-}
-
-var albumCounter = 0;
-var totalAlbums = 0;
-
-function scanForAlbums(cleanup) {
- Scanner.scanAlbums();
- return;
-}
-
-function settings() {
- OC.dialogs.form([{text: t('gallery', 'Scanning root'), name: 'root', type:'text', value:gallery_scanning_root},
- {text: t('gallery', 'Default order'), name: 'order', type:'select', value:gallery_default_order, options:[
- {text:t('gallery', 'Ascending'), value:'ASC'}, {text: t('gallery', 'Descending'), value:'DESC'} ]}],
- t('gallery', 'Settings'),
- function(values) {
- var scanning_root = values[0].value;
- var disp_order = values[1].value;
- if (scanning_root == '') {
- OC.dialogs.alert(t('gallery', 'Scanning root cannot be empty'), t('gallery', 'Error'));
- return;
- }
- $.getJSON(OC.filePath('gallery','ajax','galleryOp.php'), {operation: 'store_settings', root: scanning_root, order: disp_order}, function(r) {
- if (r.status == 'success') {
- if (r.rescan == 'yes') {
- Albums.clear(document.getElementById('gallery_list'));
- scanForAlbums(true);
- }
- gallery_scanning_root = scanning_root;
- } else {
- OC.dialogs.alert(t('gallery', 'Error: ') + r.cause, t('gallery', 'Error'));
- return;
- }
- });
- });
-}
diff --git a/apps/gallery/js/pictures.js b/apps/gallery/js/pictures.js
new file mode 100644
index 00000000000..678c9bcbf55
--- /dev/null
+++ b/apps/gallery/js/pictures.js
@@ -0,0 +1,37 @@
+
+function constructSharingPath() {
+ return document.location.protocol + '//' + document.location.host + OC.linkTo('', 'public.php') + '?service=gallery&token=' + Albums.token;
+}
+
+function shareGallery() {
+ var existing_token = '';
+ //if (Albums.token)
+ // existing_token = constructSharingPath();
+ var form_fields = [{text: 'Share', name: 'share', type: 'checkbox', value: false},
+ {text: 'Share recursive', name: 'recursive', type: 'checkbox', value: false},
+ {text: 'Shared gallery address', name: 'address', type: 'text', value: ''}];
+ OC.dialogs.form(form_fields, t('gallery', 'Share gallery'), function(values){
+ var p = '';
+ for (var i in paths) p += paths[i]+'/';
+ if (p == '') p = '/';
+ alert(p);
+ $.getJSON(OC.filePath('gallery', 'ajax', 'galleryOp.php'), {operation: 'share', path: p, share: values[0].value, recursive: values[1].value}, function(r) {
+ if (r.status == 'success') {
+ Albums.shared = r.sharing;
+ if (Albums.shared) {
+ Albums.token = r.token;
+ Albums.recursive = r.recursive;
+ } else {
+ Albums.token = '';
+ Albums.recursive = false;
+ }
+ var actual_addr = '';
+ if (Albums.token)
+ actual_addr = constructSharingPath();
+ $('input[name="address"]').val(actual_addr);
+ } else {
+ OC.dialogs.alert(t('gallery', 'Error: ') + r.cause, t('gallery', 'Internal error'));
+ }
+ });
+ });
+}
diff --git a/apps/gallery/lib/hooks_handlers.php b/apps/gallery/lib/hooks_handlers.php
index 6391e9f4e54..a9f4dc6affc 100644
--- a/apps/gallery/lib/hooks_handlers.php
+++ b/apps/gallery/lib/hooks_handlers.php
@@ -13,136 +13,30 @@
*
* 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
+* 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/>.
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
-OCP\Util::connectHook(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, "OC_Gallery_Hooks_Handlers", "addPhotoFromPath");
OCP\Util::connectHook(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_delete, "OC_Gallery_Hooks_Handlers", "removePhoto");
//OCP\Util::connectHook(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, "OC_Gallery_Hooks_Handlers", "renamePhoto");
-require_once(OC::$CLASSPATH['OC_Gallery_Album']);
-require_once(OC::$CLASSPATH['OC_Gallery_Photo']);
+require_once(OC::$CLASSPATH['Pictures_Managers']);
class OC_Gallery_Hooks_Handlers {
- private static $APP_TAG = "Gallery";
- private static function isPhoto($filename) {
- $ext = strtolower(substr($filename, strrpos($filename, '.')+1));
- return $ext=='png' || $ext=='jpeg' || $ext=='jpg' || $ext=='gif';
- }
+ public static function removePhoto($params) {
+ \OC\Pictures\ThumbnailsManager::getInstance()->delete($params[OC_Filesystem::signal_param_path]);
+ }
- private static function directoryContainsPhotos($dirpath) {
- $dirhandle = OC_Filesystem::opendir($dirpath.'/');
- if ($dirhandle != FALSE) {
- while (($filename = readdir($dirhandle)) != FALSE) {
- if ($filename[0] == '.') continue;
- if (self::isPhoto($dirpath.'/'.$filename)) return true;
- }
- }
- return false;
- }
-
- private static function createAlbum($path) {
- $new_album_name = trim(str_replace('/', '.', $path), '.');
- if ($new_album_name == '')
- $new_album_name = 'main';
-
- 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(OCP\USER::getUser(), null, $path);
- }
-
- public static function pathInRoot($path) {
- $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;
-
- $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) {
- $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));
- }
- }
- }
- }
-
- public static function renamePhoto($params) {
- $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, OCP\USER::getUser());
- } elseif (self::isPhoto($newpath)) {
- $olddir = dirname($oldpath);
- $newdir = dirname($newpath);
- if ($olddir == '') $olddir = '/';
- if ($newdir == '') $newdir = '/';
- if (!self::isPhoto($newpath)) return;
- 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(OCP\USER::getUser(), null, $olddir);
- $album = $albums->fetchRow();
- if (!$album) {
- $albums = self::createAlbum($newdir);
- $album = $albums->fetchRow();
- }
- $newAlbumId = $oldAlbumId = $album['album_id'];
- } else {
- $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);
- $newalbum = $newalbum->fetchRow();
- }
- $oldalbum = $oldalbum->fetchRow();
- if (!$oldalbum) {
- OC_Gallery_Photo::create($newalbum['album_id'], $newpath);
- return;
- }
- $newAlbumId = $newalbum['album_id'];
- $oldAlbumId = $oldalbum['album_id'];
-
- }
- OC_Gallery_Photo::changePath($oldAlbumId, $newAlbumId, $oldpath, $newpath);
- }
- }
+ public static function renamePhoto($params) {
+ $oldpath = $params[OC_Filesystem::signal_param_oldpath];
+ $newpath = $params[OC_Filesystem::signal_param_newpath];
+ //TODO: implement this
+ }
}
?>
diff --git a/apps/gallery/lib/managers.php b/apps/gallery/lib/managers.php
index 2444659d0a4..d4d978dbdd0 100644
--- a/apps/gallery/lib/managers.php
+++ b/apps/gallery/lib/managers.php
@@ -2,11 +2,6 @@
namespace OC\Pictures;
-require_once('lib/base.php');
-
-\OCP\JSON::checkLoggedIn();
-\OCP\JSON::checkAppEnabled('gallery');
-
class DatabaseManager {
private static $instance = null;
const TAG = 'DatabaseManager';
@@ -29,13 +24,11 @@ class DatabaseManager {
if (!$image->loadFromFile($path)) {
return false;
}
- \OCP\DB::beginTransaction();
$stmt = \OCP\DB::prepare('INSERT INTO *PREFIX*pictures_images_cache (uid_owner, path, width, height) VALUES (?, ?, ?, ?)');
$stmt->execute(array(\OCP\USER::getUser(), $path, $image->width(), $image->height()));
- \OCP\DB::commit();
- $ret = array('filepath' => $path, 'width' => $image->width(), 'height' => $image->height());
+ $ret = array('path' => $path, 'width' => $image->width(), 'height' => $image->height());
unset($image);
- return $ret;
+ return $ret;
}
private function __construct() {}
@@ -81,14 +74,19 @@ class ThumbnailsManager {
public function getThumbnailInfo($path) {
$arr = DatabaseManager::getInstance()->getFileData($path);
+ if (!$arr) {
+ $thubnail = $this->getThumbnail($path);
+ unset($thubnail);
+ $arr = DatabaseManager::getInstance()->getFileData($path);
+ }
$ret = array('filepath' => $arr['path'],
- 'width' => $arr['width'],
- 'height' => $arr['height']);
+ 'width' => $arr['width'],
+ 'height' => $arr['height']);
return $ret;
}
public function delete($path) {
- unlink(\OC::$CONFIG_DATADIRECTORY_ROOT.'/'.\OC_User::getUser()."/gallery".$path);
+ unlink(\OCP\Config::getSystemValue('datadirectory').'/'.\OC_User::getUser()."/gallery".$path);
}
private function __construct() {}
diff --git a/apps/gallery/lib/tiles.php b/apps/gallery/lib/tiles.php
index ff9519142ac..e43c99bb76a 100644
--- a/apps/gallery/lib/tiles.php
+++ b/apps/gallery/lib/tiles.php
@@ -95,7 +95,7 @@ class TileSingle extends TileBase {
public function get($extra = '') {
// !HACK! file path needs to be encoded twice because files app decode twice url, so any special chars like + or & in filename
// !HACK! will result in failing of opening them
- return '<a rel="images" title="'.basename($this->getPath()).'" href="'.\OCP\Util::linkTo('files', 'download.php').'?file='.urlencode(urlencode($this->getPath())).'"><img rel="images" src="'.\OCP\Util::linkTo('gallery', 'ajax/thumbnail.php').'&filepath='.urlencode($this->getPath()).'" '.$extra.'></a>';
+ return '<a rel="images" title="'.htmlentities(basename($this->getPath())).'" href="'.\OCP\Util::linkTo('files', 'download.php').'?file='.urlencode(urlencode($this->getPath())).'"><img rel="images" src="'.\OCP\Util::linkTo('gallery', 'ajax/thumbnail.php').'&filepath='.urlencode($this->getPath()).'" '.$extra.'></a>';
}
public function getMiniatureSrc() {
@@ -156,11 +156,11 @@ class TileStack extends TileBase {
}
public function getOnHoverAction() {
- return 'javascript:t(this);return false;';
+ return 'javascript:explode(this);return false;';
}
public function getOnOutAction() {
- return 'javascript:o(this);return false;';
+ return 'javascript:deplode(this);return false;';
}
public function getCount() {
diff --git a/apps/gallery/templates/index.php b/apps/gallery/templates/index.php
index 39e3bbf47b3..749f8891f81 100644
--- a/apps/gallery/templates/index.php
+++ b/apps/gallery/templates/index.php
@@ -1,21 +1,22 @@
<?php
$l = OC_L10N::get('gallery');
+$root = !empty($_GET['root']) ? $_GET['root'] : '/';
?>
<style>
div.gallery_div {position:relative; display: inline-block; height: 152px; width: 150px; margin: 5px;}
-div.miniature_border {position:absolute; height: 150px; -webkit-transition-duration: .2s; background-position: 50%;}
+div.miniature_border {position:absolute; height: 150px; -moz-transition-duration: 0.2s; -o-transition-duration:0.2s; -webkit-transition-duration: .2s; background-position: 50%;}
div.line {display:inline-block; border: 0; width: auto; height: 160px}
-div.gallery_div img{position:absolute; top: 1; left: 0; -webkit-transition-duration: 0.3s; height:150px; width: auto;}
+div.gallery_div img{position:absolute; top: 1; left: 0; -moz-transition-duration: 0.3s; -o-transition-duration:0.3s; -webkit-transition-duration: 0.3s; height:150px; width: auto;}
div.gallery_div img.shrinker {width:80px !important;}
div.title { opacity: 0; text-align: center; vertical-align: middle; font-family: Arial; font-size: 12px; border: 0; position: absolute; text-overflow: ellipsis; bottom: 20px; left:5px; height:auto; padding: 5px; width: 140px; background-color: black; color: white; -webkit-transition: opacity 0.5s; z-index:1000; border-radius: 7px}
div.visible { opacity: 0.8;}
</style>
<script type="text/javascript">
-var root = "<?php echo !empty($_GET['root']) ? $_GET['root'] : '/'; ?>";
+var root = "<?php echo htmlentities($root); ?>";
-function t(element) {
+function explode(element) {
$('div', element).each(function(index, elem) {
if ($(elem).hasClass('title')) {
$(elem).addClass('visible');
@@ -27,7 +28,7 @@ function t(element) {
});
}
-function o(element) {
+function deplode(element) {
$('div', element).each(function(index, elem) {
if ($(elem).hasClass('title')) {
$(elem).removeClass('visible');
@@ -55,6 +56,21 @@ $(document).ready(function() {
</script>
+<div id="controls"><?php
+ $sr = trim($root, '/');
+ if (!empty($sr)) {
+ $paths = explode('/', $sr);
+ $path = '/';
+ for ($i = 0; $i < count($paths); $i++) {
+ $path .= urlencode($paths[$i]).'/';
+ $classess = 'crumb'.($i == count($paths)-1?' last':'');
+ echo '<div class="'.$classess.'" style="background-image:url(\''.\OCP\image_path('core','breadcrumb.png').'\')"><a href="'.\OCP\Util::linkTo('gallery', 'index.php').'&root='.$path.'">'.$paths[$i].'</a></div>';
+ }
+ }
+
+?> <!--<a href="javascript:shareGallery();"><input type="button" value="<?php echo $l->t('Share');?>" /></a>--><br/>
+</div>
+<div id="gallerycontent">
<?php
include('apps/gallery/lib/tiles.php');
@@ -66,7 +82,7 @@ sort($images);
$arr = array();
$tl = new \OC\Pictures\TilesLine();
$ts = new \OC\Pictures\TileStack(array(), '');
-$previous_element = $images[0];
+$previous_element = @$images[0];
for($i = 0; $i < count($images); $i++) {
$prev_dir_arr = explode('/', $previous_element);
$dir_arr = explode('/', $images[$i]);
@@ -85,10 +101,8 @@ for($i = 0; $i < count($images); $i++) {
$dir_arr = explode('/', $previous_element);
-if (count($images)>1) {
- if (count($dir_arr)==0) {
- $tl->addTile(new \OC\Pictures\TileSingle($previous_element));
- } else if (count($dir_arr) && $ts->getCount() == 0){
+if (count($images)>1 && count($dir_arr) > 1) {
+ if (count($dir_arr) && $ts->getCount() == 0){
$ts = new \OC\Pictures\TileStack(array($root.$previous_element), $dir_arr[0]);
} else {
$arr[] = $previous_element;
@@ -103,3 +117,4 @@ if ($ts->getCount() != 0) {
echo $tl->get();
?>
+</div>
diff --git a/apps/media/ajax/api.php b/apps/media/ajax/api.php
index 6e269f3bb78..a229c17e804 100644
--- a/apps/media/ajax/api.php
+++ b/apps/media/ajax/api.php
@@ -103,6 +103,10 @@ if($arguments['action']){
@ob_end_clean();
$ftype=OC_Filesystem::getMimeType( $arguments['path'] );
+ if(substr($ftype,0,5)!='audio' and $ftype!='application/ogg'){
+ echo 'Not an audio file';
+ exit();
+ }
$songId=OC_MEDIA_COLLECTION::getSongByPath($arguments['path']);
OC_MEDIA_COLLECTION::registerPlay($songId);
diff --git a/apps/media/appinfo/database.xml b/apps/media/appinfo/database.xml
index 702ae9c28b4..9b942d282bb 100644
--- a/apps/media/appinfo/database.xml
+++ b/apps/media/appinfo/database.xml
@@ -5,7 +5,7 @@
<create>true</create>
<overwrite>false</overwrite>
- <charset>latin1</charset>
+ <charset>utf8</charset>
<table>
diff --git a/apps/remoteStorage/appinfo/database.xml b/apps/remoteStorage/appinfo/database.xml
index 00ee4942744..d48f9f747b1 100644
--- a/apps/remoteStorage/appinfo/database.xml
+++ b/apps/remoteStorage/appinfo/database.xml
@@ -3,7 +3,7 @@
<name>*dbname*</name>
<create>true</create>
<overwrite>false</overwrite>
- <charset>latin1</charset>
+ <charset>utf8</charset>
<table>
<name>*dbprefix*authtoken</name>
<declaration>
diff --git a/apps/remoteStorage/auth.php b/apps/remoteStorage/auth.php
index ac0e83bb373..99e2272d3ab 100644
--- a/apps/remoteStorage/auth.php
+++ b/apps/remoteStorage/auth.php
@@ -25,6 +25,7 @@
*
*/
+header("X-Frame-Options: Sameorigin");
// Do not load FS ...
$RUNTIME_NOSETUPFS = true;
@@ -43,9 +44,9 @@ foreach($_GET as $k => $v) {
$userId=$v;
} else if($k=='redirect_uri'){
$appUrlParts=explode('/', $v);
- $appUrl = $appUrlParts[2];//bit dodgy i guess
+ $appUrl = htmlentities($appUrlParts[2]);//TODO: check if this is equal to client_id
} else if($k=='scope'){
- $categories=$v;
+ $categories=htmlentities($v);
}
}
$currUser = OCP\USER::getUser();
@@ -112,7 +113,7 @@ if($userId && $appUrl && $categories) {
}//end 'need to click Allow still'
} else {//login not ok
if($currUser) {
- die('You are logged in as '.$currUser.' instead of '.$userId);
+ die('You are logged in as '.$currUser.' instead of '.htmlentities($userId));
} else {
header('Location: /?redirect_url='.urlencode('/apps/remoteStorage/auth.php'.$_SERVER['PATH_INFO'].'?'.$_SERVER['QUERY_STRING']));
}
diff --git a/apps/tasks/ajax/addtask.php b/apps/tasks/ajax/addtask.php
index d6e313bd089..9f35e7f21ec 100644
--- a/apps/tasks/ajax/addtask.php
+++ b/apps/tasks/ajax/addtask.php
@@ -8,7 +8,7 @@ $calendars = OC_Calendar_Calendar::allCalendars(OCP\User::getUser(), true);
$first_calendar = reset($calendars);
$cid = $first_calendar['id'];
-$input = $_GET['text'];
+$input = $_POST['text'];
$request = array();
$request['summary'] = $input;
$request["categories"] = null;
diff --git a/apps/tasks/ajax/delete.php b/apps/tasks/ajax/delete.php
index 6d2868748d1..e29add9b556 100644
--- a/apps/tasks/ajax/delete.php
+++ b/apps/tasks/ajax/delete.php
@@ -24,7 +24,7 @@
OCP\JSON::checkLoggedIn();
OCP\JSON::checkAppEnabled('tasks');
-$id = $_GET['id'];
+$id = $_POST['id'];
$task = OC_Calendar_App::getEventObject( $id );
OC_Calendar_Object::delete($id);
diff --git a/apps/tasks/js/tasks.js b/apps/tasks/js/tasks.js
index 60d2a523be1..6547b80981c 100644
--- a/apps/tasks/js/tasks.js
+++ b/apps/tasks/js/tasks.js
@@ -310,8 +310,11 @@ OC.Tasks = {
};
$(document).ready(function(){
- fillHeight($('#tasks_lists'));
- fillWindow($('#tasks_list'));
+ $(window).resize(function () {
+ fillHeight($('#tasks_lists'));
+ fillWindow($('#tasks_list'));
+ });
+ $(window).trigger('resize');
/*-------------------------------------------------------------------------
* Actions for startup
@@ -440,7 +443,7 @@ $(document).ready(function(){
$('#tasks_delete').live('click',function(){
var id = $('#task_details').data('id');
- $.getJSON('ajax/delete.php',{'id':id},function(jsondata){
+ $.post('ajax/delete.php',{'id':id},function(jsondata){
if(jsondata.status == 'success'){
$('#tasks [data-id="'+jsondata.data.id+'"]').remove();
$('#task_details').data('id','');
@@ -455,7 +458,7 @@ $(document).ready(function(){
$('#tasks_addtask').click(function(){
var input = $('#tasks_newtask').val();
- $.getJSON(OC.filePath('tasks', 'ajax', 'addtask.php'),{text:input},function(jsondata){
+ $.post(OC.filePath('tasks', 'ajax', 'addtask.php'),{text:input},function(jsondata){
if(jsondata.status == 'success'){
$('#tasks_list').append(OC.Tasks.create_task_div(jsondata.task));
}
diff --git a/apps/tasks/templates/part.taskform.php b/apps/tasks/templates/part.taskform.php
index c00560903b0..0a25ed33c91 100644
--- a/apps/tasks/templates/part.taskform.php
+++ b/apps/tasks/templates/part.taskform.php
@@ -5,7 +5,7 @@
<input type="text" id="location" name="location" placeholder="<?php echo $l->t('Location of the task');?>" value="<?php echo isset($_['details']->LOCATION) ? $_['details']->LOCATION[0]->value : '' ?>">
<br>
<label for="categories"><?php echo $l->t('Categories'); ?></label>
- <input id="categories" name="categories" type="text" placeholder="<?php echo $l->t('Separate categories with commas'); ?>" value="<?php echo isset($_['categories']) ? htmlspecialchars($_['categories']) : '' ?>">
+ <input id="categories" name="categories" type="text" placeholder="<?php echo $l->t('Separate categories with commas'); ?>" value="<?php echo isset($_['categories']) ? $_['categories'] : '' ?>">
<a class="action edit" onclick="$(this).tipsy('hide');OCCategories.edit();" title="<?php echo $l->t('Edit categories'); ?>"><img alt="<?php echo $l->t('Edit categories'); ?>" src="<?php echo OCP\image_path('core','actions/rename.svg')?>" class="svg action" style="width: 16px; height: 16px;"></a>
<br>
<label for="due"><?php echo $l->t('Due'); ?></label>
diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php
index 62e7c8ca6bc..78bc5b46566 100644
--- a/apps/user_ldap/group_ldap.php
+++ b/apps/user_ldap/group_ldap.php
@@ -186,11 +186,11 @@ class OC_GROUP_LDAP extends OC_Group_Backend {
if(!$this->configured) {
return array();
}
- if(is_null($this->_groups)) {
+ if(empty($this->_groups)) {
$ldap_groups = OC_LDAP::fetchListOfGroups($this->ldapGroupFilter, array(OC_LDAP::conf('ldapGroupDisplayName'), 'dn'));
$this->_groups = OC_LDAP::ownCloudGroupNames($ldap_groups);
}
- return $this->groups;
+ return $this->_groups;
}
/**
diff --git a/apps/user_ldap/lib_ldap.php b/apps/user_ldap/lib_ldap.php
index 22d464b65a2..befdf267bcd 100644
--- a/apps/user_ldap/lib_ldap.php
+++ b/apps/user_ldap/lib_ldap.php
@@ -576,7 +576,7 @@ class OC_LDAP {
static private function combineFilter($filters, $operator) {
$combinedFilter = '('.$operator;
foreach($filters as $filter) {
- if(substr($filter,0,1) != '(') {
+ if($filter[0] != '(') {
$filter = '('.$filter.')';
}
$combinedFilter.=$filter;
@@ -692,4 +692,4 @@ class OC_LDAP {
return false;
}
- } \ No newline at end of file
+ }
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
index 9c0620578be..42084855e85 100644
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -20,7 +20,7 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
-$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute');
+$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_group_display_name', 'ldap_tls', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute');
OCP\Util::addscript('user_ldap', 'settings');
@@ -54,6 +54,7 @@ foreach($params as $param){
// settings with default values
$tmpl->assign( 'ldap_port', OCP\Config::getAppValue('user_ldap', 'ldap_port', '389'));
$tmpl->assign( 'ldap_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_display_name', 'uid'));
+$tmpl->assign( 'ldap_group_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', 'cn'));
$tmpl->assign( 'ldap_group_member_assoc_attribute', OCP\Config::getAppValue('user_ldap', 'ldap_group_member_assoc_attribute', 'uniqueMember'));
$tmpl->assign( 'ldap_agent_password', base64_decode(OCP\Config::getAppValue('user_ldap', 'ldap_agent_password')));
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 3462f2473f4..31f453b5a5a 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -22,6 +22,7 @@
<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><label for="ldap_group_display_name"><?php echo $l->t('Group Display Name Field');?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" value="<?php echo $_['ldap_group_display_name']; ?>" /></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 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>
diff --git a/config/config.sample.php b/config/config.sample.php
index afc04f8ec1b..5af5a6efc02 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -3,32 +3,89 @@
define("DEBUG", true);
$CONFIG = array(
+/* Flag to indicate OwnCloud is successfully installed (true = installed) */
"installed" => false,
+
+/* Type of database, can be sqlite, mysql or pgsql */
"dbtype" => "sqlite",
+
+/* Name of the OwnCloud database */
"dbname" => "owncloud",
+
+/* User to access the OwnCloud database */
"dbuser" => "",
+
+/* Password to access the OwnCloud database */
"dbpassword" => "",
+
+/* Host running the OwnCloud database */
"dbhost" => "",
+
+/* Prefix for the OwnCloud tables in the database */
"dbtableprefix" => "",
+
+/* Define the salt used to hash the user passwords. All your user passwords are lost if you lose this string. */
+"passwordsalt" => "",
+
+/* Force use of HTTPS connection (true = use HTTPS) */
"forcessl" => false,
-"enablebackup" => false,
+
+/* Theme to use for OwnCloud */
"theme" => "",
+
+/* Path to the 3rdparty directory */
"3rdpartyroot" => "",
+
+/* URL to the 3rdparty directory, as seen by the browser */
"3rdpartyurl" => "",
+
+/* Default app to load on login */
"defaultapp" => "files",
+
+/* Enable the help menu item in the settings */
"knowledgebaseenabled" => true,
-"knowledgebaseurl" => "",
+
+/* URL to use for the help page, server should understand OCS */
+"knowledgebaseurl" => "http://api.apps.owncloud.com/v1",
+
+/* Enable installing apps from the appstore */
"appstoreenabled" => true,
-"appstoreurl" => "",
+
+/* URL of the appstore to use, server should understand OCS */
+"appstoreurl" => "http://api.apps.owncloud.com/v1",
+
+/* Mode to use for sending mail, can be sendmail, smtp, qmail or php, see PHPMailer docs */
"mail_smtpmode" => "sendmail",
+
+/* Host to use for sending mail, depends on mail_smtpmode if this is used */
"mail_smtphost" => "127.0.0.1",
+
+/* authentication needed to send mail, depends on mail_smtpmode if this is used
+ * (false = disable authentication)
+ */
"mail_smtpauth" => false,
+
+/* Username to use for sendmail mail, depends on mail_smtpauth if this is used */
"mail_smtpname" => "",
+
+/* Password to use for sendmail mail, depends on mail_smtpauth if this is used */
"mail_smtppassword" => "",
+
+/* Check 3rdparty apps for malicious code fragments */
"appcodechecker" => "",
-"log_type" => "",
+
+/* Check if ownCloud is up to date */
+"updatechecker" => true,
+
+/* Place to log to, can be owncloud and syslog (owncloud is log menu item in admin menu) */
+"log_type" => "owncloud",
+
+/* File for the owncloud logger to log to, (default is ownloud.log in the data dir */
"logfile" => "",
+
+/* Loglevel to start logging at. 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR (default is WARN) */
"loglevel" => "",
+
/* Set this to false to disable the check for writable apps dir.
* If the apps dir is not writable, you can't download&install extra apps
* in the admin apps menu.
@@ -46,5 +103,9 @@ $CONFIG = array(
'writable' => true,
),
),
+
+/* The directory where the user data is stored, default to data in the owncloud
+ * directory. The sqlite database is also stored here, when sqlite is used.
+ */
);
?>
diff --git a/core/js/multiselect.js b/core/js/multiselect.js
index 541dddf0f70..5f339006d26 100644
--- a/core/js/multiselect.js
+++ b/core/js/multiselect.js
@@ -57,8 +57,11 @@
element=$(element);
var item=element.val();
var id='ms'+multiSelectId+'-option-'+item;
- var input=$('<input id="'+id+'" type="checkbox"/>');
- var label=$('<label for="'+id+'">'+item+'</label>');
+ var input=$('<input type="checkbox"/>');
+ input.attr('id',id);
+ var label=$('<label/>');
+ label.attr('for',id);
+ label.text(item);
if(settings.checked.indexOf(item)!=-1 || checked){
input.attr('checked',true);
}
@@ -130,7 +133,10 @@
li.text('+ '+settings.createText);
li.before(createItem(this));
var select=button.parent().next();
- select.append($('<option selected="selected" value="'+$(this).val()+'">'+$(this).val()+'</option>'));
+ var option=$('<option selected="selected"/>');
+ option.attr('value',$(this).val());
+ option.text($(this).val());
+ select.append(optione);
li.prev().children('input').trigger('click');
button.parent().data('preventHide',false);
if(settings.createCallback){
diff --git a/core/lostpassword/index.php b/core/lostpassword/index.php
index 6bed7bdd93f..bd2a3e897e5 100644
--- a/core/lostpassword/index.php
+++ b/core/lostpassword/index.php
@@ -17,7 +17,7 @@ if (isset($_POST['user'])) {
OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token);
$email = OC_Preferences::getValue($_POST['user'], 'settings', '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;
+ $link = OC_Helper::linkToAbsolute('core/lostpassword', 'resetpassword.php').'?user='.urlencode($_POST['user']).'&token='.$token;
$tmpl = new OC_Template('core/lostpassword', 'email');
$tmpl->assign('link', $link);
$msg = $tmpl->fetchPage();
diff --git a/core/templates/404.php b/core/templates/404.php
index cd4f2b40bb2..13a81010343 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 htmlentities($_['file'])?></p>
+ <p class='hint'><?php if(isset($_['file'])) echo $_['file']?></p>
</li>
</ul>
diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php
index 7a968917718..4cdbfd16e52 100644
--- a/core/templates/layout.guest.php
+++ b/core/templates/layout.guest.php
@@ -4,7 +4,7 @@
<title>ownCloud</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 if (!defined('DEBUG') || !DEBUG): ?>
+ <?php if (!empty(OC_Util::$core_styles)): ?>
<link rel="stylesheet" href="<?php echo OC_Helper::linkToRemote('core.css', false) ?>" type="text/css" media="screen" />
<?php endif ?>
<?php foreach($_['cssfiles'] as $cssfile): ?>
@@ -14,7 +14,7 @@
var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
var oc_appswebroots = <?php echo $_['apps_paths'] ?>;
</script>
- <?php if (!defined('DEBUG') || !DEBUG): ?>
+ <?php if (!empty(OC_Util::$core_scripts)): ?>
<script type="text/javascript" src="<?php echo OC_Helper::linkToRemote('core.js', false) ?>"></script>
<?php endif ?>
<?php foreach($_['jsfiles'] as $jsfile): ?>
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index 91cfa1a87a1..fabc28f6637 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -4,7 +4,7 @@
<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 if (!defined('DEBUG') || !DEBUG): ?>
+ <?php if (!empty(OC_Util::$core_styles)): ?>
<link rel="stylesheet" href="<?php echo OC_Helper::linkToRemote('core.css', false) ?>" type="text/css" media="screen" />
<?php endif ?>
<?php foreach($_['cssfiles'] as $cssfile): ?>
@@ -15,7 +15,7 @@
var oc_appswebroots = <?php echo $_['apps_paths'] ?>;
var oc_current_user = '<?php echo OC_User::getUser() ?>';
</script>
- <?php if (!defined('DEBUG') || !DEBUG): ?>
+ <?php if (!empty(OC_Util::$core_scripts)): ?>
<script type="text/javascript" src="<?php echo OC_Helper::linkToRemote('core.js', false) ?>"></script>
<?php endif ?>
<?php foreach($_['jsfiles'] as $jsfile): ?>
@@ -30,6 +30,16 @@
echo '/>';
?>
<?php endforeach; ?>
+ <script type="text/javascript">
+ $(function() {
+ requesttoken = '<?php echo $_['requesttoken']; ?>';
+ $(document).bind('ajaxSend', function(elm, xhr, s){
+ if(requesttoken) {
+ xhr.setRequestHeader('requesttoken', requesttoken);
+ }
+ });
+ });
+ </script>
</head>
<body id="<?php echo $_['bodyid'];?>">
diff --git a/core/templates/login.php b/core/templates/login.php
index 41d6ba41ef8..a40bf5c330a 100644
--- a/core/templates/login.php
+++ b/core/templates/login.php
@@ -1,7 +1,7 @@
<!--[if IE 8]><style>input[type="checkbox"]{padding:0;}</style><![endif]-->
<form action="index.php" method="post">
<fieldset>
- <?php if(!empty($_['redirect'])) { echo '<input type="hidden" name="redirect_url" value="'.htmlentities($_['redirect']).'" />'; } ?>
+ <?php if(!empty($_['redirect'])) { echo '<input type="hidden" name="redirect_url" value="'.$_['redirect'].'" />'; } ?>
<?php if($_['error']): ?>
<a href="./core/lostpassword/"><?php echo $l->t('Lost your password?'); ?></a>
<?php endif; ?>
diff --git a/db_structure.xml b/db_structure.xml
index d29dcb46f8c..94567b4d539 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -432,10 +432,8 @@
<field>
<name>configvalue</name>
- <type>text</type>
- <default></default>
+ <type>clob</type>
<notnull>true</notnull>
- <length>255</length>
</field>
</declaration>
diff --git a/index.php b/index.php
index d552c149df8..b90b1b310a9 100755
--- a/index.php
+++ b/index.php
@@ -69,10 +69,10 @@ elseif(OC_User::isLoggedIn()) {
// For all others cases, we display the guest page :
} 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"]) {
+ OC_App::loadApps(array('authentication'));
if(defined("DEBUG") && DEBUG) {
OC_Log::write('core','Trying to login from cookie',OC_Log::DEBUG);
}
@@ -88,6 +88,7 @@ elseif(OC_User::isLoggedIn()) {
// Someone wants to log in :
} elseif(isset($_POST["user"]) and isset($_POST['password']) and isset($_SESSION['sectoken']) and isset($_POST['sectoken']) and ($_SESSION['sectoken']==$_POST['sectoken']) ) {
+ OC_App::loadApps();
if(OC_User::login($_POST["user"], $_POST["password"])) {
if(!empty($_POST["remember_login"])){
if(defined("DEBUG") && DEBUG) {
@@ -107,9 +108,11 @@ elseif(OC_User::isLoggedIn()) {
// 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"])){
+ OC_App::loadApps(array('authentication'));
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();
+ $_REQUEST['redirect_url'] = (isset($_SERVER['REQUEST_URI'])?$_SERVER['REQUEST_URI']:'');
OC_Util::redirectToDefaultPage();
}else{
$error = true;
diff --git a/lib/app.php b/lib/app.php
index ca7a022f893..1dcccee1da0 100755
--- a/lib/app.php
+++ b/lib/app.php
@@ -67,6 +67,11 @@ class OC_App{
OC_Util::$scripts = array();
OC_Util::$core_styles = OC_Util::$styles;
OC_Util::$styles = array();
+
+ if (!OC_AppConfig::getValue('core', 'remote_core.css', false)) {
+ OC_AppConfig::setValue('core', 'remote_core.css', '/core/minimizer.php');
+ OC_AppConfig::setValue('core', 'remote_core.js', '/core/minimizer.php');
+ }
}
}
// return
@@ -510,7 +515,7 @@ class OC_App{
foreach(OC::$APPSROOTS as $apps_dir) {
$dh=opendir($apps_dir['path']);
while($file=readdir($dh)){
- if(substr($file,0,1)!='.' and is_file($apps_dir['path'].'/'.$file.'/appinfo/app.php')){
+ if($file[0]!='.' and is_file($apps_dir['path'].'/'.$file.'/appinfo/app.php')){
$apps[]=$file;
}
}
diff --git a/lib/archive/tar.php b/lib/archive/tar.php
index 4ff78779834..944a0ac4ba4 100644
--- a/lib/archive/tar.php
+++ b/lib/archive/tar.php
@@ -150,7 +150,7 @@ class OC_Archive_TAR extends OC_Archive{
$folderContent=array();
$pathLength=strlen($path);
foreach($files as $file){
- if(substr($file,0,1)=='/'){
+ if($file[0]=='/'){
$file=substr($file,1);
}
if(substr($file,0,$pathLength)==$path and $file!=$path){
@@ -241,7 +241,7 @@ class OC_Archive_TAR extends OC_Archive{
}
}
}
- if(substr($path,0,1)!='/'){//not all programs agree on the use of a leading /
+ if($path[0]!='/'){//not all programs agree on the use of a leading /
return $this->fileExists('/'.$path);
}else{
return false;
diff --git a/lib/archive/zip.php b/lib/archive/zip.php
index 22ab48937eb..6631a649b16 100644
--- a/lib/archive/zip.php
+++ b/lib/archive/zip.php
@@ -191,7 +191,7 @@ class OC_Archive_ZIP extends OC_Archive{
}
private function stripPath($path){
- if(substr($path,0,1)=='/'){
+ if(!$path || $path[0]=='/'){
return substr($path,1);
}else{
return $path;
diff --git a/lib/base.php b/lib/base.php
index ca4052e5a18..a0f5e83dd47 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -120,7 +120,7 @@ class OC{
// calculate the documentroot
$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']);
OC::$SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-13));
- OC::$SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen(OC::$SERVERROOT));
+ OC::$SUBURI= str_replace("\\","/",substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen(OC::$SERVERROOT)));
$scriptName=$_SERVER["SCRIPT_NAME"];
if(substr($scriptName,-1)=='/'){
$scriptName.='index.php';
@@ -428,15 +428,8 @@ class OC{
//make sure temporary files are cleaned up
register_shutdown_function(array('OC_Helper','cleanTmp'));
- if (OC_Config::getValue('installed', false)) {
- if (!OC_AppConfig::getValue('core', 'remote_core.css', false)) {
- OC_AppConfig::setValue('core', 'remote_core.css', '/core/minimizer.php');
- OC_AppConfig::setValue('core', 'remote_core.js', '/core/minimizer.php');
- }
- }
-
//parse the given parameters
- self::$REQUESTEDAPP = (isset($_GET['app'])?str_replace(array('\0', '/', '\\', '..'), '', strip_tags($_GET['app'])):OC_Config::getValue('defaultapp', 'files'));
+ self::$REQUESTEDAPP = (isset($_GET['app']) && trim($_GET['app']) != '' && !is_null($_GET['app'])?str_replace(array('\0', '/', '\\', '..'), '', strip_tags($_GET['app'])):OC_Config::getValue('defaultapp', 'files'));
if(substr_count(self::$REQUESTEDAPP, '?') != 0){
$app = substr(self::$REQUESTEDAPP, 0, strpos(self::$REQUESTEDAPP, '?'));
$param = substr(self::$REQUESTEDAPP, strpos(self::$REQUESTEDAPP, '?') + 1);
diff --git a/lib/config.php b/lib/config.php
index e3a9c11f247..9279549b1bb 100644
--- a/lib/config.php
+++ b/lib/config.php
@@ -170,14 +170,18 @@ class OC_Config{
}
$content .= ");\n?>\n";
+ $filename = OC::$SERVERROOT."/config/config.php";
// Write the file
- $result=@file_put_contents( OC::$SERVERROOT."/config/config.php", $content );
+ $result=@file_put_contents( $filename, $content );
if(!$result) {
$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;
}
+ // Prevent others not to read the config
+ @chmod($filename, 0640);
+
return true;
}
}
diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php
index f2efe0a5ac1..3ba1b3355f2 100644
--- a/lib/connector/sabre/file.php
+++ b/lib/connector/sabre/file.php
@@ -63,8 +63,8 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
* @return int
*/
public function getSize() {
-
- return OC_Filesystem::filesize($this->path);
+ $this->stat();
+ return $this->stat_cache['size'];
}
diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php
index a7d1de8b953..e7bcea3171d 100644
--- a/lib/connector/sabre/node.php
+++ b/lib/connector/sabre/node.php
@@ -29,6 +29,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @var string
*/
protected $path;
+ /**
+ * file stat cache
+ * @var array
+ */
+ protected $stat_cache;
/**
* Sets up the node, expects a full path name
@@ -77,7 +82,14 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
}
-
+ /**
+ * Set the stat cache
+ */
+ protected function stat() {
+ if (!isset($this->stat_cache)) {
+ $this->stat_cache = OC_Filesystem::stat($this->path);
+ }
+ }
/**
* Returns the last modification time, as a unix timestamp
@@ -85,8 +97,8 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @return int
*/
public function getLastModified() {
-
- return OC_Filesystem::filemtime($this->path);
+ $this->stat();
+ return $this->stat_cache['mtime'];
}
@@ -137,7 +149,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
/**
* Returns a list of properties for this nodes.;
*
- * The properties list is a list of propertynames the client requested, encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author
+ * 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
@@ -153,11 +167,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
$existing[$row['propertyname']] = $row['propertyvalue'];
}
+ // if the array was empty, we need to return everything
if(count($properties) == 0){
return $existing;
}
- // if the array was empty, we need to return everything
$props = array();
foreach($properties as $property) {
if (isset($existing[$property])) $props[$property] = $existing[$property];
diff --git a/lib/fileproxy.php b/lib/fileproxy.php
index 70db9cca23c..82c9298788c 100644
--- a/lib/fileproxy.php
+++ b/lib/fileproxy.php
@@ -27,14 +27,17 @@
* Manipulation happens by using 2 kind of proxy operations, pre and post proxies
* that manipulate the filesystem call and the result of the call respectively
*
- * A pre-proxy recieves the filepath as arugments (or 2 filespaths in case of operations like copy or move) and return a boolean
- * If a pre-proxy returnes false the file operation will be canceled
+ * A pre-proxy recieves the filepath as arugments (or 2 filespaths in case of
+ * operations like copy or move) and return a boolean
+ * If a pre-proxy returns false the file operation will be canceled
* All filesystem operations have a pre-proxy
*
* A post-proxy recieves 2 arguments, the filepath and the result of the operation.
- * The return calue of the post-proxy will be used as the new result of the operation
- * The operations that have a post-proxy are
- * file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, fileatime, filemtime, filectime, file_get_contents, getMimeType, hash, fopen, free_space and search
+ * The return value of the post-proxy will be used as the new result of the operation
+ * The operations that have a post-proxy are:
+ * file_get_contents, is_file, is_dir, file_exists, stat, is_readable,
+ * is_writable, fileatime, filemtime, filectime, file_get_contents,
+ * getMimeType, hash, fopen, free_space and search
*/
class OC_FileProxy{
@@ -42,16 +45,7 @@ class OC_FileProxy{
public static $enabled=true;
/**
- * check if this proxy implments a specific proxy operation
- * @param string #proxy name of the proxy operation
- * @return bool
- */
- public function provides($operation){
- return method_exists($this,$operation);
- }
-
- /**
- * fallback function when a proxy operation is not implement
+ * fallback function when a proxy operation is not implemented
* @param string $function the name of the proxy operation
* @param mixed
*
@@ -73,11 +67,10 @@ class OC_FileProxy{
self::$proxies[]=$proxy;
}
- public static function getProxies($operation,$post){
- $operation=(($post)?'post':'pre').$operation;
+ public static function getProxies($operation){
$proxies=array();
foreach(self::$proxies as $proxy){
- if($proxy->provides($operation)){
+ if(method_exists($proxy,$operation)){
$proxies[]=$proxy;
}
}
@@ -88,8 +81,8 @@ class OC_FileProxy{
if(!self::$enabled){
return true;
}
- $proxies=self::getProxies($operation,false);
$operation='pre'.$operation;
+ $proxies=self::getProxies($operation);
foreach($proxies as $proxy){
if(!is_null($filepath2)){
if($proxy->$operation($filepath,$filepath2)===false){
@@ -108,8 +101,8 @@ class OC_FileProxy{
if(!self::$enabled){
return $result;
}
- $proxies=self::getProxies($operation,true);
$operation='post'.$operation;
+ $proxies=self::getProxies($operation);
foreach($proxies as $proxy){
$result=$proxy->$operation($path,$result);
}
diff --git a/lib/filesystem.php b/lib/filesystem.php
index 84d45f5f24b..28bd7d52900 100644
--- a/lib/filesystem.php
+++ b/lib/filesystem.php
@@ -150,7 +150,7 @@ class OC_Filesystem{
if(!$path){
$path='/';
}
- if(substr($path,0,1)!=='/'){
+ if($path[0]!=='/'){
$path='/'.$path;
}
$foundMountPoint='';
@@ -281,7 +281,7 @@ class OC_Filesystem{
}
/**
- * change the root to a fake toor
+ * change the root to a fake root
* @param string fakeRoot
* @return bool
*/
@@ -313,11 +313,14 @@ class OC_Filesystem{
* @param string mountpoint
*/
static public function mount($class,$arguments,$mountpoint){
+ if($mountpoint[0]!='/'){
+ $mountpoint='/'.$mountpoint;
+ }
if(substr($mountpoint,-1)!=='/'){
$mountpoint=$mountpoint.'/';
}
- if(substr($mountpoint,0,1)!=='/'){
- $mountpoint='/'.$mountpoint;
+ if (self::getView() != null && $mountpoint != '/' && !self::is_dir(basename($mountpoint))) {
+ self::mkdir(basename($mountpoint));
}
self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments);
}
@@ -344,12 +347,26 @@ class OC_Filesystem{
}
/**
+ * return path to file which reflects one visible in browser
+ * @param string path
+ * @return string
+ */
+ static public function getLocalPath($path) {
+ $datadir = \OCP\Config::getSystemValue('datadirectory').'/'.\OC_User::getUser().'/files';
+ $newpath = $path;
+ if (strncmp($newpath, $datadir, strlen($datadir)) == 0) {
+ $newpath = substr($path, strlen($datadir));
+ }
+ return $newpath;
+ }
+
+ /**
* check if the requested path is valid
* @param string path
* @return bool
*/
static public function isValidPath($path){
- if(substr($path,0,1)!=='/'){
+ if(!$path || $path[0]!=='/'){
$path='/'.$path;
}
if(strstr($path,'/../') || strrchr($path, '/') === '/..' ){
diff --git a/lib/filesystemview.php b/lib/filesystemview.php
index c8df59cf827..58657671b98 100644
--- a/lib/filesystemview.php
+++ b/lib/filesystemview.php
@@ -40,6 +40,8 @@
class OC_FilesystemView {
private $fakeRoot='';
+ private $internal_path_cache=array();
+ private $storage_cache=array();
public function __construct($root){
$this->fakeRoot=$root;
@@ -49,7 +51,7 @@ class OC_FilesystemView {
if(!$path){
$path='/';
}
- if(substr($path,0,1)!=='/'){
+ if($path[0]!=='/'){
$path='/'.$path;
}
return $this->fakeRoot.$path;
@@ -84,15 +86,38 @@ class OC_FilesystemView {
* @return bool
*/
public function getInternalPath($path){
- return OC_Filesystem::getInternalPath($this->getAbsolutePath($path));
+ if (!isset($this->internal_path_cache[$path])) {
+ $this->internal_path_cache[$path] = OC_Filesystem::getInternalPath($this->getAbsolutePath($path));
+ }
+ return $this->internal_path_cache[$path];
+ }
+
+ /**
+ * get path relative to the root of the view
+ * @param string path
+ * @return string
+ */
+ public function getRelativePath($path){
+ if($this->fakeRoot==''){
+ return $path;
+ }
+ if(strpos($path,$this->fakeRoot)!==0){
+ return null;
+ }else{
+ return substr($path,strlen($this->fakeRoot));
+ }
}
+
/**
* get the storage object for a path
* @param string path
* @return OC_Filestorage
*/
public function getStorage($path){
- return OC_Filesystem::getStorage($this->getAbsolutePath($path));
+ if (!isset($this->storage_cache[$path])) {
+ $this->storage_cache[$path] = OC_Filesystem::getStorage($this->getAbsolutePath($path));
+ }
+ return $this->storage_cache[$path];
}
/**
@@ -224,7 +249,14 @@ class OC_FilesystemView {
return $this->basicOperation('unlink',$path,array('delete'));
}
public function rename($path1,$path2){
- if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and OC_Filesystem::isValidPath($path2)){
+ $absolutePath1=$this->getAbsolutePath($path1);
+ $absolutePath2=$this->getAbsolutePath($path2);
+ if(OC_FileProxy::runPreProxies('rename',$absolutePath1,$absolutePath2) and OC_Filesystem::isValidPath($path2)){
+ $path1=$this->getRelativePath($absolutePath1);
+ $path2=$this->getRelativePath($absolutePath2);
+ if($path1==null or $path2==null){
+ return false;
+ }
$run=true;
OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run));
if($run){
@@ -248,7 +280,14 @@ class OC_FilesystemView {
}
}
public function copy($path1,$path2){
- if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and $this->is_readable($path1) and OC_Filesystem::isValidPath($path2)){
+ $absolutePath1=$this->getAbsolutePath($path1);
+ $absolutePath2=$this->getAbsolutePath($path2);
+ if(OC_FileProxy::runPreProxies('copy',$absolutePath1,$absolutePath2) and OC_Filesystem::isValidPath($path2)){
+ $path1=$this->getRelativePath($absolutePath1);
+ $path2=$this->getRelativePath($absolutePath2);
+ if($path1==null or $path2==null){
+ return false;
+ }
$run=true;
OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run));
$exists=$this->file_exists($path2);
@@ -367,7 +406,12 @@ class OC_FilesystemView {
* OC_Filestorage for delegation to a storage backend for execution
*/
private function basicOperation($operation,$path,$hooks=array(),$extraParam=null){
- if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and OC_Filesystem::isValidPath($path)){
+ $absolutePath=$this->getAbsolutePath($path);
+ if(OC_FileProxy::runPreProxies($operation,$absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)){
+ $path=$this->getRelativePath($absolutePath);
+ if($path==null){
+ return false;
+ }
$internalPath=$this->getInternalPath($path);
$run=true;
if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()){
@@ -385,7 +429,7 @@ class OC_FilesystemView {
}else{
$result=$storage->$operation($internalPath);
}
- $result=OC_FileProxy::runPostProxies($operation,$path,$result);
+ $result=OC_FileProxy::runPostProxies($operation,$this->getAbsolutePath($path),$result);
if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()){
if($operation!='fopen'){//no post hooks for fopen, the file stream is still open
foreach($hooks as $hook){
diff --git a/lib/helper.php b/lib/helper.php
index 3cf5107eea9..73d4b659a34 100644
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -90,12 +90,12 @@ class OC_Helper {
}
- /**
- * @brief Returns the server protocol
- * @returns the server protocol
- *
- * Returns the server protocol. It respects reverse proxy servers and load balancers
- */
+ /**
+ * @brief Returns the server protocol
+ * @returns the server protocol
+ *
+ * Returns the server protocol. It respects reverse proxy servers and load balancers
+ */
public static function serverProtocol() {
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$proto = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']);
@@ -132,7 +132,7 @@ class OC_Helper {
* Returns a absolute url to the given service.
*/
public static function linkToRemote( $service, $add_slash = true ) {
- return self::linkToAbsolute( '', 'remote.php') . '/' . $service . ($add_slash?'/':'');
+ return self::linkToAbsolute( '', 'remote.php') . '/' . $service . (($add_slash && $service[strlen($service)-1]!='/')?'/':'');
}
/**
@@ -143,7 +143,7 @@ class OC_Helper {
*
* Returns the path to the image.
*/
- public static function imagePath( $app, $image ){
+ public static function imagePath( $app, $image ){
// Read the selected theme from the config file
$theme=OC_Config::getValue( "theme" );
@@ -551,35 +551,35 @@ 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;
- }
+ /**
+ * 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
diff --git a/lib/image.php b/lib/image.php
index af61f9424e9..e5c59bacdc5 100644
--- a/lib/image.php
+++ b/lib/image.php
@@ -407,7 +407,9 @@ class OC_Image {
break;
*/
default:
- $this->resource = imagecreatefromstring(file_get_contents($imagepath));
+
+ // this is mostly file created from encrypted file
+ $this->resource = imagecreatefromstring(\OC_Filesystem::file_get_contents(\OC_Filesystem::getLocalPath($imagepath)));
$itype = IMAGETYPE_PNG;
OC_Log::write('core','OC_Image->loadFromFile, Default', OC_Log::DEBUG);
break;
diff --git a/lib/installer.php b/lib/installer.php
index 299674b29e4..c0903f93d51 100644
--- a/lib/installer.php
+++ b/lib/installer.php
@@ -110,7 +110,7 @@ class OC_Installer{
//try to find it in a subdir
$dh=opendir($extractDir);
while($folder=readdir($dh)){
- if(substr($folder,0,1)!='.' and is_dir($extractDir.'/'.$folder)){
+ if($folder[0]!='.' and is_dir($extractDir.'/'.$folder)){
if(is_file($extractDir.'/'.$folder.'/appinfo/info.xml')){
$extractDir.='/'.$folder;
}
diff --git a/lib/json.php b/lib/json.php
index f3bbe9ac899..dfc0a7b894e 100644
--- a/lib/json.php
+++ b/lib/json.php
@@ -42,6 +42,18 @@ class OC_JSON{
}
/**
+ * @brief Check an ajax get/post call if the request token is valid.
+ * @return json Error msg if not valid.
+ */
+ public static function callCheck(){
+ if( !OC_Util::isCallRegistered()){
+ $l = OC_L10N::get('core');
+ self::error(array( 'data' => array( 'message' => $l->t('Token expired. Please reload page.') )));
+ exit();
+ }
+ }
+
+ /**
* Check if the user is a admin, send json error msg if not
*/
public static function checkAdminUser(){
diff --git a/lib/ocsclient.php b/lib/ocsclient.php
index 33308553be0..2888569ad13 100644
--- a/lib/ocsclient.php
+++ b/lib/ocsclient.php
@@ -35,12 +35,7 @@ class OC_OCSClient{
* This function returns the url of the OCS AppStore server. It´s possible to set it in the config file or it will fallback to the default
*/
private static function getAppStoreURL(){
- $configurl=OC_Config::getValue('appstoreurl', '');
- if($configurl<>'') {
- $url=$configurl;
- }else{
- $url='http://api.apps.owncloud.com/v1';
- }
+ $url = OC_Config::getValue('appstoreurl', 'http://api.apps.owncloud.com/v1');
return($url);
}
@@ -50,12 +45,7 @@ class OC_OCSClient{
* This function returns the url of the OCS knowledge base server. It´s possible to set it in the config file or it will fallback to the default
*/
private static function getKBURL(){
- $configurl=OC_Config::getValue('knowledgebaseurl', '');
- if($configurl<>'') {
- $url=$configurl;
- }else{
- $url='http://api.apps.owncloud.com/v1';
- }
+ $url = OC_Config::getValue('knowledgebaseurl', 'http://api.apps.owncloud.com/v1');
return($url);
}
@@ -95,7 +85,7 @@ class OC_OCSClient{
*
* This function returns a list of all the applications on the OCS server
*/
- public static function getApplications($categories){
+ public static function getApplications($categories,$page){
if(OC_Config::getValue('appstoreenabled', true)==false){
return(array());
}
@@ -105,7 +95,7 @@ class OC_OCSClient{
}else{
$categoriesstring=$categories;
}
- $url=OC_OCSClient::getAppStoreURL().'/content/data?categories='.urlencode($categoriesstring).'&sortmode=new&page=0&pagesize=10';
+ $url=OC_OCSClient::getAppStoreURL().'/content/data?categories='.urlencode($categoriesstring).'&sortmode=new&page='.urlencode($page).'&pagesize=100';
$apps=array();
$xml=@file_get_contents($url);
if($xml==FALSE){
diff --git a/lib/public/json.php b/lib/public/json.php
index a8554671d10..b6edbd65bd5 100644
--- a/lib/public/json.php
+++ b/lib/public/json.php
@@ -53,6 +53,13 @@ class JSON {
return(\OC_JSON::checkLoggedIn());
}
+ /**
+ * @brief Check an ajax get/post call if the request token is valid.
+ * @return json Error msg if not valid.
+ */
+ public static function callCheck(){
+ return(\OC_JSON::callCheck());
+ }
/**
* @brief Send json success msg
diff --git a/lib/public/util.php b/lib/public/util.php
index 9b499574da1..d79d3f26b1e 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -145,15 +145,15 @@ class Util {
}
- /**
- * @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 ){
+ /**
+ * @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 ));
}
@@ -248,6 +248,22 @@ class Util {
}
+ /**
+ * Register an get/post call. This is important to prevent CSRF attacks
+ * TODO: write example
+ */
+ public static function callRegister(){
+ return(\OC_Util::callRegister());
+ }
+
+
+ /**
+ * Check an ajax get/post call if the request token is valid. exit if not.
+ * Todo: Write howto
+ */
+ public static function callCheck(){
+ return(\OC_Util::callCheck());
+ }
}
?>
diff --git a/lib/setup.php b/lib/setup.php
index a096fdbb4cf..5f1fb1525ec 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -73,6 +73,10 @@ class OC_Setup {
$dbtype='sqlite3';
}
+ //generate a random salt that is used to salt the local user passwords
+ $salt=mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000);
+ OC_Config::setValue('passwordsalt', $salt);
+
//write the config file
OC_Config::setValue('datadirectory', $datadir);
OC_Config::setValue('dbtype', $dbtype);
diff --git a/lib/template.php b/lib/template.php
index b99d492a536..149859aa8a5 100644
--- a/lib/template.php
+++ b/lib/template.php
@@ -155,6 +155,9 @@ class OC_Template{
$this->renderas = $renderas;
$this->application = $app;
$this->vars = array();
+ if($renderas == 'user') {
+ $this->vars['requesttoken'] = OC_Util::callRegister();
+ }
$this->l10n = OC_L10N::get($app);
header('X-Frame-Options: Sameorigin');
header('X-XSS-Protection: 1; mode=block');
@@ -259,6 +262,7 @@ class OC_Template{
* @brief Assign variables
* @param $key key
* @param $value value
+ * @param $sanitizeHTML false, if data shouldn't get passed through htmlentities
* @returns true
*
* This function assigns a variable. It can be accessed via $_[$key] in
@@ -266,11 +270,29 @@ class OC_Template{
*
* If the key existed before, it will be overwritten
*/
- public function assign( $key, $value ){
+ public function assign( $key, $value, $sanitizeHTML=true ){
+ if($sanitizeHTML == true) {
+ if(is_array($value)) {
+ array_walk_recursive($value,'OC_Template::sanitizeHTML');
+ } else {
+ $value = OC_Template::sanitizeHTML($value);
+ }
+ }
$this->vars[$key] = $value;
return true;
}
+
+ /**
+ * @brief Internaly used to sanitze HTML
+ *
+ * This function is internally used to sanitize HTML.
+ */
+ private static function sanitizeHTML( &$value ){
+ $value = htmlentities( $value );
+ return $value;
+ }
+
/**
* @brief Appends a variable
* @param $key key
@@ -363,20 +385,21 @@ class OC_Template{
// Decide which page we show
if( $this->renderas == "user" ){
$page = new OC_Template( "core", "layout.user" );
- $page->assign('searchurl',OC_Helper::linkTo( 'search', 'index.php' ));
+ $page->assign('searchurl',OC_Helper::linkTo( 'search', 'index.php' ), false);
+ $page->assign('requesttoken', $this->vars['requesttoken']);
if(array_search(OC_APP::getCurrentApp(),array('settings','admin','help'))!==false){
- $page->assign('bodyid','body-settings');
+ $page->assign('bodyid','body-settings', false);
}else{
- $page->assign('bodyid','body-user');
+ $page->assign('bodyid','body-user', false);
}
// Add navigation entry
$navigation = OC_App::getNavigation();
- $page->assign( "navigation", $navigation);
- $page->assign( "settingsnavigation", OC_App::getSettingsNavigation());
+ $page->assign( "navigation", $navigation, false);
+ $page->assign( "settingsnavigation", OC_App::getSettingsNavigation(), false);
foreach($navigation as $entry) {
if ($entry['active']) {
- $page->assign( 'application', $entry['name'] );
+ $page->assign( 'application', $entry['name'], false );
break;
}
}
@@ -387,7 +410,7 @@ class OC_Template{
foreach(OC_App::getEnabledApps() as $app){
$apps_paths[$app] = OC_App::getAppWebPath($app);
}
- $page->assign( 'apps_paths', str_replace('\\/', '/',json_encode($apps_paths)) ); // Ugly unescape slashes waiting for better solution
+ $page->assign( 'apps_paths', str_replace('\\/', '/',json_encode($apps_paths)) , false); // Ugly unescape slashes waiting for better solution
// Read the selected theme from the config file
$theme=OC_Config::getValue( "theme" );
@@ -395,7 +418,7 @@ class OC_Template{
// Read the detected formfactor and use the right file name.
$fext = self::getFormFactorExtension();
- $page->assign('jsfiles', array());
+ $page->assign('jsfiles', array(), false);
// Add the core js files or the js files provided by the selected theme
foreach(OC_Util::$scripts as $script){
// Is it in 3rd party?
@@ -479,13 +502,13 @@ class OC_Template{
}
// Add custom headers
- $page->assign('headers',$this->headers);
+ $page->assign('headers',$this->headers, false);
foreach(OC_Util::$headers as $header){
$page->append('headers',$header);
}
// Add css files and js files
- $page->assign( "content", $data );
+ $page->assign( "content", $data, false );
return $page->fetchPage();
}
else{
@@ -530,13 +553,13 @@ class OC_Template{
$_ = array_merge( $additionalparams, $this->vars );
}
- // Einbinden
+ // Include
ob_start();
include( $this->path.$file.'.php' );
$data = ob_get_contents();
@ob_end_clean();
- // Daten zurückgeben
+ // Return data
return $data;
}
@@ -550,7 +573,7 @@ class OC_Template{
public static function printUserPage( $application, $name, $parameters = array() ){
$content = new OC_Template( $application, $name, "user" );
foreach( $parameters as $key => $value ){
- $content->assign( $key, $value );
+ $content->assign( $key, $value, false );
}
print $content->printPage();
}
@@ -565,7 +588,7 @@ class OC_Template{
public static function printAdminPage( $application, $name, $parameters = array() ){
$content = new OC_Template( $application, $name, "admin" );
foreach( $parameters as $key => $value ){
- $content->assign( $key, $value );
+ $content->assign( $key, $value, false );
}
return $content->printPage();
}
@@ -580,7 +603,7 @@ class OC_Template{
public static function printGuestPage( $application, $name, $parameters = array() ){
$content = new OC_Template( $application, $name, "guest" );
foreach( $parameters as $key => $value ){
- $content->assign( $key, $value );
+ $content->assign( $key, $value,false );
}
return $content->printPage();
}
diff --git a/lib/updater.php b/lib/updater.php
index bc5ee00b6a3..5d97178c30e 100644
--- a/lib/updater.php
+++ b/lib/updater.php
@@ -30,11 +30,12 @@ class OC_Updater{
*/
public static function check(){
OC_Appconfig::setValue('core', 'lastupdatedat',microtime(true));
+ if(OC_Appconfig::getValue('core', 'installedat','')=='') OC_Appconfig::setValue('core', 'installedat',microtime(true));
$updaterurl='http://apps.owncloud.com/updater.php';
$version=OC_Util::getVersion();
- $version['installed']=OC_Config::getValue('installedat');
- $version['updated']=OC_Appconfig::getValue('core', 'lastupdatedat', OC_Config::getValue( 'lastupdatedat'));
+ $version['installed']=OC_Appconfig::getValue('core', 'installedat');
+ $version['updated']=OC_Appconfig::getValue('core', 'lastupdatedat');
$version['updatechannel']='stable';
$version['edition']=OC_Util::getEditionString();
$versionstring=implode('x',$version);
@@ -57,11 +58,15 @@ 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. Get <a href="'.$data['web'].'">more information</a></span>';
+ if(OC_Config::getValue('updatechecker', true)==true){
+ $data=OC_Updater::check();
+ if(isset($data['version']) and $data['version']<>'') {
+ $txt='<span style="color:#AA0000; font-weight:bold;">'.$data['versionstring'].' is available. Get <a href="'.$data['web'].'">more information</a></span>';
+ }else{
+ $txt='up to date';
+ }
}else{
- $txt='up to date';
+ $txt='updates check is disabled';
}
return($txt);
}
diff --git a/lib/user/database.php b/lib/user/database.php
index 769ba6a7920..a48b8357d64 100644
--- a/lib/user/database.php
+++ b/lib/user/database.php
@@ -69,7 +69,7 @@ class OC_User_Database extends OC_User_Backend {
return false;
}else{
$hasher=$this->getHasher();
- $hash = $hasher->HashPassword($password);
+ $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', ''));
$query = OC_DB::prepare( "INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )" );
$result = $query->execute( array( $uid, $hash));
@@ -102,7 +102,7 @@ class OC_User_Database extends OC_User_Backend {
public function setPassword( $uid, $password ){
if( $this->userExists($uid) ){
$hasher=$this->getHasher();
- $hash = $hasher->HashPassword($password);
+ $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', ''));
$query = OC_DB::prepare( "UPDATE *PREFIX*users SET password = ? WHERE uid = ?" );
$result = $query->execute( array( $hash, $uid ));
@@ -129,9 +129,9 @@ class OC_User_Database extends OC_User_Backend {
$row=$result->fetchRow();
if($row){
$storedHash=$row['password'];
- if (substr($storedHash,0,1)=='$'){//the new phpass based hashing
+ if ($storedHash[0]=='$'){//the new phpass based hashing
$hasher=$this->getHasher();
- if($hasher->CheckPassword($password, $storedHash)){
+ if($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $storedHash)){
return $row['uid'];
}else{
return false;
diff --git a/lib/util.php b/lib/util.php
index b344d576ebf..cedbe3fa460 100644..100755
--- a/lib/util.php
+++ b/lib/util.php
@@ -72,6 +72,15 @@ class OC_Util {
$quotaProxy=new OC_FileProxy_Quota();
OC_FileProxy::register($quotaProxy);
self::$fsSetup=true;
+ // Load personal mount config
+ if (is_file($CONFIG_DATADIRECTORY_ROOT.'/'.$user.'/mount.php')) {
+ $mountConfig = include($CONFIG_DATADIRECTORY_ROOT.'/'.$user.'/mount.php');
+ if (isset($mountConfig['user'][$user])) {
+ foreach ($mountConfig['user'][$user] as $mountPoint => $options) {
+ OC_Filesystem::mount($options['class'], $options['options'], $mountPoint);
+ }
+ }
+ }
}
}
@@ -85,7 +94,7 @@ class OC_Util {
* @return array
*/
public static function getVersion(){
- return array(4,80,0);
+ return array(4,80,1);
}
/**
@@ -325,7 +334,8 @@ class OC_Util {
* Redirect to the user default page
*/
public static function redirectToDefaultPage(){
- if(isset($_REQUEST['redirect_url']) && substr($_REQUEST['redirect_url'], 0, strlen(OC::$WEBROOT)) == OC::$WEBROOT) {
+ OC_Log::write('core','redirectToDefaultPage',OC_Log::DEBUG);
+ if(isset($_REQUEST['redirect_url']) && (substr($_REQUEST['redirect_url'], 0, strlen(OC::$WEBROOT)) == OC::$WEBROOT || $_REQUEST['redirect_url'][0] == '/')) {
header( 'Location: '.$_REQUEST['redirect_url']);
} else {
header( 'Location: '.OC::$WEBROOT.'/'.OC_Appconfig::getValue('core', 'defaultpage', '?app=files'));
@@ -345,4 +355,77 @@ class OC_Util {
}
return $id;
}
+
+ /**
+ * @brief Register an get/post call. This is important to prevent CSRF attacks
+ * Todo: Write howto
+ * @return $token Generated token.
+ */
+ public static function callRegister(){
+ //mamimum time before token exires
+ $maxtime=(60*60); // 1 hour
+
+ // generate a random token.
+ $token=mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000);
+
+ // store the token together with a timestamp in the session.
+ $_SESSION['requesttoken-'.$token]=time();
+
+ // cleanup old tokens garbage collector
+ // only run every 20th time so we dont waste cpu cycles
+ if(rand(0,20)==0) {
+ foreach($_SESSION as $key=>$value) {
+ // search all tokens in the session
+ if(substr($key,0,12)=='requesttoken') {
+ if($value+$maxtime<time()){
+ // remove outdated tokens
+ unset($_SESSION[$key]);
+ }
+ }
+ }
+ }
+ // return the token
+ return($token);
+ }
+
+
+ /**
+ * @brief Check an ajax get/post call if the request token is valid.
+ * @return boolean False if request token is not set or is invalid.
+ */
+ public static function isCallRegistered(){
+ //mamimum time before token exires
+ $maxtime=(60*60); // 1 hour
+ if(isset($_GET['requesttoken'])) {
+ $token=$_GET['requesttoken'];
+ }elseif(isset($_POST['requesttoken'])){
+ $token=$_POST['requesttoken'];
+ }elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])){
+ $token=$_SERVER['HTTP_REQUESTTOKEN'];
+ }else{
+ //no token found.
+ return false;
+ }
+ if(isset($_SESSION['requesttoken-'.$token])) {
+ $timestamp=$_SESSION['requesttoken-'.$token];
+ if($timestamp+$maxtime<time()){
+ return false;
+ }else{
+ //token valid
+ return true;
+ }
+ }else{
+ return false;
+ }
+ }
+
+ /**
+ * @brief Check an ajax get/post call if the request token is valid. exit if not.
+ * Todo: Write howto
+ */
+ public static function callCheck(){
+ if(!OC_Util::isCallRegistered()) {
+ exit;
+ }
+ }
}
diff --git a/lib/vcategories.php b/lib/vcategories.php
index ddcec1b6a4e..1e79b62f0d6 100644
--- a/lib/vcategories.php
+++ b/lib/vcategories.php
@@ -63,7 +63,7 @@ class OC_VCategories {
* @returns array containing the categories as strings.
*/
public function categories() {
- OC_Log::write('core','OC_VCategories::categories: '.print_r($this->categories, true), OC_Log::DEBUG);
+ //OC_Log::write('core','OC_VCategories::categories: '.print_r($this->categories, true), OC_Log::DEBUG);
usort($this->categories, 'strnatcasecmp'); // usort to also renumber the keys
return $this->categories;
}
@@ -169,7 +169,7 @@ class OC_VCategories {
foreach($names as $name) {
OC_Log::write('core','OC_VCategories::delete: '.$name, OC_Log::DEBUG);
if($this->hasCategory($name)) {
- OC_Log::write('core','OC_VCategories::delete: '.$name.' got it', OC_Log::DEBUG);
+ //OC_Log::write('core','OC_VCategories::delete: '.$name.' got it', OC_Log::DEBUG);
unset($this->categories[$this->array_searchi($name, $this->categories)]);
}
}
@@ -183,14 +183,14 @@ class OC_VCategories {
//OC_Log::write('core','OC_VCategories::delete, before: '.$key.': '.print_r($categories, true), OC_Log::DEBUG);
foreach($names as $name) {
$idx = $this->array_searchi($name, $categories);
- OC_Log::write('core','OC_VCategories::delete, loop: '.$name.', '.print_r($idx, true), OC_Log::DEBUG);
+ //OC_Log::write('core','OC_VCategories::delete, loop: '.$name.', '.print_r($idx, true), OC_Log::DEBUG);
if($idx !== false) {
OC_Log::write('core','OC_VCategories::delete, unsetting: '.$categories[$this->array_searchi($name, $categories)], OC_Log::DEBUG);
unset($categories[$this->array_searchi($name, $categories)]);
//unset($categories[$idx]);
}
}
- OC_Log::write('core','OC_VCategories::delete, after: '.$key.': '.print_r($categories, true), OC_Log::DEBUG);
+ //OC_Log::write('core','OC_VCategories::delete, after: '.$key.': '.print_r($categories, true), OC_Log::DEBUG);
$vobject->setString('CATEGORIES', implode(',', $categories));
$value[1] = $vobject->serialize();
$objects[$key] = $value;
diff --git a/remote.php b/remote.php
index e1e11c5773f..9fb73c4ce1d 100644
--- a/remote.php
+++ b/remote.php
@@ -7,13 +7,17 @@ if (array_key_exists('PATH_INFO', $_SERVER)){
}else{
$path_info = substr($_SERVER['PHP_SELF'], strpos($_SERVER['PHP_SELF'], basename(__FILE__)) + strlen(basename(__FILE__)));
}
+if ($path_info === false) {
+ OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
+ exit;
+}
if (!$pos = strpos($path_info, '/', 1)) {
$pos = strlen($path_info);
}
$service=substr($path_info, 1, $pos-1);
$file = OC_AppConfig::getValue('core', 'remote_' . $service);
if(is_null($file)){
- header('HTTP/1.0 404 Not Found');
+ OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
exit;
}
@@ -23,7 +27,6 @@ if(count(explode('/',$file)) == 3) {
OC_App::loadApp($app);
$baseuri = OC::$WEBROOT . '/remote.php/'.$service.'/';
require_once( OC::$SERVERROOT.$file);
-
} else {
$parts=explode('/', $file, 2);
$app=$parts[0];
diff --git a/settings/admin.php b/settings/admin.php
index a997bad4e3c..4cbd67c3678 100644
--- a/settings/admin.php
+++ b/settings/admin.php
@@ -23,7 +23,7 @@ function compareEntries($a,$b){
usort($entries, 'compareEntries');
$tmpl->assign('loglevel',OC_Config::getValue( "loglevel", 2 ));
-$tmpl->assign('entries',$entries);
+$tmpl->assign('entries',$entries,false);
$tmpl->assign('forms',array());
foreach($forms as $form){
$tmpl->append('forms',$form);
diff --git a/settings/apps.php b/settings/apps.php
index 1a829d371a6..f85b28158f5 100644
--- a/settings/apps.php
+++ b/settings/apps.php
@@ -63,7 +63,8 @@ usort($apps, 'app_sort');
$catagoryNames=OC_OCSClient::getCategories();
if(is_array($catagoryNames)){
$categories=array_keys($catagoryNames);
- $externalApps=OC_OCSClient::getApplications($categories);
+ $page=0;
+ $externalApps=OC_OCSClient::getApplications($categories,$page);
foreach($externalApps as $app){
// show only external apps that are not exist yet
$local=false;
@@ -91,7 +92,7 @@ usort($apps, 'app_sort');
$tmpl = new OC_Template( "settings", "apps", "user" );
-$tmpl->assign('apps',$apps);
+$tmpl->assign('apps',$apps, false);
$tmpl->printPage();
diff --git a/settings/css/settings.css b/settings/css/settings.css
index b5a3c0f03b7..df1e3cfd3c2 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -34,9 +34,10 @@ li.selected { background-color:#ddd; }
#content>table:not(.nostyle) { margin-top:3em; }
table:not(.nostyle) { width:100%; }
#rightcontent { padding-left: 1em; }
-td.quota { position:absolute; }
div.quota { float:right; display:block; position:absolute; right:25em; top:0; }
+div.quota-select-wrapper { position: relative; }
select.quota { position:absolute; left:0; top:0; width:10em; }
+select.quota-user { position:relative; left:0; top:0; width:10em; }
input.quota-other { display:none; position:absolute; left:0.1em; top:0.1em; width:7em; border:none; -webkit-box-shadow: none -mox-box-shadow:none ; box-shadow:none; }
div.quota>span { position:absolute; right:0em; white-space:nowrap; top: 0.7em }
select.quota.active { background: #fff; }
diff --git a/settings/js/users.js b/settings/js/users.js
index 7c3c3d37b18..f173357749e 100644
--- a/settings/js/users.js
+++ b/settings/js/users.js
@@ -95,9 +95,9 @@ $(document).ready(function(){
$(this).children('img').click();
});
- $('select.quota').live('change',function(){
+ $('select.quota, select.quota-user').live('change',function(){
var select=$(this);
- var uid=$(this).parent().parent().data('uid');
+ var uid=$(this).parent().parent().parent().data('uid');
var quota=$(this).val();
var other=$(this).next();
if(quota!='other'){
@@ -110,7 +110,7 @@ $(document).ready(function(){
other.focus();
}
});
- $('select.quota').each(function(i,select){
+ $('select.quota, select.quota-user').each(function(i,select){
$(select).data('previous',$(select).val());
})
@@ -207,9 +207,9 @@ $(document).ready(function(){
applyMultiplySelect(select);
$('#content table tbody').last().append(tr);
- tr.find('select.quota option').attr('selected',null);
- tr.find('select.quota option').first().attr('selected','selected');
- tr.find('select.quota').data('previous','default');
+ tr.find('select.quota-user option').attr('selected',null);
+ tr.find('select.quota-user option').first().attr('selected','selected');
+ tr.find('select.quota-user').data('previous','default');
}
}
);
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index d167f2780ef..38c6042c82a 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -29,7 +29,7 @@ $levels=array('Debug','Info','Warning','Error','Fatal');
<?php echo $entry->app;?>
</td>
<td>
- <?php echo htmlentities($entry->message);?>
+ <?php echo $entry->message;?>
</td>
<td>
<?php echo OC_Util::formatDate($entry->time);?>
diff --git a/settings/templates/help.php b/settings/templates/help.php
index cf61207e601..a53ec76d681 100644
--- a/settings/templates/help.php
+++ b/settings/templates/help.php
@@ -26,9 +26,9 @@
<?php foreach($_["kbe"] as $kb): ?>
<div class="helpblock">
<?php if($kb["preview1"] <> "") { echo('<img class="preview" src="'.$kb["preview1"].'" />'); } ?>
- <?php if($kb['detailpage']<>'') echo('<p><a target="_blank" href="'.$kb['detailpage'].'"><strong>'.htmlentities($kb["name"]).'</strong></a></p>');?>
- <p><?php echo htmlentities($kb['description']);?></p>
- <?php if($kb['answer']<>'') echo('<p><strong>'.$l->t('Answer').':</strong><p>'.htmlentities($kb['answer']).'</p>');?>
+ <?php if($kb['detailpage']<>'') echo('<p><a target="_blank" href="'.$kb['detailpage'].'"><strong>'.$kb["name"].'</strong></a></p>');?>
+ <p><?php echo $kb['description'];?></p>
+ <?php if($kb['answer']<>'') echo('<p><strong>'.$l->t('Answer').':</strong><p>'.$kb['answer'].'</p>');?>
</div>
<?php endforeach;
endif?>
diff --git a/settings/templates/users.php b/settings/templates/users.php
index a23a5bafe61..ea3fe777ffe 100644
--- a/settings/templates/users.php
+++ b/settings/templates/users.php
@@ -12,29 +12,43 @@ foreach($_["groups"] as $group) {
<div id="controls">
<form id="newuser">
- <input id="newusername" placeholder="<?php echo $l->t('Name')?>" />
- <input type="password" id="newuserpassword" placeholder="<?php echo $l->t('Password')?>" />
- <select id="newusergroups" data-placeholder="groups" title="<?php echo $l->t('Groups')?>" multiple="multiple">
- <?php foreach($_["groups"] as $group): ?>
- <option value="<?php echo $group['name'];?>"><?php echo $group['name'];?></option>
- <?php endforeach;?>
- </select>
- <input type="submit" value="<?php echo $l->t('Create')?>" />
+ <input id="newusername" placeholder="<?php echo $l->t('Name')?>" /> <input
+ type="password" id="newuserpassword"
+ placeholder="<?php echo $l->t('Password')?>" /> <select
+ id="newusergroups" data-placeholder="groups"
+ title="<?php echo $l->t('Groups')?>" multiple="multiple">
+ <?php foreach($_["groups"] as $group): ?>
+ <option value="<?php echo $group['name'];?>">
+ <?php echo $group['name'];?>
+ </option>
+ <?php endforeach;?>
+ </select> <input type="submit" value="<?php echo $l->t('Create')?>" />
</form>
<div class="quota">
<span><?php echo $l->t('Default Quota');?>:</span>
- <select class='quota'>
- <?php foreach($_['quota_preset'] as $preset):?>
+ <div class="quota-select-wrapper">
+ <select class='quota'>
+ <?php foreach($_['quota_preset'] as $preset):?>
<?php if($preset!='default'):?>
- <option <?php if($_['default_quota']==$preset) echo 'selected="selected"';?> value='<?php echo $preset;?>'><?php echo $preset;?></option>
+ <option
+ <?php if($_['default_quota']==$preset) echo 'selected="selected"';?>
+ value='<?php echo $preset;?>'>
+ <?php echo $preset;?>
+ </option>
<?php endif;?>
- <?php endforeach;?>
- <?php if(array_search($_['default_quota'],$_['quota_preset'])===false):?>
- <option selected="selected" value='<?php echo $_['default_quota'];?>'><?php echo $_['default_quota'];?></option>
- <?php endif;?>
- <option value='other'><?php echo $l->t('Other');?>...</option>
- </select>
- <input class='quota-other'></input>
+ <?php endforeach;?>
+ <?php if(array_search($_['default_quota'],$_['quota_preset'])===false):?>
+ <option selected="selected"
+ value='<?php echo $_['default_quota'];?>'>
+ <?php echo $_['default_quota'];?>
+ </option>
+ <?php endif;?>
+ <option value='other'>
+ <?php echo $l->t('Other');?>
+ ...
+ </option>
+ </select> <input class='quota-other'></input>
+ </div>
</div>
</div>
@@ -49,38 +63,52 @@ foreach($_["groups"] as $group) {
</tr>
</thead>
<tbody>
- <?php foreach($_["users"] as $user): ?>
+ <?php foreach($_["users"] as $user): ?>
<tr data-uid="<?php echo $user["name"] ?>">
<td class="name"><?php echo $user["name"]; ?></td>
- <td class="password">
- <span>●●●●●●●</span>
- <img class="svg action" src="<?php echo image_path('core','actions/rename.svg')?>" alt="set new password" title="set new password" />
+ <td class="password"><span>●●●●●●●</span> <img class="svg action"
+ src="<?php echo image_path('core','actions/rename.svg')?>"
+ alt="set new password" title="set new password" />
</td>
- <td class="groups">
- <select data-username="<?php echo $user['name'] ;?>" data-user-groups="<?php echo $user['groups'] ;?>" data-placeholder="groups" title="<?php echo $l->t('Groups')?>" multiple="multiple">
+ <td class="groups"><select
+ data-username="<?php echo $user['name'] ;?>"
+ data-user-groups="<?php echo $user['groups'] ;?>"
+ data-placeholder="groups" title="<?php echo $l->t('Groups')?>"
+ multiple="multiple">
<?php foreach($_["groups"] as $group): ?>
- <option value="<?php echo $group['name'];?>"><?php echo $group['name'];?></option>
+ <option value="<?php echo $group['name'];?>">
+ <?php echo $group['name'];?>
+ </option>
<?php endforeach;?>
- </select>
+ </select>
</td>
<td class="quota">
- <select class='quota'>
- <?php foreach($_['quota_preset'] as $preset):?>
- <option <?php if($user['quota']==$preset) echo 'selected="selected"';?> value='<?php echo $preset;?>'><?php echo $preset;?></option>
- <?php endforeach;?>
- <?php if(array_search($user['quota'],$_['quota_preset'])===false):?>
- <option selected="selected" value='<?php echo $user['quota'];?>'><?php echo $user['quota'];?></option>
- <?php endif;?>
- <option value='other'><?php echo $l->t('Other');?>...</option>
- </select>
- <input class='quota-other'></input>
+ <div class="quota-select-wrapper">
+ <select class='quota-user'>
+ <?php foreach($_['quota_preset'] as $preset):?>
+ <option
+ <?php if($user['quota']==$preset) echo 'selected="selected"';?>
+ value='<?php echo $preset;?>'>
+ <?php echo $preset;?>
+ </option>
+ <?php endforeach;?>
+ <?php if(array_search($user['quota'],$_['quota_preset'])===false):?>
+ <option selected="selected" value='<?php echo $user['quota'];?>'>
+ <?php echo $user['quota'];?>
+ </option>
+ <?php endif;?>
+ <option value='other'>
+ <?php echo $l->t('Other');?>
+ ...
+ </option>
+ </select> <input class='quota-other'></input>
+ </div>
</td>
- <td class="remove">
- <?php if($user['name']!=OC_User::getUser()):?>
- <img alt="Delete" title="<?php echo $l->t('Delete')?>" class="svg action" src="<?php echo image_path('core','actions/delete.svg') ?>" />
- <?php endif;?>
+ <td class="remove"><?php if($user['name']!=OC_User::getUser()):?> <img
+ alt="Delete" title="<?php echo $l->t('Delete')?>" class="svg action"
+ src="<?php echo image_path('core','actions/delete.svg') ?>" /> <?php endif;?>
</td>
</tr>
- <?php endforeach; ?>
+ <?php endforeach; ?>
</tbody>
</table>
diff --git a/tests/index.php b/tests/index.php
index 9c5178f81a8..691bf2a5d45 100644
--- a/tests/index.php
+++ b/tests/index.php
@@ -47,7 +47,7 @@ function loadTests($dir=''){
}
if($dh=opendir($dir)){
while($name=readdir($dh)){
- if(substr($name,0,1)!='.'){//no hidden files, '.' or '..'
+ if($name[0]!='.'){//no hidden files, '.' or '..'
$file=$dir.'/'.$name;
if(is_dir($file)){
loadTests($file);