diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..57f71e6d --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: kataras diff --git a/.gitignore b/.gitignore index 600d2d33..19980596 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ -.vscode \ No newline at end of file +.DS_STORE +.vscode +/issue-*/ +/feature-*/ +.directory +node_modules +package-lock.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2439779b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: go -os: - - linux - - osx -go: - - tip \ No newline at end of file diff --git a/LICENSE b/LICENSE index c1f4e6b3..8696ebc1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2018 Gerasimos Maropoulos and contributors. +Copyright (c) 2016-2024 Gerasimos Maropoulos and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 652e1af5..533f00d5 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,320 @@ # Examples -<img align="right" width="150px" src="https://iris-go.com/images/logo.svg?v=10"> +<a href="https://iris-go.com"> <img align="right" width="115px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a> -<a href="https://travis-ci.org/iris-contrib/examples"><img src="https://img.shields.io/travis/iris-contrib/examples.svg?style=flat-square" alt="Build Status"></a> -<a href="https://github.com/iris-contrib/examples/blob/master/LICENSE"><img src="https://img.shields.io/badge/%20license-MIT%20%20License%20-E91E63.svg?style=flat-square" alt="License"></a> -<a href="https://github.com/kataras/iris/blob/master/HISTORY.md"><img src="https://img.shields.io/badge/version-10.x%20-blue.svg?style=flat-square" alt="CHANGELOG/HISTORY"></a> +<a href="https://github.com/kataras/iris/actions"><img src="https://img.shields.io/github/actions/workflow/status/iris-contrib/swagger/ci.yml?branch=master&style=flat-square" alt="Build Status"></a> +<a href="https://github.com/iris-contrib/examples/blob/v12/LICENSE"><img src="https://img.shields.io/badge/%20license-MIT%20%20License%20-E91E63.svg?style=flat-square" alt="License"></a> +<a href="https://github.com/kataras/iris/blob/v12/HISTORY.md"><img src="https://img.shields.io/badge/version-v12.2.x%20-blue.svg?style=flat-square" alt="CHANGELOG/HISTORY"></a> -This repository provides easy to understand code snippets on how to get started with web development with the Go programming language using the [Iris](https://github.com/kataras/iris) web framework. +This repository provides easy to understand code snippets on how to get started with web development with the Go programming language using the [Iris](https://github.com/kataras/iris) web framework. This branch contains the latest [iris main examples](github.com/kataras/iris/tree/v12/examples). -It doesn't contain "best ways" neither explains all its features. It's just a simple, practical cookbook for young Gophers! +To read the Iris documentation please navigate to [the documentation](https://iris-go.com/docs) instead. -## Table of Contents +> Examples are tested using Windows 11, Ubuntu 23.04 LTS, macOS 14 Sonoma with [Microsoft's Visual Studio Code](https://code.visualstudio.com/) and built using the [Go 1.22.2](https://go.dev/dl/). -* [Overview](overview) - * [Hello world!](hello-world/main.go) - * [Hello WebAssemply!](https://github.com/kataras/iris/tree/master/_examples/webassemply/basic) **NEW** - * [Glimpse](overview/main.go) - * [Tutorial: Online Visitors](tutorial/online-visitors/main.go) - * [Tutorial: URL Shortener using BoltDB](tutorial/url-shortener/main.go) - * [Tutorial: DropzoneJS + Go: How to build a file upload form](tutorial/dropzonejs/main.go) - * [Tutorial:Iris Go Framework + MongoDB](https://medium.com/go-language/iris-go-framework-mongodb-552e349eab9c) -* [Structuring](structuring) - * [Bootstrapper](structuring/bootstrap/bootstrap/bootstrapper.go) - * [MVC with Repository and Service layer Overview](mvc/overview/main.go) - * [Login (MVC with Single Responsibility package)](structuring/login-mvc-single-responsible-package/main.go) - * [Login (MVC with Datamodels, Datasource, Repository and Service layer)](mvc/login/main.go) -* [HTTP Listening](http-listening) - * [Common, with address](http-listening/listen-addr/main.go) - * [UNIX socket file](http-listening/listen-unix/main.go) - * [TLS](http-listening/listen-tls/main.go) - * [Letsencrypt (Automatic Certifications)](http-listening/listen-letsencrypt/main.go) - * [Custom net.Listener](http-listening/custom-listener/main.go) - * [SO_REUSEPORT for unix systems](http-listening/custom-listener/unix-reuseport/main.go) - * [Omit server errors](http-listening/listen-addr/omit-server-errors/main.go) - * [Custom HTTP Server](http-listening/custom-httpserver/easy-way/main.go) - * [Custom HTTP Server (STD)](http-listening/custom-httpserver/std-way/main.go) - * [Multi HTTP Servers](http-listening/custom-httpserver/multi/main.go) - * [Graceful Shutdown](http-listening/graceful-shutdown/default-notifier/main.go) -* [Configuration](configuration) +# Table of Contents + +* [Serverless](https://github.com/iris-contrib/gateway#netlify) +* [REST API for Apache Kafka](kafka-api) +* [URL Shortener](url-shortener) +* [Dropzone.js](dropzonejs) +* [Caddy](caddy) +* [Bootstrapper](bootstrapper) +* [Project Structure](project) :fire: +* Monitor + * [Simple Process Monitor (includes UI)](monitor/monitor-middleware/main.go) **NEW** + * [Heap, MSpan/MCache, Size Classes, Objects, Goroutines, GC/CPU fraction (includes UI)](monitor/statsviz/main.go) **NEW** +* Database + * [MySQL, Groupcache & Docker](database/mysql) + * [MongoDB](database/mongodb) + * [Sqlx](database/orm/sqlx/main.go) + * [Gorm](database/orm/gorm/main.go) + * [Reform](database/orm/reform/main.go) + * [x/sqlx](database/sqlx/main.go) **NEW** +* GraphQL + * [GraphQL: schema-first](graphql/schema-first) **NEW** +* HTTP Server + * [HOST:PORT](http-server/listen-addr/main.go) + * [Public Test Domain](http-server/listen-addr-public/main.go) + * [UNIX socket file](http-server/listen-unix/main.go) + * [TLS](http-server/listen-tls/main.go) + * [Letsencrypt (Automatic Certifications)](http-server/listen-letsencrypt/main.go) + * [Socket Sharding (SO_REUSEPORT)](http-server/socket-sharding/main.go) + * [Graceful Shutdown](http-server/graceful-shutdown/default-notifier/main.go) + * [Notify on shutdown](http-server/notify-on-shutdown/main.go) + * Custom TCP Listener + * [Common net.Listener](http-server/custom-listener/main.go) + * Custom HTTP Server + * [Pass a custom Server](http-server/custom-httpserver/easy-way/main.go) + * [Use Iris as a single http.Handler](http-server/custom-httpserver/std-way/main.go) + * [Multi Instances](http-server/custom-httpserver/multi/main.go) + * [HTTP/3 Quic](http-server/http3-quic) + * [H2C](http-server/h2c/main.go) **NEW** + * [Timeout](http-server/timeout/main.go) +* HTTP Client + * [Weather Client](http-client/weatherapi) +* Configuration * [Functional](configuration/functional/main.go) - * [From Configuration Struct](configuration/from-configuration-structure/main.go) - * [Import from YAML file](configuration/from-yaml-file/main.go) - * [Share Configuration between multiple instances](configuration/from-yaml-file/shared-configuration/main.go) - * [Import from TOML file](configuration/from-toml-file/main.go) -* [Routing](routing) + * [Configuration Struct](configuration/from-configuration-structure/main.go) + * [Using Viper](configuration/viper) + * [Import from YAML](configuration/from-yaml-file/main.go) + * [Share Configuration across instances](configuration/from-yaml-file/shared-configuration/main.go) + * [Import from TOML](configuration/from-toml-file/main.go) + * [Multi Environment Configuration](configuration/multi-environments) **NEW** +* Routing + * [Custom Context](routing/custom-context/main.go) **HOT/NEW** + * [Party Controller](routing/party-controller) **NEW** * [Overview](routing/overview/main.go) * [Basic](routing/basic/main.go) * [Custom HTTP Errors](routing/http-errors/main.go) + * [HTTP Wire Errors](routing/http-wire-errors/main.go) **NEW** + * [Service and Validation](routing/http-wire-errors/service/main.go) **NEW** + * [Not Found - Intelligence](routing/intelligence/main.go) + * [Not Found - Suggest Closest Paths](routing/intelligence/manual/main.go) * [Dynamic Path](routing/dynamic-path/main.go) - * [Root level wildcard path](routing/dynamic-path/root-wildcard/main.go) - * [Reverse routing](routing/reverse/main.go) - * [Custom wrapper](routing/custom-wrapper/main.go) + * [At-username](routing/dynamic-path/at-username/main.go) + * [Root Wildcard](routing/dynamic-path/root-wildcard/main.go) + * [Implement a Parameter Type](routing/macros/main.go) + * [Same Path Pattern but Func](routing/dynamic-path/same-pattern-different-func/main.go) + * Middleware + * [Per Route](routing/writing-a-middleware/per-route/main.go) + * [Globally](routing/writing-a-middleware/globally/main.go) + * [Remove a Handler](routing/remove-handler/main.go) + * Share Values + * [Share Services](routing/writing-a-middleware/share-services/main.go) + * [Share Functions](routing/writing-a-middleware/share-funcs/main.go) + * [Handlers Execution Rule](routing/route-handlers-execution-rules/main.go) + * [Route Register Rule](routing/route-register-rule/main.go) + * Convert net/http Handlers + * [From func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)](convert-handlers/negroni-like/main.go) + * [From http.Handler or http.HandlerFunc](convert-handlers/nethttp/main.go) + * [From func(http.Handler) http.Handler](convert-handlers/wrapper/main.go) + * [Convert by your own: sentry/raven middleware](convert-handlers/real-usecase-raven/writing-middleware/main.go) + * [Rewrite Middleware](routing/rewrite/main.go) * [Route State](routing/route-state/main.go) -* [Hero](hero) - * [Basic](hero/basic/main.go) - * [Overview](hero/overview/main.go) -* [MVC](mvc) - * [Hello world](mvc/hello-world/main.go) **UPDATED** - * [Session Controller](mvc/session-controller/main.go) **UPDATED** - * [Overview - Plus Repository and Service layers](mvc/overview/main.go) **UPDATED** - * [Login showcase - Plus Repository and Service layers](mvc/login/web/main.go) **UPDATED** - * [Singleton](mvc/singleton/main.go) **NEW** - * [Websocket Controller](mvc/websocket/main.go) **NEW** - * [Vue.js Todo MVC](tutorial/vuejs-todo-mvc/src/web/main.go) **NEW** -* [Custom Context](routing/custom-context) - * [Method Overriding](routing/custom-context/method-overriding/main.go) - * [New Implementation](routing/custom-context/new-implementation/main.go) -* [Convert http.Handler](convert-handlers) - * [From func(http.ResponseWriter, *http.Request, http.HandlerFunc)](convert-handlers/negroni-like/main.go) - * [From http.Handler or http.HandlerFunc](convert-handlers/nethttp/main.go) -* [Subdomains](subdomains) - * [Single](subdomains/single/main.go) - * [Multi](subdomains/multi/main.go) - * [Wildcard](subdomains/wildcard/main.go) - * [WWW](subdomains/www/main.go) -* [View](view) + * [Remove Route](routing/remove-route/main.go) + * [Reverse Routing](routing/reverse/main.go) + * [Router Wrapper](routing/custom-wrapper/main.go) + * [Custom Router](routing/custom-router/main.go) + * Subdomains + * [Single](routing/subdomains/single/main.go) + * [Multi](routing/subdomains/multi/main.go) + * [Wildcard](routing/subdomains/wildcard/main.go) + * [WWW](routing/subdomains/www/main.go) + * [WWW Method](routing/subdomains/www/www-method/main.go) + * [Redirection](routing/subdomains/redirect/main.go) + * [Multi Instances](routing/subdomains/redirect/multi-instances/main.go) + * [HTTP Errors View](routing/subdomains/http-errors-view/main.go) + * [HTTP Method Override](https://github.com/kataras/iris/blob/main/middleware/methodoverride/methodoverride_test.go) + * [API Versioning](routing/versioning/main.go) + * [Sitemap](routing/sitemap/main.go) +* Logging + * [Application File Logger](logging/file-logger/main.go) + * [Application JSON Logger](logging/json-logger/main.go) + * [Rollbar](logging/rollbar/main.go) + * AccessLog + * [Log Requests to a JSON File](logging/request-logger/accesslog-simple/main.go) + * [Using Log Rotation and more](logging/request-logger/accesslog) + * [Custom Fields and Template](logging/request-logger/accesslog-template/main.go) + * [Listen and render Logs to a Client](logging/request-logger/accesslog-broker/main.go) + * [The CSV Formatter](logging/request-logger/accesslog-csv/main.go) + * [Create your own Formatter](logging/request-logger/accesslog-formatter/main.go) + * [Root and Proxy AccessLog instances](logging/request-logger/accesslog-proxy/main.go) + * [Slack integration example](logging/request-logger/accesslog-slack/main.go) +* API Documentation + * [Swagger](https://github.com/iris-contrib/swagger/tree/master/_examples/basic) +* Testing + * [Testing with httptest](testing/httptest/main_test.go) + * [Testing with ginkgo](testing/ginkgotest) +* [Recovery](recover/main.go) + * [Panic and custom Error Handler with Compression](recover/panic-and-custom-error-handler-with-compression/main.go) +* [Profiling](pprof/main.go) +* File Server + * [File Server](file-server/file-server/main.go) + * [HTTP/2 Push Targets](file-server/http2push/main.go) + * [HTTP/2 Push Targets (Embedded)](file-server/http2push-embedded/main.go) + * [HTTP/2 Push Targets (Gzipped Embedded)](file-server/http2push-embedded-gzipped/main.go) + * [Favicon](file-server/favicon/main.go) + * [Basic](file-server/basic/main.go) + * [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go) + * [Embedding Files Into App Executable File (Bindata)](file-server/embedding-files-into-app-bindata/main.go) + * [Embedding Gzipped Files Into App Executable File (Bindata)](file-server/embedding-gzipped-files-into-app-bindata/main.go) + * [Send Files (rate limiter included)](file-server/send-files/main.go) + * Single Page Applications + * [Vue Router](file-server/spa-vue-router) + * [Basic SPA](file-server/single-page-application/basic/main.go) + * [Embedded Single Page Application and `iris.PrefixDir`](file-server/single-page-application/embedded-single-page-application/main.go) + * [Embedded Single Page Application with other routes](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go) + * [Upload File](file-server/upload-file/main.go) + * [Upload Multiple Files](file-server/upload-files/main.go) + * [WebDAV](file-server/webdav/main.go) +* View * [Overview](view/overview/main.go) - * [Hi](view/template_html_0/main.go) + * [Layout](view/layout) + * [Ace](view/layout/ace) + * [Blocks](view/layout/blocks) + * [Django](view/layout/django) + * [Handlebars](view/layout/handlebars) + * [HTML](view/layout/html) + * [Jet](view/layout/jet) + * [Pug](view/layout/pug) + * [Basic](view/template_html_0/main.go) * [A simple Layout](view/template_html_1/main.go) * [Layouts: `yield` and `render` tmpl funcs](view/template_html_2/main.go) - * [The `urlpath` tmpl func](view/template_html_3/main.go) - * [The `url` tmpl func](view/template_html_4/main.go) + * The `urlpath` template func + * [HTML](view/template_html_3/main.go) + * [Django](view/template_django_1/main.go) + * [The `url` template func](view/template_html_4/main.go) * [Inject Data Between Handlers](view/context-view-data/main.go) + * [Inject Engine Between Handlers](view/context-view-engine/main.go) * [Embedding Templates Into App Executable File](view/embedding-templates-into-app/main.go) - * [Write to a custom `io.Writer`](view/write-to/main.go) - * [Greeting with Pug (Jade)`](view/template_pug_0/main.go) - * [Pug (Jade) Actions`](view/template_pug_1/main.go) - * [Pug (Jade) Includes`](view/template_pug_2/main.go) - * [Pug (Jade) Extends`](view/template_pug_3/main.go) -* [Authentication](authentication) - * [Basic Authentication](authentication/basicauth/main.go) - * [OAUth2](authentication/oauth2/main.go) - * [JWT](experimental-handlers/jwt/simple/main.go) -* [File Server](file-server) - * [Favicon](file-server/favicon/main.go) - * [Basic](file-server/basic/main.go) - * [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go) - * [Embedding Gziped Files Into App Executable File](file-server/embedding-gziped-files-into-app/main.go) **NEW** - * [Send/Force-Download Files](file-server/send-files/main.go) -* [Single Page Applications](file-server/single-page-application) - * [Single Page Application](file-server/single-page-application/basic/main.go) - * [Embedded Single Page Application](file-server/single-page-application/embedded-single-page-application/main.go) -* [How to Read from *http.Request`](http_reqest) - * [Bind JSON](http_request/read-json/main.go) - * [Bind Form](http_request/read-form/main.go) - * [Upload/Read Files](http_request/upload-files/main.go) -* [How to Write to http.ResponseWriter](http_responsewriter) - * [Write `valyala/quicktemplate` templates](http_responsewriter/quicktemplate/main.go) - * [Text, Markdown, HTML, JSON, JSONP, XML, Binary](http_responsewriter/write-rest/main.go) - * [Stream Writer](http_responsewriter/stream-writer/main.go) - * [Transactions](http_responsewriter/transactions/main.go) - * [SSE (third-party package usage for server-side events)](http_responsewriter/sse-third-party/main.go) -* [Miscellaneous](miscellaneous) - * [Request Logger](http_request/request-logger/main.go) - * [Log Requests to a file](http_request/request-logger/request-logger-file/main.go) - * [Localization and Internationalization](miscellaneous/i18n/main.go) - * [Recovery](miscellaneous/recover/main.go) - * [Profiling (pprof)](miscellaneous/pprof/main.go) - * [Internal Application File Logger](miscellaneous/file-logger/main.go) - * [Testing](testing/httptest/main_test.go) - * [Caching](cache/simple/main.go) - * [Yaag - API Automated Docs](apidoc/yaag/main.go) -* [Sessions](sessions) - * [Overview](sessions/overview/main.go) - * [Standalone](sessions/standalone/main.go) + * [Embedding Templates Into App Executable File (Bindata)](view/embedding-templates-into-app-bindata/main.go) + * [Write to a custom `io.Writer`](view/write-to) + * Parse a Template from Text + * [HTML, Pug and Ace](view/parse-parse/main.go) + * [Django](view/parse-parse/django/main.go) + * [Jet](view/parse-parse/jet/main.go) + * [Handlebars](view/parse-parse/handlebars/main.go) + * [Blocks](view/template_blocks_0) + * [Blocks Embedded](view/template_blocks_1_embedded) + * [Pug: `Actions`](view/template_pug_0) + * [Pug: `Includes`](view/template_pug_1) + * [Pug Embedded`](view/template_pug_2_embedded) + * [Ace](view/template_ace_0) + * [Django](view/template_django_0) + * [Jet](view/template_jet_0) + * [Jet Embedded](view/template_jet_1_embedded) + * [Jet 'urlpath' tmpl func](view/template_jet_2) + * [Jet Template Funcs from Struct](view/template_jet_3) + * [Handlebars](view/template_handlebars_0) + * Third-Parties + * [Render `valyala/quicktemplate` templates](view/quicktemplate) + * [Render `shiyanhui/hero` templates](view/herotemplate) + * [Render `a-h/templ` templates](view/templ) **NEW** +* [Request ID](https://github.com/kataras/iris/blob/main/middleware/requestid/requestid_test.go) +* [Request Rate Limit](request-ratelimit/main.go) +* [Request Referrer](request-referrer/main.go) +* [Webassembly](webassembly/main.go) +* Request Body + * [Bind JSON](request-body/read-json/main.go) + * * [JSON Stream and disable unknown fields](request-body/read-json-stream/main.go) + * * [Struct Validation](request-body/read-json-struct-validation/main.go) + * [Bind XML](request-body/read-xml/main.go) + * [Bind MsgPack](request-body/read-msgpack/main.go) + * [Bind YAML](request-body/read-yaml/main.go) + * [Bind Form](request-body/read-form/main.go) + * [Checkboxes](request-body/read-form/checkboxes/main.go) + * [Bind Query](request-body/read-query/main.go) + * [Bind Params](request-body/read-params/main.go) + * [Bind URL](request-body/read-url/main.go) + * [Bind Headers](request-body/read-headers/main.go) + * [Bind Body](request-body/read-body/main.go) + * [Add Converter](request-body/form-query-headers-params-decoder/main.go) + * [Bind Custom per type](request-body/read-custom-per-type/main.go) + * [Bind Custom via Unmarshaler](request-body/read-custom-via-unmarshaler/main.go) + * [Bind Many times](request-body/read-many/main.go) +* Response Writer + * [Content Negotiation](response-writer/content-negotiation) + * [Text, Markdown, YAML, HTML, JSON, JSONP, Msgpack, XML and Binary](response-writer/write-rest/main.go) + * [Third-party JSON Encoder](response-writer/json-third-party/main.go) + * [Protocol Buffers](response-writer/protobuf/main.go) + * [HTTP/2 Server Push](response-writer/http2push/main.go) + * [Stream Writer](response-writer/stream-writer/main.go) + * [Server-Sent Events](response-writer/sse/main.go) + * [SSE 3rd-party (r3labs/sse)](response-writer/sse-third-party/main.go) + * [SSE 3rd-party (alexandrevicenzi/go-sse)](response-writer/sse-third-party-2/main.go) + * Cache + * [Simple](response-writer/cache/simple/main.go) + * [Client-Side (304)](response-writer/cache/client-side/main.go) +* Compression + * [Server-Side](compression/main.go) + * [Client-Side](compression/client/main.go) + * [Client-Side (using Iris)](compress/client-using-iris/main.go) +* Localization and Internationalization + * [Basic](i18n/basic) + * [Ttemplates and Functions](i18n/template) + * [Ttemplates and Functions (Embedded)](i18n/template-embedded) + * [Pluralization and Variables](i18n/plurals) +* Authentication, Authorization & Bot Detection + * [Recommended: Auth package and Single-Sign-On](auth/auth) **NEW (GO 1.18 Generics required)** + * Basic Authentication + * [Basic](auth/basicauth/basic) + * [Load from a slice of Users](auth/basicauth/users_list) + * [Load from a file & encrypted passwords](auth/basicauth/users_file_bcrypt) + * [Fetch & validate a User from a Database (MySQL)](auth/basicauth/database) + * [CORS](auth/cors) + * JSON Web Tokens + * [Basic](auth/jwt/basic/main.go) + * [Middleware](auth/jwt/midleware/main.go) + * [Blocklist](auth/jwt/blocklist/main.go) + * [Refresh Token](auth/jwt/refresh-token/main.go) + * [Tutorial](auth/jwt/tutorial) + * [JWT (community edition)](https://github.com/iris-contrib/middleware/tree/v12/jwt/_example/main.go) + * [OAUth2](auth/goth/main.go) + * [Manage Permissions](auth/permissions/main.go) + * [Google reCAPTCHA](auth/recaptcha/main.go) + * [hCaptcha](auth/hcaptcha/main.go) +* Cookies + * [Basic](cookies/basic/main.go) + * [Options](cookies/options/main.go) + * [Encode/Decode (with `securecookie`)](cookies/securecookie/main.go) +* Sessions + * [Overview: Config](sessions/overview/main.go) + * [Overview: Routes](sessions/overview/example/example.go) + * [Basic](sessions/basic/main.go) * [Secure Cookie](sessions/securecookie/main.go) * [Flash Messages](sessions/flash-messages/main.go) * [Databases](sessions/database) * [Badger](sessions/database/badger/main.go) - * [Redis](sessions/database/redis/main.go) * [BoltDB](sessions/database/boltdb/main.go) -* [Websockets](websocket) - * [Chat](websocket/chat/main.go) + * [Redis](sessions/database/redis/main.go) + * [View Data](sessions/viewdata) +* Websocket + * [Gorilla FileWatch (3rd-party)](websocket/gorilla-filewatch/main.go) + * [Basic](websocket/basic) + * [Server](websocket/basic/server.go) + * [Go Client](websocket/basic/go-client/client.go) + * [Browser Client](websocket/basic/browser/index.html) + * [Browser NPM Client (browserify)](websocket/basic/browserify/app.js) * [Native Messages](websocket/native-messages/main.go) - * [Connection List](websocket/connectionlist/main.go) - * [TLS Enabled](websocket/secure/main.go) - * [Custom Raw Go Client](websocket/custom-go-client/main.go) -* [Experimental Handlers](experimental-handlers) - * [Casbin wrapper](experimental-handlers/casbin/wrapper/main.go) - * [Casbin middleware](experimental-handlers/casbin/middleware/main.go) - * [Cloudwatch](experimental-handlers/cloudwatch/simple/main.go) - * [CORS](experimental-handlers/cors/simple/main.go) - * [JWT](experimental-handlers/jwt/main.go) - * [Newrelic](experimental-handlers/newrelic/simple/main.go) - * [Prometheus](experimental-handlers/prometheus/simple/main.go) - * [Secure](experimental-handlers/secure/simple/main.go) - * [Tollboothic](experimental-handlers/tollboothic/limit-handler/main.go) - -> Do not forget to [star or watch the project](https://github.com/kataras/iris/stargazers) in order to stay updated with the latest tech trends, it takes some seconds for the sake of go! - -> Examples are tested using Windows 10, Ubuntu 16.10 with [Microsoft's Visual Studio Code](https://code.visualstudio.com/) and built using the [Go 1.9](https://golang.org/dl). - -## Run - -1. Install the Go Programming Language, version 1.9 from [here](https://golang.org/dl). -2. Install Iris: `go get -u github.com/kataras/iris` -3. [Download the examples](https://github.com/iris-contrib/examples/archive/master.zip) and copy-paste them to your `$GOPATH/src/github.com/iris-contrib/examples` - -And run - -```sh -$ cd $GOPATH/src/github.com/iris-contrib/examples/overview -$ go run main.go -``` - -## Any troubles with examples? - - https://github.com/iris-contrib/examples/issues - -## Su, 04 June 2017 - -This repository is just a minor of the https://github.com/kataras/iris/master/_examples folder. + * [TLS](websocket/secure/README.md) + * [Online Visitors](websocket/online-visitors/main.go) +* Dependency Injection + * [Overview (Movies Service)](ependency-injection/overview/main.go) + * [Basic](dependency-injection/basic/main.go) + * [Middleware](dependency-injection/basic/middleware/main.go) + * [Sessions](dependency-injection/sessions/main.go) + * [Smart Contract](dependency-injection/smart-contract/main.go) + * [JWT](dependency-injection/jwt/main.go) + * [JWT (iris-contrib)](dependency-injection/jwt/contrib/main.go) + * [Register Dependency from Context](dependency-injection/context-register-dependency/main.go) +* MVC + * [Overview](mvc/overview) + * [Repository and Service layers](mvc/repository) + * [Hello world](mvc/hello-world/main.go) + * [Basic](mvc/basic/main.go) + * [Wildcard](mvc/basic/wildcard/main.go) + * [Default request values](mvc/request-default-values/main.go) + * [Singleton](mvc/singleton) + * [Regexp](mvc/regexp/main.go) + * [Session Controller](mvc/session-controller/main.go) + * [Authenticated Controller](mvc/authenticated-controller/main.go) + * [Versioned Controller](mvc/versioned-controller/main.go) + * [Websocket Controller](mvc/websocket) + * [Websocket + Authentication (Single-Sign-On)](mvc/websocket-auth) **NEW (GO 1.18 Generics required)** + * [Register Middleware](mvc/middleware) + * [gRPC](mvc/grpc-compatible) + * [gRPC Bidirectional Stream](mvc/grpc-compatible-bidirectional-stream) + * [Login (Repository and Service layers)](mvc/login) + * [Login (Single Responsibility)](mvc/login-mvc-single-responsibility) + * [Vue.js Todo App](mvc/vuejs-todo-mvc) + * [HTTP Error Handler](mvc/error-handler-http) + * [Error Handler](mvc/error-handler) + * [Handle errors using mvc.Result](mvc/error-handler-custom-result) + * [Handle errors using PreflightResult](mvc/error-handler-preflight) + * [Handle errors by hijacking the result](mvc/error-handler-hijack) +* Desktop Applications + * [The blink package](desktop/blink) + * [The lorca package](desktop/lorca) + * [The webview package](desktop/webview) +* Middlewares [(Community)](https://github.com/iris-contrib/middleware) diff --git a/apidoc/swagger/README.md b/apidoc/swagger/README.md new file mode 100644 index 00000000..08e23049 --- /dev/null +++ b/apidoc/swagger/README.md @@ -0,0 +1,3 @@ +# Swagger 2.0 + +Visit https://github.com/iris-contrib/swagger instead. diff --git a/apidoc/yaag/main.go b/apidoc/yaag/main.go deleted file mode 100644 index ed931a53..00000000 --- a/apidoc/yaag/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/betacraft/yaag/irisyaag" - "github.com/betacraft/yaag/yaag" -) - -/* - go get github.com/betacraft/yaag/... -*/ - -type myXML struct { - Result string `xml:"result"` -} - -func main() { - app := iris.New() - - yaag.Init(&yaag.Config{ // <- IMPORTANT, init the middleware. - On: true, - DocTitle: "Iris", - DocPath: "apidoc.html", - BaseUrls: map[string]string{"Production": "", "Staging": ""}, - }) - app.Use(irisyaag.New()) // <- IMPORTANT, register the middleware. - - app.Get("/json", func(ctx iris.Context) { - ctx.JSON(iris.Map{"result": "Hello World!"}) - }) - - app.Get("/plain", func(ctx iris.Context) { - ctx.Text("Hello World!") - }) - - app.Get("/xml", func(ctx iris.Context) { - ctx.XML(myXML{Result: "Hello World!"}) - }) - - app.Get("/complex", func(ctx iris.Context) { - value := ctx.URLParam("key") - ctx.JSON(iris.Map{"value": value}) - }) - - // Run our HTTP Server. - // - // Documentation of "yaag" doesn't note the follow, but in Iris we are careful on what - // we provide to you. - // - // Each incoming request results on re-generation and update of the "apidoc.html" file. - // Recommentation: - // Write tests that calls those handlers, save the generated "apidoc.html". - // Turn off the yaag middleware when in production. - // - // Example usage: - // Visit all paths and open the generated "apidoc.html" file to see the API's automated docs. - app.Run(iris.Addr(":8080")) -} diff --git a/auth/auth/README.md b/auth/auth/README.md new file mode 100644 index 00000000..3f91efeb --- /dev/null +++ b/auth/auth/README.md @@ -0,0 +1,12 @@ +# Auth Package (+ Single Sign On) + +```sh +$ go run . +``` + +1. GET/POST: http://localhost:8080/signin +2. GET: http://localhost:8080/member +3. GET: http://localhost:8080/owner +4. POST: http://localhost:8080/refresh +5. GET: http://localhost:8080/signout +6. GET: http://localhost:8080/signout-all \ No newline at end of file diff --git a/auth/auth/auth.yml b/auth/auth/auth.yml new file mode 100644 index 00000000..9cfed272 --- /dev/null +++ b/auth/auth/auth.yml @@ -0,0 +1,36 @@ +Headers: # required. + - "Authorization" + - "X-Authorization" +Cookie: # optional. + Name: "iris_auth_cookie" + Secure: false + Hash: "D*G-KaPdSgUkXp2s5v8y/B?E(H+MbQeThWmYq3t6w9z$C&F)J@NcRfUjXn2r4u7x" # length of 64 characters (512-bit). + Block: "VkYp3s6v9y$B&E)H@McQfTjWmZq4t7w!" # length of 32 characters (256-bit). +Keys: + - ID: IRIS_AUTH_ACCESS # required. + Alg: EdDSA + MaxAge: 2h # 2 hours lifetime for access tokens. + Private: |+ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIFdZWoDdFny5SMnP9Fyfr8bafi/B527EVZh8JJjDTIFO + -----END PRIVATE KEY----- + Public: |+ + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAzpgjKSr9E032DX+foiOxq1QDsbzjLxagTN+yVpGWZB4= + -----END PUBLIC KEY----- + - ID: IRIS_AUTH_REFRESH # optional. Good practise to have it though. + Alg: EdDSA + # 1 month lifetime for refresh tokens, + # after that period the user has to signin again. + MaxAge: 720h + Private: |+ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIHJ1aoIjA2sRp5eqGjGR3/UMucrHbBdBv9p8uwfzZ1KZ + -----END PRIVATE KEY----- + Public: |+ + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAsKKAr+kDtfAqwG7cZdoEAfh9jHt9W8qi9ur5AA1KQAQ= + -----END PUBLIC KEY----- + # Example of setting a binary form of the encryption key for refresh tokens, + # it could be a "string" as well. + EncryptionKey: !!binary stSNLTu91YyihPxzeEOXKwGVMG00CjcC/68G8nMgmqA= diff --git a/auth/auth/main.go b/auth/auth/main.go new file mode 100644 index 00000000..4858eee1 --- /dev/null +++ b/auth/auth/main.go @@ -0,0 +1,139 @@ +//go:build go1.18 +// +build go1.18 + +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/auth" +) + +func allowRole(role AccessRole) auth.VerifyUserFunc[User] { + return func(u User) error { + if !u.Role.Allow(role) { + return fmt.Errorf("invalid role") + } + + return nil + } +} + +const configFilename = "./auth.yml" + +func main() { + app := iris.New() + app.RegisterView(iris.Blocks(iris.Dir("./views"), ".html"). + LayoutDir("layouts"). + Layout("main")) + + /* + // Easiest 1-liner way, load from configuration and initialize a new auth instance: + s := auth.MustLoad[User]("./auth.yml") + // Bind a configuration from file: + var c auth.Configuration + c.BindFile("./auth.yml") + s, err := auth.New[User](c) + // OR create new programmatically configuration: + config := auth.Configuration{ + ...fields + } + s, err := auth.New[User](config) + // OR generate a new configuration: + config := auth.MustGenerateConfiguration() + s, err := auth.New[User](config) + // OR generate a new config and save it if cannot open the config file. + if _, err := os.Stat(configFilename); err != nil { + generatedConfig := auth.MustGenerateConfiguration() + configContents, err := generatedConfig.ToYAML() + if err != nil { + panic(err) + } + + err = os.WriteFile(configFilename, configContents, 0600) + if err != nil { + panic(err) + } + } + */ + + // 1. Load configuration from a file. + authConfig, err := auth.LoadConfiguration(configFilename) + if err != nil { + panic(err) + } + + // 2. Initialize a new auth instance for "User" claims (generics: go1.18 +). + s, err := auth.New[User](authConfig) + if err != nil { + panic(err) + } + + // 3. Add a custom provider, in our case is just a memory-based one. + s.AddProvider(NewProvider()) + // 3.1. Optionally set a custom error handler. + // s.SetErrorHandler(new(auth.DefaultErrorHandler)) + + app.Get("/signin", renderSigninForm) + // 4. generate token pairs. + app.Post("/signin", s.SigninHandler) + // 5. refresh token pairs. + app.Post("/refresh", s.RefreshHandler) + // 6. calls the provider's InvalidateToken method. + app.Get("/signout", s.SignoutHandler) + // 7. calls the provider's InvalidateTokens method. + app.Get("/signout-all", s.SignoutAllHandler) + + // 8.1. allow access for users with "Member" role. + app.Get("/member", s.VerifyHandler(allowRole(Member)), renderMemberPage(s)) + // 8.2. allow access for users with "Owner" role. + app.Get("/owner", s.VerifyHandler(allowRole(Owner)), renderOwnerPage(s)) + + /* Subdomain user verify: + app.Subdomain("owner", s.VerifyHandler(allowRole(Owner))).Get("/", renderOwnerPage(s)) + */ + app.Listen(":8080", iris.WithOptimizations) // Setup HTTPS/TLS for production instead. + /* Test subdomain user verify, one way is ingrok, + add the below to the arguments above: + , iris.WithConfiguration(iris.Configuration{ + EnableOptmizations: true, + Tunneling: iris.TunnelingConfiguration{ + AuthToken: "YOUR_AUTH_TOKEN", + Region: "us", + Tunnels: []tunnel.Tunnel{ + { + Name: "Iris Auth (Test)", + Addr: ":8080", + Hostname: "YOUR_DOMAIN", + }, + { + Name: "Iris Auth (Test Subdomain)", + Addr: ":8080", + Hostname: "owner.YOUR_DOMAIN", + }, + }, + }, + })*/ +} + +func renderSigninForm(ctx iris.Context) { + if err := ctx.View("signin", iris.Map{"Title": "Signin Page"}); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func renderMemberPage(s *auth.Auth[User]) iris.Handler { + return func(ctx iris.Context) { + user := s.GetUser(ctx) + ctx.Writef("Hello member: %s\n", user.Email) + } +} + +func renderOwnerPage(s *auth.Auth[User]) iris.Handler { + return func(ctx iris.Context) { + user := s.GetUser(ctx) + ctx.Writef("Hello owner: %s\n", user.Email) + } +} diff --git a/auth/auth/user.go b/auth/auth/user.go new file mode 100644 index 00000000..f4f65ea4 --- /dev/null +++ b/auth/auth/user.go @@ -0,0 +1,34 @@ +//go:build go1.18 +// +build go1.18 + +package main + +type AccessRole uint16 + +func (r AccessRole) Is(v AccessRole) bool { + return r&v != 0 +} + +func (r AccessRole) Allow(v AccessRole) bool { + return r&v >= v +} + +const ( + InvalidAccessRole AccessRole = 1 << iota + Read + Write + Delete + + Owner = Read | Write | Delete + Member = Read | Write +) + +type User struct { + ID string `json:"id"` + Email string `json:"email"` + Role AccessRole `json:"role"` +} + +func (u User) GetID() string { + return u.ID +} diff --git a/auth/auth/user_provider.go b/auth/auth/user_provider.go new file mode 100644 index 00000000..3d05c6ac --- /dev/null +++ b/auth/auth/user_provider.go @@ -0,0 +1,101 @@ +//go:build go1.18 +// +build go1.18 + +package main + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/kataras/iris/v12/auth" +) + +type Provider struct { + dataset []User + + invalidated map[string]struct{} // key = token. Entry is blocked. + invalidatedAll map[string]int64 // key = user id, value = timestamp. Issued before is consider invalid. + mu sync.RWMutex +} + +func NewProvider() *Provider { + return &Provider{ + dataset: []User{ + { + ID: "id-1", + Email: "kataras2006@hotmail.com", + Role: Owner, + }, + { + ID: "id-2", + Email: "example@example.com", + Role: Member, + }, + }, + invalidated: make(map[string]struct{}), + invalidatedAll: make(map[string]int64), + } +} + +func (p *Provider) Signin(ctx context.Context, username, password string) (User, error) { // fired on SigninHandler. + // your database... + for _, user := range p.dataset { + if user.Email == username { + return user, nil + } + } + + return User{}, fmt.Errorf("user not found") +} + +func (p *Provider) ValidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on VerifyHandler. + // your database and checks of blocked tokens... + + // check for specific token ids. + p.mu.RLock() + _, tokenBlocked := p.invalidated[standardClaims.ID] + if !tokenBlocked { + // this will disallow refresh tokens with origin jwt token id as the blocked access token as well. + if standardClaims.OriginID != "" { + _, tokenBlocked = p.invalidated[standardClaims.OriginID] + } + } + p.mu.RUnlock() + + if tokenBlocked { + return fmt.Errorf("token was invalidated") + } + // + + // check all tokens issuet before the "InvalidateToken" method was fired for this user. + p.mu.RLock() + ts, oldUserBlocked := p.invalidatedAll[u.ID] + p.mu.RUnlock() + + if oldUserBlocked && standardClaims.IssuedAt <= ts { + return fmt.Errorf("token was invalidated") + } + // + + return nil // else valid. +} + +func (p *Provider) InvalidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on SignoutHandler. + // invalidate this specific token. + p.mu.Lock() + p.invalidated[standardClaims.ID] = struct{}{} + p.mu.Unlock() + + return nil +} + +func (p *Provider) InvalidateTokens(ctx context.Context, u User) error { // fired on SignoutAllHandler. + // invalidate all previous tokens came from "u". + p.mu.Lock() + p.invalidatedAll[u.ID] = time.Now().Unix() + p.mu.Unlock() + + return nil +} diff --git a/auth/auth/views/layouts/main.html b/auth/auth/views/layouts/main.html new file mode 100644 index 00000000..b44c3648 --- /dev/null +++ b/auth/auth/views/layouts/main.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{ if .Title }}{{ .Title }}{{ else }}Default Main Title{{ end }}</title> +</head> +<style> + body { + margin: 0; + display: flex; + min-height: 100vh; + flex-direction: column; + } + main { + display: block; + flex: 1 0 auto; + } + .container { + max-width: 500px; + margin: auto; + } +</style> +<body> + <div class="container"> + <main>{{ template "content" . }}</main> + <footer style="position: fixed; bottom: 0; width: 100%;">{{ partial "partials/footer" . }}</footer> + </div> +</body> +</html> \ No newline at end of file diff --git a/auth/auth/views/partials/footer.html b/auth/auth/views/partials/footer.html new file mode 100644 index 00000000..69b8f9b8 --- /dev/null +++ b/auth/auth/views/partials/footer.html @@ -0,0 +1 @@ +<i>Iris Web Framework © 2022</i> \ No newline at end of file diff --git a/auth/auth/views/signin.html b/auth/auth/views/signin.html new file mode 100644 index 00000000..57f7514c --- /dev/null +++ b/auth/auth/views/signin.html @@ -0,0 +1,9 @@ +<div class="user_signin"> + <form action="" method="post"> + <label for="username">Email:</label> + <input name="username" type="email" /> + <label for="password">Password:</label> + <input name="password" type="password" /> + <input type="submit" value="Sign in" /> + </form> +</div> \ No newline at end of file diff --git a/auth/basicauth/basic/main.go b/auth/basicauth/basic/main.go new file mode 100644 index 00000000..06f3ce5d --- /dev/null +++ b/auth/basicauth/basic/main.go @@ -0,0 +1,99 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/errors" + + "github.com/kataras/iris/v12/middleware/basicauth" +) + +func newApp() *iris.Application { + app := iris.New() + + /* + opts := basicauth.Options{ + Realm: "Authorization Required", + MaxAge: 30 * time.Minute, + GC: basicauth.GC{ + Every: 2 * time.Hour, + }, + Allow: basicauth.AllowUsers(map[string]string{ + "myusername": "mypassword", + "mySecondusername": "mySecondpassword", + }), + MaxTries: 2, + } + auth := basicauth.New(opts) + + OR simply: + */ + + auth := basicauth.Default(map[string]string{ + "myusername": "mypassword", + "mySecondusername": "mySecondpassword", + }) + + // To the next routes of a party (group of routes): + /* + app.Use(auth) + */ + + // For global effect, including not founds: + /* + app.UseRouter(auth) + */ + + // For global effect, excluding http errors such as not founds: + /* + app.UseGlobal(auth) or app.Use(auth) before any route registered. + */ + + // For single/per routes: + /* + app.Get("/mysecret", auth, h) + */ + + app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") }) + + // to party + + needAuth := app.Party("/admin", auth) + { + //http://localhost:8080/admin + needAuth.Get("/", handler) + // http://localhost:8080/admin/profile + needAuth.Get("/profile", handler) + + // http://localhost:8080/admin/settings + needAuth.Get("/settings", handler) + + needAuth.Get("/logout", logout) + } + + return app +} + +func main() { + app := newApp() + // open http://localhost:8080/admin + app.Listen(":8080") +} + +func handler(ctx iris.Context) { + // user := ctx.User().(*myUserType) + // or ctx.User().GetRaw().(*myUserType) + // ctx.Writef("%s %s:%s", ctx.Path(), user.Username, user.Password) + // OR if you don't have registered custom User structs: + username, password, _ := ctx.Request().BasicAuth() + ctx.Writef("%s %s:%s", ctx.Path(), username, password) +} + +func logout(ctx iris.Context) { + // fires 401, invalidates the basic auth, + // logout through javascript and ajax is a better solution though. + err := ctx.Logout() + if err != nil { + errors.Internal.Err(ctx, err) + return + } +} diff --git a/authentication/basicauth/main_test.go b/auth/basicauth/basic/main_test.go similarity index 71% rename from authentication/basicauth/main_test.go rename to auth/basicauth/basic/main_test.go index 2e123c0c..1cce493a 100644 --- a/authentication/basicauth/main_test.go +++ b/auth/basicauth/basic/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestBasicAuth(t *testing.T) { @@ -17,11 +17,11 @@ func TestBasicAuth(t *testing.T) { // with valid basic auth e.GET("/admin").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin myusername:mypassword") e.GET("/admin/profile").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin/profile myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin/profile myusername:mypassword") e.GET("/admin/settings").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin/settings myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin/settings myusername:mypassword") // with invalid basic auth e.GET("/admin/settings").WithBasicAuth("invalidusername", "invalidpassword"). diff --git a/auth/basicauth/database/Dockerfile b/auth/basicauth/database/Dockerfile new file mode 100644 index 00000000..dd88c66c --- /dev/null +++ b/auth/basicauth/database/Dockerfile @@ -0,0 +1,18 @@ +# docker build -t myapp . +# docker run --rm -it -p 8080:8080 myapp:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +# cache step +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/myapp . +ENTRYPOINT ["./myapp"] \ No newline at end of file diff --git a/auth/basicauth/database/README.md b/auth/basicauth/database/README.md new file mode 100644 index 00000000..b59433eb --- /dev/null +++ b/auth/basicauth/database/README.md @@ -0,0 +1,44 @@ +# BasicAuth + MySQL & Docker Example + +## ⚡ Get Started + +Download the folder. + +### Install (Docker) + +Install [Docker](https://www.docker.com/) and execute the command below + +```sh +$ docker-compose up --build +``` + +### Install (Manually) + +Run `go build -mod=mod` or `go run -mod=mod main.go` and read below. + +#### MySQL + +Environment variables: + +```sh +MYSQL_USER=user_myapp +MYSQL_PASSWORD=dbpassword +MYSQL_HOST=localhost +MYSQL_DATABASE=myapp +``` + +Download the schema from [migration/db.sql](migration/db.sql) and execute it against your MySQL server instance. + +<http://localhost:8080> + +```sh +username: admin +password: admin +``` + +```sh +username: iris +password: iris_password +``` + +The example does not contain code to add a user to the database, as this is out of the scope of this middleware. More features can be implemented by end-developers. diff --git a/auth/basicauth/database/docker-compose.yml b/auth/basicauth/database/docker-compose.yml new file mode 100644 index 00000000..abbb4fff --- /dev/null +++ b/auth/basicauth/database/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.1' + +services: + db: + image: mysql + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_ROOT_PASSWORD: dbpassword + MYSQL_DATABASE: myapp + MYSQL_USER: user_myapp + MYSQL_PASSWORD: dbpassword + tty: true + volumes: + - ./migration:/docker-entrypoint-initdb.d + app: + build: . + ports: + - 8080:8080 + environment: + PORT: 8080 + MYSQL_USER: user_myapp + MYSQL_PASSWORD: dbpassword + MYSQL_DATABASE: myapp + MYSQL_HOST: db + restart: on-failure + healthcheck: + test: ["CMD", "curl", "-f", "tcp://db:3306"] + interval: 30s + timeout: 10s + retries: 10 + depends_on: + - db \ No newline at end of file diff --git a/auth/basicauth/database/go.mod b/auth/basicauth/database/go.mod new file mode 100644 index 00000000..8728ae09 --- /dev/null +++ b/auth/basicauth/database/go.mod @@ -0,0 +1,55 @@ +module myapp + +go 1.22 + +require ( + github.com/go-sql-driver/mysql v1.8.1 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/auth/basicauth/database/go.sum b/auth/basicauth/database/go.sum new file mode 100644 index 00000000..cad809f4 --- /dev/null +++ b/auth/basicauth/database/go.sum @@ -0,0 +1,182 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/auth/basicauth/database/main.go b/auth/basicauth/database/main.go new file mode 100644 index 00000000..e8e439e9 --- /dev/null +++ b/auth/basicauth/database/main.go @@ -0,0 +1,114 @@ +package main // Look README.md + +import ( + "context" + "database/sql" + "fmt" + "os" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" + + _ "github.com/go-sql-driver/mysql" // lint: mysql driver. +) + +// User is just an example structure of a user, +// it MUST contain a Username and Password exported fields +// or/and complete the basicauth.User interface. +type User struct { + ID int64 `db:"id" json:"id"` + Username string `db:"username" json:"username"` + Password string `db:"password" json:"password"` + Email string `db:"email" json:"email"` +} + +// GetUsername returns the Username field. +func (u User) GetUsername() string { + return u.Username +} + +// GetPassword returns the Password field. +func (u User) GetPassword() string { + return u.Password +} + +func main() { + dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true&charset=utf8mb4&collation=utf8mb4_unicode_ci", + getenv("MYSQL_USER", "user_myapp"), + getenv("MYSQL_PASSWORD", "dbpassword"), + getenv("MYSQL_HOST", "localhost"), + getenv("MYSQL_DATABASE", "myapp"), + ) + db, err := connect(dsn) + if err != nil { + panic(err) + } + + // Validate a user from database. + allowFunc := func(ctx iris.Context, username, password string) (interface{}, bool) { + user, err := db.getUserByUsernameAndPassword(context.Background(), username, password) + return user, err == nil + } + + opts := basicauth.Options{ + Realm: basicauth.DefaultRealm, + ErrorHandler: basicauth.DefaultErrorHandler, + Allow: allowFunc, + } + + auth := basicauth.New(opts) + + app := iris.New() + app.Use(auth) + app.Get("/", index) + app.Listen(":8080") +} + +func index(ctx iris.Context) { + user, _ := ctx.User().GetRaw() + // user is a type of main.User + ctx.JSON(user) +} + +func getenv(key string, def string) string { + v := os.Getenv(key) + if v == "" { + return def + } + + return v +} + +type database struct { + *sql.DB +} + +func connect(dsn string) (*database, error) { + conn, err := sql.Open("mysql", dsn) + if err != nil { + return nil, err + } + err = conn.Ping() + if err != nil { + conn.Close() + return nil, err + } + + return &database{conn}, nil +} + +func (db *database) getUserByUsernameAndPassword(ctx context.Context, username, password string) (User, error) { + query := fmt.Sprintf("SELECT * FROM %s WHERE %s = ? AND %s = ? LIMIT 1", "users", "username", "password") + rows, err := db.QueryContext(ctx, query, username, password) + if err != nil { + return User{}, err + } + defer rows.Close() + if !rows.Next() { + return User{}, sql.ErrNoRows + } + + var user User + err = rows.Scan(&user.ID, &user.Username, &user.Password, &user.Email) + return user, err +} diff --git a/auth/basicauth/database/migration/db.sql b/auth/basicauth/database/migration/db.sql new file mode 100644 index 00000000..d0100157 --- /dev/null +++ b/auth/basicauth/database/migration/db.sql @@ -0,0 +1,22 @@ +CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE myapp; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS users; +CREATE TABLE users ( + id int(11) NOT NULL AUTO_INCREMENT, + username varchar(255) NOT NULL, + password varchar(255) NOT NULL, + email varchar(255) NOT NULL, + PRIMARY KEY (id) +); + +INSERT INTO users (username,password,email) +VALUES + ('admin', 'admin', 'kataras2006@hotmail.com'), + ("iris", 'iris_password', 'iris-go@outlook.com'); + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/auth/basicauth/users_file_bcrypt/main.go b/auth/basicauth/users_file_bcrypt/main.go new file mode 100644 index 00000000..5f272185 --- /dev/null +++ b/auth/basicauth/users_file_bcrypt/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" +) + +func main() { + auth := basicauth.Load("users.yml", basicauth.BCRYPT) + /* Same as: + opts := basicauth.Options{ + Realm: basicauth.DefaultRealm, + Allow: basicauth.AllowUsersFile("users.yml", basicauth.BCRYPT), + } + + auth := basicauth.New(opts) + */ + + app := iris.New() + app.Use(auth) + app.Get("/", index) + // kataras:kataras_pass + // makis:makis_pass + app.Listen(":8080") +} + +func index(ctx iris.Context) { + user := ctx.User() + ctx.JSON(user) +} diff --git a/auth/basicauth/users_file_bcrypt/users.yml b/auth/basicauth/users_file_bcrypt/users.yml new file mode 100644 index 00000000..46f68fa6 --- /dev/null +++ b/auth/basicauth/users_file_bcrypt/users.yml @@ -0,0 +1,12 @@ +# The file cannot be modified during the serve time. +# To support real-time users changes please use the Options.Allow instead, +# (see the database example for that). +# +# Again, the username and password (or capitalized) fields are required, +# the rest are optional, depending on your application needs. +- username: kataras + password: $2a$10$Irg8k8HWkDlvL0YDBKLCYee6j6zzIFTplJcvZYKA.B8/clHPZn2Ey # encrypted of kataras_pass + age: 27 + role: admin +- username: makis + password: $2a$10$3GXzp3J5GhHThGisbpvpZuftbmzPivDMo94XPnkTnDe7254x7sJ3O # encrypted of makis_pass diff --git a/auth/basicauth/users_list/main.go b/auth/basicauth/users_list/main.go new file mode 100644 index 00000000..619d809e --- /dev/null +++ b/auth/basicauth/users_list/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" +) + +// User is just an example structure of a user, +// it MUST contain a Username and Password exported fields +// or complete the basicauth.User interface. +type User struct { + Username string `json:"username"` + Password string `json:"password"` + Roles []string `json:"roles"` +} + +var users = []User{ + {"admin", "admin", []string{"admin"}}, + {"kataras", "kataras_pass", []string{"manager", "author"}}, + {"george", "george_pass", []string{"member"}}, + {"john", "john_pass", []string{}}, +} + +func main() { + opts := basicauth.Options{ + Realm: basicauth.DefaultRealm, + // Defaults to 0, no expiration. + // Prompt for new credentials on a client's request + // made after 10 minutes the user has logged in: + MaxAge: 10 * time.Minute, + // Clear any expired users from the memory every one hour, + // note that the user's expiration time will be + // reseted on the next valid request (when Allow passed). + GC: basicauth.GC{ + Every: 2 * time.Hour, + }, + // The users can be a slice of custom users structure + // or a map[string]string (username:password) + // or []map[string]interface{} with username and passwords required fields, + // read the godocs for more. + Allow: basicauth.AllowUsers(users), + } + + auth := basicauth.New(opts) + // OR: basicauth.Default(users) + + app := iris.New() + app.Use(auth) + app.Get("/", index) + app.Listen(":8080") +} + +func index(ctx iris.Context) { + user, _ := ctx.User().GetRaw() + ctx.JSON(user) +} diff --git a/auth/cors/main.go b/auth/cors/main.go new file mode 100644 index 00000000..c5b6c5e8 --- /dev/null +++ b/auth/cors/main.go @@ -0,0 +1,63 @@ +// Package main integrates the "rs/cors" net/http middleware into Iris. +// That cors third-party middleware cannot be registered through `iris.FromStd` +// as a common middleware because it should be injected before the Iris Router itself, +// it allows/dissallows HTTP Methods too. +// +// This is just an example you can use to run something, based on custom logic, +// before the Iris Router itself. +// +// In the "routing/custom-wrapper" example +// we learn how we can acquire and release an Iris context to fire an Iris Handler +// based on custom logic, before the Iris Router itself. In that example +// we will fire a net/http handler (the "rs/cors" handler one) instead. +// +// https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/rs/cors" +) + +func main() { + app := iris.New() + c := cors.New(cors.Options{ + AllowedOrigins: []string{"*"}, + AllowCredentials: true, + // Enable Debugging for testing, consider disabling in production + Debug: true, + }) + // app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) { + // [custom logic...] + // if shouldFireNetHTTPHandler { + // ...ServeHTTP(w,r) + // return + // } + // router(w,r) + // }) + // In our case, the cors package has a ServeHTTP + // of the same form of app.WrapRouter's accept input argument, + // so we can just do: + app.WrapRouter(c.ServeHTTP) + + // Serve ./public/index.html, main.js. + app.HandleDir("/", iris.Dir("./public")) + + // Register routes here... + app.Get("/data", listData) + + // http://localhost:8080 and click the "fetch data" button. + app.Listen(":8080") +} + +type item struct { + Title string `json:"title"` +} + +func listData(ctx iris.Context) { + ctx.JSON([]item{ + {"Item 1"}, + {"Item 2"}, + {"Item 3"}, + }) +} diff --git a/auth/cors/public/index.html b/auth/cors/public/index.html new file mode 100644 index 00000000..7f36d6ce --- /dev/null +++ b/auth/cors/public/index.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Iris Cors Example</title> +</head> + +<body> + <ul id="list"> + </ul> + + <input type="button" value="Fetch Data" id="fetchBtn" /> + + <script src="main.js"></script> + </body> +</html> \ No newline at end of file diff --git a/auth/cors/public/main.js b/auth/cors/public/main.js new file mode 100644 index 00000000..aa83baf3 --- /dev/null +++ b/auth/cors/public/main.js @@ -0,0 +1,43 @@ +// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch +async function doRequest(method = 'GET', url = '', data = {}) { + // Default options are marked with * + + const request = { + method: method, // *GET, POST, PUT, DELETE, etc. + mode: 'cors', // no-cors, *cors, same-origin + cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached + credentials: 'same-origin', // include, *same-origin, omit + redirect: 'follow', // manual, *follow, error + referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url + }; + + if (data !== undefined && method !== 'GET' && method !== 'HEAD') { + request.headers = { + 'Content-Type': 'application/json' + // 'Content-Type': 'application/x-www-form-urlencoded', + }; + // body data type must match "Content-Type" header. + request.body = JSON.stringify(data); + } + + const response = await fetch(url, request); + return response.json(); // parses JSON response into native JavaScript objects. +} + +const ul = document.getElementById("list"); + +function fetchData() { + console.log("sending request...") + + doRequest('GET', '/data').then(data => { + data.forEach(item => { + var li = document.createElement("li"); + li.appendChild(document.createTextNode(item.title)); + ul.appendChild(li); + }); + + console.log(data); // JSON data parsed by `response.json()` call. + }); +} + +document.getElementById("fetchBtn").onclick = fetchData; \ No newline at end of file diff --git a/authentication/oauth2/main.go b/auth/goth/main.go similarity index 83% rename from authentication/oauth2/main.go rename to auth/goth/main.go index 562a2a12..0a188cfb 100644 --- a/authentication/oauth2/main.go +++ b/auth/goth/main.go @@ -24,9 +24,9 @@ import ( "os" "sort" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12/sessions" "github.com/gorilla/securecookie" // optionally, used for session's encoder/decoder @@ -74,16 +74,14 @@ var sessionsManager *sessions.Sessions func init() { // attach a session manager cookieName := "mycustomsessionid" - // AES only supports key sizes of 16, 24 or 32 bytes. - // You either need to provide exactly that amount or you derive the key from what you type in. - hashKey := []byte("the-big-and-secret-fash-key-here") - blockKey := []byte("lot-secret-of-characters-big-too") + hashKey := securecookie.GenerateRandomKey(64) + blockKey := securecookie.GenerateRandomKey(32) secureCookie := securecookie.New(hashKey, blockKey) sessionsManager = sessions.New(sessions.Config{ - Cookie: cookieName, - Encode: secureCookie.Encode, - Decode: secureCookie.Decode, + Cookie: cookieName, + Encoding: secureCookie, + AllowReclaim: true, }) } @@ -126,8 +124,7 @@ See https://github.com/markbates/goth/examples/main.go to see this in action. func BeginAuthHandler(ctx iris.Context) { url, err := GetAuthURL(ctx) if err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.Writef("%v", err) + ctx.StopWithError(iris.StatusBadRequest, err) return } @@ -179,7 +176,6 @@ var SetState = func(ctx iris.Context) string { } return "state" - } // GetState gets the state returned by the provider during the callback. @@ -194,7 +190,7 @@ CompleteUserAuth does what it says on the tin. It completes the authentication process and fetches all of the basic information about the user from the provider. It expects to be able to get the name of the provider from the query parameters -as either "provider" or ":provider". +as either "provider" or "{provider}" path parameter. See https://github.com/markbates/goth/examples/main.go to see this in action. */ @@ -273,14 +269,14 @@ func main() { yammer.New(os.Getenv("YAMMER_KEY"), os.Getenv("YAMMER_SECRET"), "http://localhost:3000/auth/yammer/callback"), onedrive.New(os.Getenv("ONEDRIVE_KEY"), os.Getenv("ONEDRIVE_SECRET"), "http://localhost:3000/auth/onedrive/callback"), - //Pointed localhost.com to http://localhost:3000/auth/yahoo/callback through proxy as yahoo + // Pointed localhost.com to http://localhost:3000/auth/yahoo/callback through proxy as yahoo // does not allow to put custom ports in redirection uri yahoo.New(os.Getenv("YAHOO_KEY"), os.Getenv("YAHOO_SECRET"), "http://localhost.com"), slack.New(os.Getenv("SLACK_KEY"), os.Getenv("SLACK_SECRET"), "http://localhost:3000/auth/slack/callback"), stripe.New(os.Getenv("STRIPE_KEY"), os.Getenv("STRIPE_SECRET"), "http://localhost:3000/auth/stripe/callback"), wepay.New(os.Getenv("WEPAY_KEY"), os.Getenv("WEPAY_SECRET"), "http://localhost:3000/auth/wepay/callback", "view_user"), - //By default paypal production auth urls will be used, please set PAYPAL_ENV=sandbox as environment variable for testing - //in sandbox environment + // By default paypal production auth urls will be used, please set PAYPAL_ENV=sandbox as environment variable for testing + // in sandbox environment paypal.New(os.Getenv("PAYPAL_KEY"), os.Getenv("PAYPAL_SECRET"), "http://localhost:3000/auth/paypal/callback"), steam.New(os.Getenv("STEAM_KEY"), "http://localhost:3000/auth/steam/callback"), heroku.New(os.Getenv("HEROKU_KEY"), os.Getenv("HEROKU_SECRET"), "http://localhost:3000/auth/heroku/callback"), @@ -292,7 +288,7 @@ func main() { discord.New(os.Getenv("DISCORD_KEY"), os.Getenv("DISCORD_SECRET"), "http://localhost:3000/auth/discord/callback", discord.ScopeIdentify, discord.ScopeEmail), meetup.New(os.Getenv("MEETUP_KEY"), os.Getenv("MEETUP_SECRET"), "http://localhost:3000/auth/meetup/callback"), - //Auth0 allocates domain per customer, a domain must be provided for auth0 to work + // Auth0 allocates domain per customer, a domain must be provided for auth0 to work auth0.New(os.Getenv("AUTH0_KEY"), os.Getenv("AUTH0_SECRET"), "http://localhost:3000/auth/auth0/callback", os.Getenv("AUTH0_DOMAIN")), xero.New(os.Getenv("XERO_KEY"), os.Getenv("XERO_SECRET"), "http://localhost:3000/auth/xero/callback"), ) @@ -305,45 +301,46 @@ func main() { goth.UseProviders(openidConnect) } - m := make(map[string]string) - m["amazon"] = "Amazon" - m["bitbucket"] = "Bitbucket" - m["box"] = "Box" - m["dailymotion"] = "Dailymotion" - m["deezer"] = "Deezer" - m["digitalocean"] = "Digital Ocean" - m["discord"] = "Discord" - m["dropbox"] = "Dropbox" - m["facebook"] = "Facebook" - m["fitbit"] = "Fitbit" - m["github"] = "Github" - m["gitlab"] = "Gitlab" - m["soundcloud"] = "SoundCloud" - m["spotify"] = "Spotify" - m["steam"] = "Steam" - m["stripe"] = "Stripe" - m["twitch"] = "Twitch" - m["uber"] = "Uber" - m["wepay"] = "Wepay" - m["yahoo"] = "Yahoo" - m["yammer"] = "Yammer" - m["gplus"] = "Google Plus" - m["heroku"] = "Heroku" - m["instagram"] = "Instagram" - m["intercom"] = "Intercom" - m["lastfm"] = "Last FM" - m["linkedin"] = "Linkedin" - m["onedrive"] = "Onedrive" - m["paypal"] = "Paypal" - m["twitter"] = "Twitter" - m["salesforce"] = "Salesforce" - m["slack"] = "Slack" - m["meetup"] = "Meetup.com" - m["auth0"] = "Auth0" - m["openid-connect"] = "OpenID Connect" - m["xero"] = "Xero" - - var keys []string + m := map[string]string{ + "amazon": "Amazon", + "bitbucket": "Bitbucket", + "box": "Box", + "dailymotion": "Dailymotion", + "deezer": "Deezer", + "digitalocean": "Digital Ocean", + "discord": "Discord", + "dropbox": "Dropbox", + "facebook": "Facebook", + "fitbit": "Fitbit", + "github": "Github", + "gitlab": "Gitlab", + "soundcloud": "SoundCloud", + "spotify": "Spotify", + "steam": "Steam", + "stripe": "Stripe", + "twitch": "Twitch", + "uber": "Uber", + "wepay": "Wepay", + "yahoo": "Yahoo", + "yammer": "Yammer", + "gplus": "Google Plus", + "heroku": "Heroku", + "instagram": "Instagram", + "intercom": "Intercom", + "lastfm": "Last FM", + "linkedin": "Linkedin", + "onedrive": "Onedrive", + "paypal": "Paypal", + "twitter": "Twitter", + "salesforce": "Salesforce", + "slack": "Slack", + "meetup": "Meetup.com", + "auth0": "Auth0", + "openid-connect": "OpenID Connect", + "xero": "Xero", + } + + keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } @@ -356,6 +353,7 @@ func main() { // set sessions // and setup the router for the showcase app := iris.New() + app.Logger().SetLevel("debug") // attach and build our templates app.RegisterView(iris.HTML("./templates", ".html")) @@ -363,16 +361,27 @@ func main() { // start of the router app.Get("/auth/{provider}/callback", func(ctx iris.Context) { - user, err := CompleteUserAuth(ctx) if err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.Writef("%v", err) + ctx.StopWithError(iris.StatusInternalServerError, err) return } - ctx.ViewData("", user) - if err := ctx.View("user.html"); err != nil { - ctx.Writef("%v", err) + + // Between handlers (user as root .): + // ctx.ViewData("", user) + // + // Between handlers (user as .user variable): + // ctx.ViewData("user", user) + // ---- + // Directly (user as root): + // ctx.View("user.html", user) + // + // Directly (user as .user variable): + if err := ctx.View("user.html", iris.Map{ + "user": user, + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -383,27 +392,27 @@ func main() { app.Get("/auth/{provider}", func(ctx iris.Context) { // try to get the user without re-authenticating - if gothUser, err := CompleteUserAuth(ctx); err == nil { - ctx.ViewData("", gothUser) - if err := ctx.View("user.html"); err != nil { - ctx.Writef("%v", err) - } - } else { + gothUser, err := CompleteUserAuth(ctx) + if err != nil { BeginAuthHandler(ctx) + return + } + + if err := ctx.View("user.html", gothUser); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) app.Get("/", func(ctx iris.Context) { - - ctx.ViewData("", providerIndex) - - if err := ctx.View("index.html"); err != nil { - ctx.Writef("%v", err) + if err := ctx.View("index.html", providerIndex); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) // http://localhost:3000 - app.Run(iris.Addr("localhost:3000")) + app.Listen("localhost:3000") } type ProviderIndex struct { diff --git a/authentication/oauth2/templates/index.html b/auth/goth/templates/index.html similarity index 100% rename from authentication/oauth2/templates/index.html rename to auth/goth/templates/index.html diff --git a/authentication/oauth2/templates/user.html b/auth/goth/templates/user.html similarity index 70% rename from authentication/oauth2/templates/user.html rename to auth/goth/templates/user.html index 10ab7c5c..363a5f6c 100644 --- a/authentication/oauth2/templates/user.html +++ b/auth/goth/templates/user.html @@ -8,4 +8,12 @@ <p>UserID: {{.UserID}}</p> <p>AccessToken: {{.AccessToken}}</p> <p>ExpiresAt: {{.ExpiresAt}}</p> -<p>RefreshToken: {{.RefreshToken}}</p> \ No newline at end of file +<p>RefreshToken: {{.RefreshToken}}</p> + +<hr/> + +<h3>Iterate all properties</h3> + +{{range $key, $value := .RawData}} + {{ $key }} => {{ $value }} <br/> +{{end}} diff --git a/auth/hcaptcha/hosts b/auth/hcaptcha/hosts new file mode 100644 index 00000000..d11c711b --- /dev/null +++ b/auth/hcaptcha/hosts @@ -0,0 +1,3 @@ +# https://docs.hcaptcha.com/#localdev +# Add to the end of your hosts file, e.g. on windows: C:/windows/system32/drivers/etc/hosts +127.0.0.1 yourdomain.com diff --git a/auth/hcaptcha/main.go b/auth/hcaptcha/main.go new file mode 100644 index 00000000..7d4e9298 --- /dev/null +++ b/auth/hcaptcha/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "os" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/hcaptcha" +) + +// Get the following values from: https://dashboard.hcaptcha.com +// Also, check: https://docs.hcaptcha.com/#localdev to test on local environment. +var ( + siteKey = os.Getenv("HCAPTCHA-SITE-KEY") + secretKey = os.Getenv("HCAPTCHA-SECRET-KEY") +) + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./templates", ".html")) + + hCaptcha := hcaptcha.New(secretKey) + app.Get("/register", registerForm) + app.Post("/register", hCaptcha, register) // See `hcaptcha.SiteVerify` for manual validation too. + + app.Logger().Infof("SiteKey = %s\tSecretKey = %s", + siteKey, secretKey) + + // GET: http://yourdomain.com/register + app.Listen(":80") +} + +func register(ctx iris.Context) { + hcaptchaResp, ok := hcaptcha.Get(ctx) + if !ok { + ctx.StatusCode(iris.StatusUnauthorized) + ctx.WriteString("Are you a bot?") + return + } + + ctx.Writef("Register action here...action was asked by a Human.\nResponse value is: %#+v", hcaptchaResp) +} + +func registerForm(ctx iris.Context) { + ctx.ViewData("SiteKey", siteKey) + if err := ctx.View("register_form.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/auth/hcaptcha/templates/register_form.html b/auth/hcaptcha/templates/register_form.html new file mode 100644 index 00000000..26a0cdc0 --- /dev/null +++ b/auth/hcaptcha/templates/register_form.html @@ -0,0 +1,18 @@ +<html> + +<head> + <title>hCaptcha Demo</title> + <script src="https://hcaptcha.com/1/api.js" async defer></script> +</head> + +<body> + <form action="/register" method="POST"> + <input type="text" name="email" placeholder="Email" /> + <input type="password" name="password" placeholder="Password" /> + <div class="h-captcha" data-sitekey="{{ .SiteKey }}"></div> + <br /> + <input type="submit" value="Submit" /> + </form> +</body> + +</html> \ No newline at end of file diff --git a/auth/jwt/basic/main.go b/auth/jwt/basic/main.go new file mode 100644 index 00000000..ddcb9a58 --- /dev/null +++ b/auth/jwt/basic/main.go @@ -0,0 +1,73 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" +) + +/* +Documentation: + https://github.com/kataras/jwt#table-of-contents +*/ + +// Replace with your own key and keep them secret. +// The "signatureSharedKey" is used for the HMAC(HS256) signature algorithm. +var signatureSharedKey = []byte("sercrethatmaycontainch@r32length") + +func main() { + app := iris.New() + + app.Get("/", generateToken) + app.Get("/protected", protected) + + app.Listen(":8080") +} + +type fooClaims struct { + Foo string `json:"foo"` +} + +func generateToken(ctx iris.Context) { + claims := fooClaims{ + Foo: "bar", + } + + // Sign and generate compact form token. + token, err := jwt.Sign(jwt.HS256, signatureSharedKey, claims, jwt.MaxAge(10*time.Minute)) + if err != nil { + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + tokenString := string(token) // or jwt.BytesToString + ctx.HTML(`Token: ` + tokenString + `<br/><br/> + <a href="/protected?token=` + tokenString + `">/protected?token=` + tokenString + `</a>`) +} + +func protected(ctx iris.Context) { + // Extract the token, e.g. cookie, Authorization: Bearer $token + // or URL query. + token := ctx.URLParam("token") + // Verify the token. + verifiedToken, err := jwt.Verify(jwt.HS256, signatureSharedKey, []byte(token)) + if err != nil { + ctx.StopWithStatus(iris.StatusUnauthorized) + return + } + + ctx.Writef("This is an authenticated request.\n\n") + + // Decode the custom claims. + var claims fooClaims + verifiedToken.Claims(&claims) + + // Just an example on how you can retrieve all the standard claims (set by jwt.MaxAge, "exp"). + standardClaims := jwt.GetVerifiedToken(ctx).StandardClaims + + expiresAtString := standardClaims.ExpiresAt().Format(ctx.Application().ConfigurationReadOnly().GetTimeFormat()) + timeLeft := standardClaims.Timeleft() + + ctx.Writef("foo=%s\nexpires at: %s\ntime left: %s\n", claims.Foo, expiresAtString, timeLeft) +} diff --git a/auth/jwt/blocklist/main.go b/auth/jwt/blocklist/main.go new file mode 100644 index 00000000..8f3362c8 --- /dev/null +++ b/auth/jwt/blocklist/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" + "github.com/kataras/iris/v12/middleware/jwt/blocklist/redis" + + // Optionally to set token identifier. + "github.com/google/uuid" +) + +var ( + signatureSharedKey = []byte("sercrethatmaycontainch@r32length") + + signer = jwt.NewSigner(jwt.HS256, signatureSharedKey, 15*time.Minute) + verifier = jwt.NewVerifier(jwt.HS256, signatureSharedKey) +) + +type userClaims struct { + Username string `json:"username"` +} + +func main() { + app := iris.New() + + // IMPORTANT + // + // To use the in-memory blocklist just: + // verifier.WithDefaultBlocklist() + // To use a persistence blocklist, e.g. redis, + // start your redis-server and: + blocklist := redis.NewBlocklist() + // To configure single client or a cluster one: + // blocklist.ClientOptions.Addr = "127.0.0.1:6379" + // blocklist.ClusterOptions.Addrs = []string{...} + // To set a prefix for jwt ids: + // blocklist.Prefix = "myapp-" + // + // To manually connect and check its error before continue: + // err := blocklist.Connect() + // By default the verifier will try to connect, if failed then it will throw http error. + // + // And then register it: + verifier.Blocklist = blocklist + verifyMiddleware := verifier.Verify(func() interface{} { + return new(userClaims) + }) + + app.Get("/", authenticate) + + protectedAPI := app.Party("/protected", verifyMiddleware) + protectedAPI.Get("/", protected) + protectedAPI.Get("/logout", logout) + + // http://localhost:8080 + // http://localhost:8080/protected?token=$token + // http://localhost:8080/logout?token=$token + // http://localhost:8080/protected?token=$token (401) + app.Listen(":8080") +} + +func authenticate(ctx iris.Context) { + claims := userClaims{ + Username: "kataras", + } + + // Generate JWT ID. + random, err := uuid.NewRandom() + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + id := random.String() + + // Set the ID with the jwt.ID. + token, err := signer.Sign(claims, jwt.ID(id)) + + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Write(token) +} + +func protected(ctx iris.Context) { + claims := jwt.Get(ctx).(*userClaims) + + // To the standard claims, e.g. the generated ID: + // jwt.GetVerifiedToken(ctx).StandardClaims.ID + + ctx.WriteString(claims.Username) +} + +func logout(ctx iris.Context) { + ctx.Logout() + + ctx.Redirect("/", iris.StatusTemporaryRedirect) +} diff --git a/auth/jwt/middleware/main.go b/auth/jwt/middleware/main.go new file mode 100644 index 00000000..a33a17e1 --- /dev/null +++ b/auth/jwt/middleware/main.go @@ -0,0 +1,91 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" +) + +var ( + sigKey = []byte("signature_hmac_secret_shared_key") + // encKey = []byte("GCM_AES_256_secret_shared_key_32") +) + +type fooClaims struct { + Foo string `json:"foo"` +} + +/* +In this example you will learn the essentials +of the Iris builtin JWT middleware based on the github.com/kataras/jwt package. +*/ + +func main() { + app := iris.New() + + signer := jwt.NewSigner(jwt.HS256, sigKey, 10*time.Minute) + // Enable payload encryption with: + // signer.WithEncryption(encKey, nil) + app.Get("/", generateToken(signer)) + + verifier := jwt.NewVerifier(jwt.HS256, sigKey) + // Enable server-side token block feature (even before its expiration time): + verifier.WithDefaultBlocklist() + // Enable payload decryption with: + // verifier.WithDecryption(encKey, nil) + verifyMiddleware := verifier.Verify(func() interface{} { + return new(fooClaims) + }) + + protectedAPI := app.Party("/protected") + // Register the verify middleware to allow access only to authorized clients. + protectedAPI.Use(verifyMiddleware) + // ^ or UseRouter(verifyMiddleware) to disallow unauthorized http error handlers too. + + protectedAPI.Get("/", protected) + // Invalidate the token through server-side, even if it's not expired yet. + protectedAPI.Get("/logout", logout) + + // http://localhost:8080 + // http://localhost:8080/protected?token=$token (or Authorization: Bearer $token) + // http://localhost:8080/protected/logout?token=$token + // http://localhost:8080/protected?token=$token (401) + app.Listen(":8080") +} + +func generateToken(signer *jwt.Signer) iris.Handler { + return func(ctx iris.Context) { + claims := fooClaims{Foo: "bar"} + + token, err := signer.Sign(claims) + if err != nil { + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + ctx.Write(token) + } +} + +func protected(ctx iris.Context) { + // Get the verified and decoded claims. + claims := jwt.Get(ctx).(*fooClaims) + + // Optionally, get token information if you want to work with them. + // Just an example on how you can retrieve all the standard claims (set by signer's max age, "exp"). + standardClaims := jwt.GetVerifiedToken(ctx).StandardClaims + expiresAtString := standardClaims.ExpiresAt().Format(ctx.Application().ConfigurationReadOnly().GetTimeFormat()) + timeLeft := standardClaims.Timeleft() + + ctx.Writef("foo=%s\nexpires at: %s\ntime left: %s\n", claims.Foo, expiresAtString, timeLeft) +} + +func logout(ctx iris.Context) { + err := ctx.Logout() + if err != nil { + ctx.WriteString(err.Error()) + } else { + ctx.Writef("token invalidated, a new token is required to access the protected API") + } +} diff --git a/auth/jwt/refresh-token/main.go b/auth/jwt/refresh-token/main.go new file mode 100644 index 00000000..1e6ca587 --- /dev/null +++ b/auth/jwt/refresh-token/main.go @@ -0,0 +1,183 @@ +package main + +import ( + "fmt" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" +) + +const ( + accessTokenMaxAge = 10 * time.Minute + refreshTokenMaxAge = time.Hour +) + +var ( + privateKey, publicKey = jwt.MustLoadRSA("rsa_private_key.pem", "rsa_public_key.pem") + + signer = jwt.NewSigner(jwt.RS256, privateKey, accessTokenMaxAge) + verifier = jwt.NewVerifier(jwt.RS256, publicKey) +) + +// UserClaims a custom access claims structure. +type UserClaims struct { + ID string `json:"user_id"` + // Do: `json:"username,required"` to have this field required + // or see the Validate method below instead. + Username string `json:"username"` +} + +// GetID implements the partial context user's ID interface. +// Note that if claims were a map then the claims value converted to UserClaims +// and no need to implement any method. +// +// This is useful when multiple auth methods are used (e.g. basic auth, jwt) +// but they all share a couple of methods. +func (u *UserClaims) GetID() string { + return u.ID +} + +// GetUsername implements the partial context user's Username interface. +func (u *UserClaims) GetUsername() string { + return u.Username +} + +// Validate completes the middleware's custom ClaimsValidator. +// It will not accept a token which its claims missing the username field +// (useful to not accept refresh tokens generated by the same algorithm). +func (u *UserClaims) Validate() error { + if u.Username == "" { + return fmt.Errorf("username field is missing") + } + + return nil +} + +// For refresh token, we will just use the jwt.Claims +// structure which contains the standard JWT fields. + +func main() { + app := iris.New() + app.OnErrorCode(iris.StatusUnauthorized, handleUnauthorized) + + app.Get("/authenticate", generateTokenPair) + app.Get("/refresh", refreshToken) + + protectedAPI := app.Party("/protected") + { + verifyMiddleware := verifier.Verify(func() interface{} { + return new(UserClaims) + }) + + protectedAPI.Use(verifyMiddleware) + + protectedAPI.Get("/", func(ctx iris.Context) { + // Access the claims through: jwt.Get: + // claims := jwt.Get(ctx).(*UserClaims) + // ctx.Writef("Username: %s\n", claims.Username) + // + // OR through context's user (if at least one method was implement by our UserClaims): + user := ctx.User() + id, _ := user.GetID() + username, _ := user.GetUsername() + ctx.Writef("ID: %s\nUsername: %s\n", id, username) + }) + } + + // http://localhost:8080/protected (401) + // http://localhost:8080/authenticate (200) (response JSON {access_token, refresh_token}) + // http://localhost:8080/protected?token={access_token} (200) + // http://localhost:8080/protected?token={refresh_token} (401) + // http://localhost:8080/refresh?refresh_token={refresh_token} + // OR http://localhost:8080/refresh (request JSON{refresh_token = {refresh_token}}) (200) (response JSON {access_token, refresh_token}) + // http://localhost:8080/refresh?refresh_token={access_token} (401) + app.Listen(":8080") +} + +func generateTokenPair(ctx iris.Context) { + // Simulate a user... + userID := "53afcf05-38a3-43c3-82af-8bbbe0e4a149" + + // Map the current user with the refresh token, + // so we make sure, on refresh route, that this refresh token owns + // to that user before re-generate. + refreshClaims := jwt.Claims{Subject: userID} + + accessClaims := UserClaims{ + ID: userID, + Username: "kataras", + } + + // Generates a Token Pair, long-live for refresh tokens, e.g. 1 hour. + // First argument is the access claims, + // second argument is the refresh claims, + // third argument is the refresh max age. + tokenPair, err := signer.NewTokenPair(accessClaims, refreshClaims, refreshTokenMaxAge) + if err != nil { + ctx.Application().Logger().Errorf("token pair: %v", err) + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + // Send the generated token pair to the client. + // The tokenPair looks like: {"access_token": $token, "refresh_token": $token} + ctx.JSON(tokenPair) +} + +// There are various methods of refresh token, depending on the application requirements. +// In this example we will accept a refresh token only, we will verify only a refresh token +// and we re-generate a whole new pair. An alternative would be to accept a token pair +// of both access and refresh tokens, verify the refresh, verify the access with a Leeway time +// and check if its going to expire soon, then generate a single access token. +func refreshToken(ctx iris.Context) { + // Assuming you have access to the current user, e.g. sessions. + // + // Simulate a database call against our jwt subject + // to make sure that this refresh token is a pair generated by this user. + // * Note: You can remove the ExpectSubject and do this validation later on by yourself. + currentUserID := "53afcf05-38a3-43c3-82af-8bbbe0e4a149" + + // Get the refresh token from ?refresh_token=$token OR + // the request body's JSON{"refresh_token": "$token"}. + refreshToken := []byte(ctx.URLParam("refresh_token")) + if len(refreshToken) == 0 { + // You can read the whole body with ctx.GetBody/ReadBody too. + var tokenPair jwt.TokenPair + if err := ctx.ReadJSON(&tokenPair); err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + refreshToken = tokenPair.RefreshToken + } + + // Verify the refresh token, which its subject MUST match the "currentUserID". + _, err := verifier.VerifyToken(refreshToken, jwt.Expected{Subject: currentUserID}) + if err != nil { + ctx.Application().Logger().Errorf("verify refresh token: %v", err) + ctx.StatusCode(iris.StatusUnauthorized) + return + } + + /* Custom validation checks can be performed after Verify calls too: + currentUserID := "53afcf05-38a3-43c3-82af-8bbbe0e4a149" + userID := verifiedToken.StandardClaims.Subject + if userID != currentUserID { + ctx.StopWithStatus(iris.StatusUnauthorized) + return + } + */ + + // All OK, re-generate the new pair and send to client, + // we could only generate an access token as well. + generateTokenPair(ctx) +} + +func handleUnauthorized(ctx iris.Context) { + if err := ctx.GetErr(); err != nil { + ctx.Application().Logger().Errorf("unauthorized: %v", err) + } + + ctx.WriteString("Unauthorized") +} diff --git a/auth/jwt/refresh-token/rsa_private_key.pem b/auth/jwt/refresh-token/rsa_private_key.pem new file mode 100644 index 00000000..411e3a89 --- /dev/null +++ b/auth/jwt/refresh-token/rsa_private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN PRIVATE KEY----- +MIIEowIBAAKCAQEArwO0q8WbBvrplz3lTQjsWu66HC7M3mVAjmjLq8Wj/ipqVtiJ +MrUL9t/0q9PNO/KX9u+HayFNYM4TnYkXVZX3M5E31W8fPPy74D/XpqFwrwT7bAEw +pT51JJyxkoBAyOh08lmR2EYvpGF7qErra7qbkk4LGFbhoFCXdMLXguT4rPymkzFH +dQrmGYOBS+v9imSuJddCZpXyv6Ko7AKB4mhzg4RC5RJZO5GEHVUrSMHxZB0syF8c +U+28iL8A7SlGKTNZPZiHmCQVRqA6WlllL/YV/t6p24kaNZBUp9JGbAzOeKuVUv2u +vfNKwB/aBwnFKauM9I6RmC4bnI1nGHjETlNNWwIDAQABAoIBAHBPKHmybTGlgpET +nzo4J7SSzcuYHM/6mdrJVSn9wqcwAN2KR0DK/cqHHTPGz0VRAEPuojAVRtqAZAYM +G3VIr0HgRrwoextf9BCL549+uhkWUWGVwenIktPT2f/xXaGPyrxazkTDhX8vL3Nn +4HtZXMweWPBdkJyYGxlKj5Hn7czTpG3VKpvpHeFlY4caF+FT2as1jcQ1MjPnGslH +Ss+sYPBp/70w2T114Z4wlR4OryI1LeuFeje9obrn0HAmJd0ZKYM21awp/YWJ/y8J +wIH6XQ4AGR9iTRhuffK1XRM/Iec3K/YhOn4PtKdT7OsIujAKY7A9WcqSFif+/E1g +jom3eMECgYEAw5Zdqt2uZ19FuDlDTW4Kw8Z2NyXgWp33LkAXG1mJw7bqDhfPeB1c +xTPs4i4RubGuDusygxZ3GgJAO7tLGzNQfWNoi03mM7Q/BJGkA9VZr+U28zsSRQOQ ++J9xNsdgUMP1js7X/NNM2bxTC8zy9wEsWr9JwNo1C7uHTE9WXAumBI8CgYEA5RKV +niSbyko36W3Vi0ZnGBrRhy0Eiq85V2mhWzHN+txcv+8aISow2wioTUzrpR0aVZ4j +v9+siJENlALVzdUFihy0lPxHqLJT746Cixz95WRTLkdHeNllV0DMfOph2x3j1Hjd +3PgTv+jqb6npY0/2Vb2pp4t/zVikGaObsAalSHUCgYBne8B1bjMfqI3n6gxNBIMX +kILtrNGmwFuPEgPnyZkVf0sZR8nSwJ5cDJwyE7P3LyZr6E9igllj3nsD35Xef2j/ +3r/qrL2275BEJ5bDHHgGk91eFgwVjcx/b0TkedrhAL2E4LXwpA/OSFEcNkT7IZjJ +Ltqj+hAE9CSi4HtN2i/tywKBgBotKn28zzSpkIQTMgDNVcCSZ/kbctZqOZI8lty1 +70TIY6znJMQ/bv/ImHrk3FSs47J+9LTbWXrtoHCWdlokCpMCvrv7rDCh2Cea0F4X +PQg2k67JJGix5vu2guePXQlN/Bfui+PRUWhvtEJ4VxwrKgoYN0fXEA6mH3JymLrf +t4l1AoGBALk4o9swGjw7MnByYJmOidlJ0p9Wj1BWWJJYoYX2VfjIuvZj6BNxkEb0 +aVmYRC+40e9L1rOyrlyaO/TiQaIPE4ljVs/AmMKGz8sIcVfwdyERH3nDrXxvlAav +lSvfKoYM3J+5c63CDuU45gztpmavNerzCczqYTLOEMx1eCLHOQlx +-----END PRIVATE KEY----- diff --git a/auth/jwt/refresh-token/rsa_public_key.pem b/auth/jwt/refresh-token/rsa_public_key.pem new file mode 100644 index 00000000..99a96176 --- /dev/null +++ b/auth/jwt/refresh-token/rsa_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwO0q8WbBvrplz3lTQjs +Wu66HC7M3mVAjmjLq8Wj/ipqVtiJMrUL9t/0q9PNO/KX9u+HayFNYM4TnYkXVZX3 +M5E31W8fPPy74D/XpqFwrwT7bAEwpT51JJyxkoBAyOh08lmR2EYvpGF7qErra7qb +kk4LGFbhoFCXdMLXguT4rPymkzFHdQrmGYOBS+v9imSuJddCZpXyv6Ko7AKB4mhz +g4RC5RJZO5GEHVUrSMHxZB0syF8cU+28iL8A7SlGKTNZPZiHmCQVRqA6WlllL/YV +/t6p24kaNZBUp9JGbAzOeKuVUv2uvfNKwB/aBwnFKauM9I6RmC4bnI1nGHjETlNN +WwIDAQAB +-----END PUBLIC KEY----- diff --git a/auth/jwt/tutorial/README.md b/auth/jwt/tutorial/README.md new file mode 100644 index 00000000..5a52c56b --- /dev/null +++ b/auth/jwt/tutorial/README.md @@ -0,0 +1,62 @@ +# Iris JWT Tutorial + +This example show how to use JWT with domain-driven design pattern with Iris. There is also a simple Go client which describes how you can use Go to authorize a user and use the server's API. + +## Run the server + +```sh +$ go run main.go +``` + +## Authenticate, get the token + +```sh +$ curl --location --request POST 'http://localhost:8080/signin' \ +--header 'Content-Type: application/x-www-form-urlencoded' \ +--data-urlencode 'username=admin' \ +--data-urlencode 'password=admin' + +> $token +``` + +## Get all TODOs for this User + +```sh +$ curl --location --request GET 'http://localhost:8080/todos' \ +--header 'Authorization: Bearer $token' + +> $todos +``` + +## Get a specific User's TODO + +```sh +$ curl --location --request GET 'http://localhost:8080/todos/$id' \ +--header 'Authorization: Bearer $token' + +> $todo +``` + +## Get all TODOs for all Users (admin role) + +```sh +$ curl --location --request GET 'http://localhost:8080/admin/todos' \ +--header 'Authorization: Bearer $token' + +> $todos +``` + +## Create a new TODO + +```sh +$ curl --location --request POST 'http://localhost:8080/todos' \ +--header 'Authorization: Bearer $token' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "title": "test titlte", + "body": "test body" +}' + +> Status Created +> $todo +``` diff --git a/auth/jwt/tutorial/api/auth.go b/auth/jwt/tutorial/api/auth.go new file mode 100644 index 00000000..2e540e09 --- /dev/null +++ b/auth/jwt/tutorial/api/auth.go @@ -0,0 +1,140 @@ +package api + +import ( + "fmt" + "os" + "time" + + "myapp/domain/model" + "myapp/domain/repository" + "myapp/util" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" +) + +const defaultSecretKey = "sercrethatmaycontainch@r$32chars" + +func getSecretKey() string { + secret := os.Getenv(util.AppName + "_SECRET") + if secret == "" { + return defaultSecretKey + } + + return secret +} + +// UserClaims represents the user token claims. +type UserClaims struct { + UserID string `json:"user_id"` + Roles []model.Role `json:"roles"` +} + +// Validate implements the custom struct claims validator, +// this is totally optionally and maybe unnecessary but good to know how. +func (u *UserClaims) Validate() error { + if u.UserID == "" { + return fmt.Errorf("%w: %s", jwt.ErrMissingKey, "user_id") + } + + return nil +} + +// Verify allows only authorized clients. +func Verify() iris.Handler { + secret := getSecretKey() + + verifier := jwt.NewVerifier(jwt.HS256, []byte(secret), jwt.Expected{Issuer: util.AppName}) + verifier.Extractors = []jwt.TokenExtractor{jwt.FromHeader} // extract token only from Authorization: Bearer $token + return verifier.Verify(func() interface{} { + return new(UserClaims) + }) +} + +// AllowAdmin allows only authorized clients with "admin" access role. +// Should be registered after Verify. +func AllowAdmin(ctx iris.Context) { + if !IsAdmin(ctx) { + ctx.StopWithText(iris.StatusForbidden, "admin access required") + return + } + + ctx.Next() +} + +// SignIn accepts the user form data and returns a token to authorize a client. +func SignIn(repo repository.UserRepository) iris.Handler { + secret := getSecretKey() + signer := jwt.NewSigner(jwt.HS256, []byte(secret), 15*time.Minute) + + return func(ctx iris.Context) { + /* + type LoginForm struct { + Username string `form:"username"` + Password string `form:"password"` + } + and ctx.ReadForm OR use the ctx.FormValue(s) method. + */ + + var ( + username = ctx.FormValue("username") + password = ctx.FormValue("password") + ) + + user, ok := repo.GetByUsernameAndPassword(username, password) + if !ok { + ctx.StopWithText(iris.StatusBadRequest, "wrong username or password") + return + } + + claims := UserClaims{ + UserID: user.ID, + Roles: user.Roles, + } + + // Optionally, generate a JWT ID. + jti, err := util.GenerateUUID() + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + token, err := signer.Sign(claims, jwt.Claims{ + ID: jti, + Issuer: util.AppName, + }) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Write(token) + } +} + +// SignOut invalidates a user from server-side using the jwt Blocklist. +func SignOut(ctx iris.Context) { + ctx.Logout() // this is automatically binded to a function which invalidates the current request token by the JWT Verifier above. +} + +// GetClaims returns the current authorized client claims. +func GetClaims(ctx iris.Context) *UserClaims { + claims := jwt.Get(ctx).(*UserClaims) + return claims +} + +// GetUserID returns the current authorized client's user id extracted from claims. +func GetUserID(ctx iris.Context) string { + return GetClaims(ctx).UserID +} + +// IsAdmin reports whether the current client has admin access. +func IsAdmin(ctx iris.Context) bool { + for _, role := range GetClaims(ctx).Roles { + if role == model.Admin { + return true + } + } + + return false +} diff --git a/auth/jwt/tutorial/api/router.go b/auth/jwt/tutorial/api/router.go new file mode 100644 index 00000000..506260bc --- /dev/null +++ b/auth/jwt/tutorial/api/router.go @@ -0,0 +1,23 @@ +package api + +import ( + "myapp/domain/repository" + + "github.com/kataras/iris/v12" +) + +// NewRouter accepts some dependencies +// and returns a function which returns the routes on the given Iris Party (group of routes). +func NewRouter(userRepo repository.UserRepository, todoRepo repository.TodoRepository) func(iris.Party) { + return func(router iris.Party) { + router.Post("/signin", SignIn(userRepo)) + + router.Use(Verify()) // protect the next routes with JWT. + + router.Post("/todos", CreateTodo(todoRepo)) + router.Get("/todos", ListTodos(todoRepo)) + router.Get("/todos/{id}", GetTodo(todoRepo)) + + router.Get("/admin/todos", AllowAdmin, ListAllTodos(todoRepo)) + } +} diff --git a/auth/jwt/tutorial/api/todo.go b/auth/jwt/tutorial/api/todo.go new file mode 100644 index 00000000..317494e8 --- /dev/null +++ b/auth/jwt/tutorial/api/todo.go @@ -0,0 +1,119 @@ +package api + +import ( + "errors" + "myapp/domain/repository" + + "github.com/kataras/iris/v12" +) + +// TodoRequest represents a Todo HTTP request. +type TodoRequest struct { + Title string `json:"title" form:"title" url:"title"` + Body string `json:"body" form:"body" url:"body"` +} + +// CreateTodo handles the creation of a Todo entry. +func CreateTodo(repo repository.TodoRepository) iris.Handler { + return func(ctx iris.Context) { + var req TodoRequest + err := ctx.ReadBody(&req) // will bind the "req" to a JSON, form or url query request data. + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + userID := GetUserID(ctx) + todo, err := repo.Create(userID, req.Title, req.Body) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.StatusCode(iris.StatusCreated) + ctx.JSON(todo) + } +} + +// GetTodo lists all users todos. +// Parameter: {id}. +func GetTodo(repo repository.TodoRepository) iris.Handler { + return func(ctx iris.Context) { + id := ctx.Params().Get("id") + userID := GetUserID(ctx) + + todo, err := repo.GetByID(id) + if err != nil { + code := iris.StatusInternalServerError + if errors.Is(err, repository.ErrNotFound) { + code = iris.StatusNotFound + } + + ctx.StopWithError(code, err) + return + } + + if !IsAdmin(ctx) { // admin can access any user's todos. + if todo.UserID != userID { + ctx.StopWithStatus(iris.StatusForbidden) + return + } + } + + ctx.JSON(todo) + } +} + +// ListTodos lists todos of the current user. +func ListTodos(repo repository.TodoRepository) iris.Handler { + return func(ctx iris.Context) { + userID := GetUserID(ctx) + todos, err := repo.GetAllByUser(userID) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + // if len(todos) == 0 { + // ctx.StopWithError(iris.StatusNotFound, fmt.Errorf("no entries found")) + // return + // } + // Or let the client decide what to do on empty list. + ctx.JSON(todos) + } +} + +// ListAllTodos lists all users todos. +// Access: admin. +// Middleware: AllowAdmin. +func ListAllTodos(repo repository.TodoRepository) iris.Handler { + return func(ctx iris.Context) { + todos, err := repo.GetAll() + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.JSON(todos) + } +} + +/* Leave as exercise: use filtering instead... + +// ListTodosByUser lists all todos by a specific user. +// Access: admin. +// Middleware: AllowAdmin. +// Parameter: {id}. +func ListTodosByUser(repo repository.TodoRepository) iris.Handler { + return func(ctx iris.Context) { + userID := ctx.Params().Get("id") + todos, err := repo.GetAllByUser(userID) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.JSON(todos) + } +} +*/ diff --git a/auth/jwt/tutorial/domain/model/role.go b/auth/jwt/tutorial/domain/model/role.go new file mode 100644 index 00000000..00fd1c25 --- /dev/null +++ b/auth/jwt/tutorial/domain/model/role.go @@ -0,0 +1,9 @@ +package model + +// Role represents a role. +type Role string + +const ( + // Admin represents the Admin access role. + Admin Role = "admin" +) diff --git a/auth/jwt/tutorial/domain/model/todo.go b/auth/jwt/tutorial/domain/model/todo.go new file mode 100644 index 00000000..d0a2ea27 --- /dev/null +++ b/auth/jwt/tutorial/domain/model/todo.go @@ -0,0 +1,10 @@ +package model + +// Todo represents the Todo model. +type Todo struct { + ID string `json:"id"` + UserID string `json:"user_id"` + Title string `json:"title"` + Body string `json:"body"` + CreatedAt int64 `json:"created_at"` // unix seconds. +} diff --git a/auth/jwt/tutorial/domain/model/user.go b/auth/jwt/tutorial/domain/model/user.go new file mode 100644 index 00000000..9fa8bcdf --- /dev/null +++ b/auth/jwt/tutorial/domain/model/user.go @@ -0,0 +1,9 @@ +package model + +// User represents our User model. +type User struct { + ID string `json:"id"` + Username string `json:"username"` + HashedPassword []byte `json:"-"` + Roles []Role `json:"roles"` +} diff --git a/auth/jwt/tutorial/domain/repository/samples.go b/auth/jwt/tutorial/domain/repository/samples.go new file mode 100644 index 00000000..b7d267ba --- /dev/null +++ b/auth/jwt/tutorial/domain/repository/samples.go @@ -0,0 +1,45 @@ +package repository + +import ( + "fmt" + + "myapp/domain/model" +) + +// GenerateSamples generates data samples. +func GenerateSamples(userRepo UserRepository, todoRepo TodoRepository) error { + // Create users. + for _, username := range []string{"vasiliki", "george", "kwstas"} { + // My grandmother. + // My young brother. + // My youngest brother. + password := fmt.Sprintf("%s_pass", username) + if _, err := userRepo.Create(username, password); err != nil { + return err + } + } + + // Create a user with admin role. + if _, err := userRepo.Create("admin", "admin", model.Admin); err != nil { + return err + } + + // Create two todos per user. + users, err := userRepo.GetAll() + if err != nil { + return err + } + + for i, u := range users { + for j := 0; j < 2; j++ { + title := fmt.Sprintf("%s todo %d:%d title", u.Username, i, j) + body := fmt.Sprintf("%s todo %d:%d body", u.Username, i, j) + _, err := todoRepo.Create(u.ID, title, body) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/auth/jwt/tutorial/domain/repository/todo_repository.go b/auth/jwt/tutorial/domain/repository/todo_repository.go new file mode 100644 index 00000000..a3c8429f --- /dev/null +++ b/auth/jwt/tutorial/domain/repository/todo_repository.go @@ -0,0 +1,94 @@ +package repository + +import ( + "errors" + "sync" + + "myapp/domain/model" + "myapp/util" +) + +// ErrNotFound indicates that an entry was not found. +// Usage: errors.Is(err, ErrNotFound) +var ErrNotFound = errors.New("not found") + +// TodoRepository is responsible for Todo CRUD operations, +// however, for the sake of the example we only implement the Create and Read ones. +type TodoRepository interface { + Create(userID, title, body string) (model.Todo, error) + GetByID(id string) (model.Todo, error) + GetAll() ([]model.Todo, error) + GetAllByUser(userID string) ([]model.Todo, error) +} + +var ( + _ TodoRepository = (*memoryTodoRepository)(nil) +) + +type memoryTodoRepository struct { + todos []model.Todo // map[string]model.Todo + mu sync.RWMutex +} + +// NewMemoryTodoRepository returns the default in-memory todo repository. +func NewMemoryTodoRepository() TodoRepository { + r := new(memoryTodoRepository) + return r +} + +func (r *memoryTodoRepository) Create(userID, title, body string) (model.Todo, error) { + id, err := util.GenerateUUID() + if err != nil { + return model.Todo{}, err + } + + todo := model.Todo{ + ID: id, + UserID: userID, + Title: title, + Body: body, + CreatedAt: util.Now().Unix(), + } + + r.mu.Lock() + r.todos = append(r.todos, todo) + r.mu.Unlock() + + return todo, nil +} + +func (r *memoryTodoRepository) GetByID(id string) (model.Todo, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + for _, todo := range r.todos { + if todo.ID == id { + return todo, nil + } + } + + return model.Todo{}, ErrNotFound +} + +func (r *memoryTodoRepository) GetAll() ([]model.Todo, error) { + r.mu.RLock() + tmp := make([]model.Todo, len(r.todos)) + copy(tmp, r.todos) + r.mu.RUnlock() + return tmp, nil +} + +func (r *memoryTodoRepository) GetAllByUser(userID string) ([]model.Todo, error) { + // initialize a slice, so we don't have "null" at empty response. + todos := make([]model.Todo, 0) + + r.mu.RLock() + for _, todo := range r.todos { + if todo.UserID == userID { + todos = append(todos, todo) + } + } + r.mu.RUnlock() + + return todos, nil +} diff --git a/auth/jwt/tutorial/domain/repository/user_repository.go b/auth/jwt/tutorial/domain/repository/user_repository.go new file mode 100644 index 00000000..b6e0bd76 --- /dev/null +++ b/auth/jwt/tutorial/domain/repository/user_repository.go @@ -0,0 +1,82 @@ +package repository + +import ( + "sync" + + "myapp/domain/model" + "myapp/util" +) + +// UserRepository is responsible for User CRUD operations, +// however, for the sake of the example we only implement the Read one. +type UserRepository interface { + Create(username, password string, roles ...model.Role) (model.User, error) + // GetByUsernameAndPassword should return a User based on the given input. + GetByUsernameAndPassword(username, password string) (model.User, bool) + GetAll() ([]model.User, error) +} + +var ( + _ UserRepository = (*memoryUserRepository)(nil) +) + +type memoryUserRepository struct { + // Users represents a user database. + // For the sake of the tutorial we use a simple slice of users. + users []model.User + mu sync.RWMutex +} + +// NewMemoryUserRepository returns the default in-memory user repository. +func NewMemoryUserRepository() UserRepository { + r := new(memoryUserRepository) + return r +} + +func (r *memoryUserRepository) Create(username, password string, roles ...model.Role) (model.User, error) { + id, err := util.GenerateUUID() + if err != nil { + return model.User{}, err + } + + hashedPassword, err := util.GeneratePassword(password) + if err != nil { + return model.User{}, err + } + + user := model.User{ + ID: id, + Username: username, + HashedPassword: hashedPassword, + Roles: roles, + } + + r.mu.Lock() + r.users = append(r.users, user) + r.mu.Unlock() + + return user, nil +} + +// GetByUsernameAndPassword returns a user from the storage based on the given "username" and "password". +func (r *memoryUserRepository) GetByUsernameAndPassword(username, password string) (model.User, bool) { + for _, u := range r.users { // our example uses a static slice. + if u.Username == username { + // we compare the user input and the stored hashed password. + ok := util.ValidatePassword(password, u.HashedPassword) + if ok { + return u, true + } + } + } + + return model.User{}, false +} + +func (r *memoryUserRepository) GetAll() ([]model.User, error) { + r.mu.RLock() + tmp := make([]model.User, len(r.users)) + copy(tmp, r.users) + r.mu.RUnlock() + return tmp, nil +} diff --git a/auth/jwt/tutorial/go-client/README.md b/auth/jwt/tutorial/go-client/README.md new file mode 100644 index 00000000..f7a96a9c --- /dev/null +++ b/auth/jwt/tutorial/go-client/README.md @@ -0,0 +1,12 @@ +# Go Client + +```sh +$ go run . +``` + +```sh +2020/11/04 21:08:40 Access Token: +"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYTAwYzI3ZDEtYjVhYS00NjU0LWFmMTYtYjExNzNkZTY1NjI5Iiwicm9sZXMiOlsiYWRtaW4iXSwiaWF0IjoxNjA0NTE2OTIwLCJleHAiOjE2MDQ1MTc4MjAsImp0aSI6IjYzNmVmMDc0LTE2MzktNGJhZi1hNGNiLTQ4ZDM4NGMxMzliYSIsImlzcyI6Im15YXBwIn0.T9B0zG0AHShO5JfQgrMQBlToH33KHgp8nLMPFpN6QmM" +2020/11/04 21:08:40 Todo Created: +model.Todo{ID:"cfa38d7a-c556-4301-ae1f-fb90f705071c", UserID:"a00c27d1-b5aa-4654-af16-b1173de65629", Title:"test todo title", Body:"test todo body contents", CreatedAt:1604516920} +``` diff --git a/auth/jwt/tutorial/go-client/client.go b/auth/jwt/tutorial/go-client/client.go new file mode 100644 index 00000000..9ca27c9d --- /dev/null +++ b/auth/jwt/tutorial/go-client/client.go @@ -0,0 +1,108 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" +) + +// Client is the default http client instance used by the following methods. +var Client = http.DefaultClient + +// RequestOption is a function which can be used to modify +// a request instance before Do. +type RequestOption func(*http.Request) error + +// WithAccessToken sets the given "token" to the authorization request header. +func WithAccessToken(token []byte) RequestOption { + bearer := "Bearer " + string(token) + return func(req *http.Request) error { + req.Header.Add("Authorization", bearer) + return nil + } +} + +// WithContentType sets the content-type request header. +func WithContentType(cType string) RequestOption { + return func(req *http.Request) error { + req.Header.Set("Content-Type", cType) + return nil + } +} + +// WithContentLength sets the content-length request header. +func WithContentLength(length int) RequestOption { + return func(req *http.Request) error { + req.Header.Set("Content-Length", strconv.Itoa(length)) + return nil + } +} + +// Do fires a request to the server. +func Do(method, url string, body io.Reader, opts ...RequestOption) (*http.Response, error) { + req, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + for _, opt := range opts { + if err = opt(req); err != nil { + return nil, err + } + } + + return Client.Do(req) +} + +// JSON fires a request with "v" as client json data. +func JSON(method, url string, v interface{}, opts ...RequestOption) (*http.Response, error) { + buf := new(bytes.Buffer) + err := json.NewEncoder(buf).Encode(v) + if err != nil { + return nil, err + } + + opts = append(opts, WithContentType("application/json; charset=utf-8")) + return Do(method, url, buf, opts...) +} + +// Form fires a request with "formData" as client form data. +func Form(method, url string, formData url.Values, opts ...RequestOption) (*http.Response, error) { + encoded := formData.Encode() + body := strings.NewReader(encoded) + + opts = append([]RequestOption{ + WithContentType("application/x-www-form-urlencoded"), + WithContentLength(len(encoded)), + }, opts...) + + return Do(method, url, body, opts...) +} + +// BindResponse binds a response body to the "dest" pointer and closes the body. +func BindResponse(resp *http.Response, dest interface{}) error { + contentType := resp.Header.Get("Content-Type") + if idx := strings.IndexRune(contentType, ';'); idx > 0 { + contentType = contentType[0:idx] + } + + switch contentType { + case "application/json": + defer resp.Body.Close() + return json.NewDecoder(resp.Body).Decode(dest) + default: + return fmt.Errorf("unsupported content type: %s", contentType) + } +} + +// RawResponse simply returns the raw response body. +func RawResponse(resp *http.Response) ([]byte, error) { + defer resp.Body.Close() + + return io.ReadAll(resp.Body) +} diff --git a/auth/jwt/tutorial/go-client/main.go b/auth/jwt/tutorial/go-client/main.go new file mode 100644 index 00000000..d22688e1 --- /dev/null +++ b/auth/jwt/tutorial/go-client/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "net/url" + + "myapp/api" + "myapp/domain/model" +) + +const base = "http://localhost:8080" + +func main() { + accessToken, err := authenticate("admin", "admin") + if err != nil { + log.Fatal(err) + } + + log.Printf("Access Token:\n%q", accessToken) + + todo, err := createTodo(accessToken, "test todo title", "test todo body contents") + if err != nil { + log.Fatal(err) + } + + log.Printf("Todo Created:\n%#+v", todo) +} + +func authenticate(username, password string) ([]byte, error) { + endpoint := base + "/signin" + + data := make(url.Values) + data.Set("username", username) + data.Set("password", password) + + resp, err := Form(http.MethodPost, endpoint, data) + if err != nil { + return nil, err + } + + accessToken, err := RawResponse(resp) + return accessToken, err +} + +func createTodo(accessToken []byte, title, body string) (model.Todo, error) { + var todo model.Todo + + endpoint := base + "/todos" + + req := api.TodoRequest{ + Title: title, + Body: body, + } + + resp, err := JSON(http.MethodPost, endpoint, req, WithAccessToken(accessToken)) + if err != nil { + return todo, err + } + + if resp.StatusCode != http.StatusCreated { + rawData, _ := RawResponse(resp) + return todo, fmt.Errorf("failed to create a todo: %s", string(rawData)) + } + + err = BindResponse(resp, &todo) + return todo, err +} diff --git a/auth/jwt/tutorial/go.mod b/auth/jwt/tutorial/go.mod new file mode 100644 index 00000000..2fd33d66 --- /dev/null +++ b/auth/jwt/tutorial/go.mod @@ -0,0 +1,54 @@ +module myapp + +go 1.22 + +require ( + github.com/google/uuid v1.6.0 + github.com/kataras/iris/v12 v12.2.11 + golang.org/x/crypto v0.22.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/jwt v0.1.12 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/auth/jwt/tutorial/go.sum b/auth/jwt/tutorial/go.sum new file mode 100644 index 00000000..ad26f38f --- /dev/null +++ b/auth/jwt/tutorial/go.sum @@ -0,0 +1,180 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/jwt v0.1.12 h1:FHPgTTj5UqjlBye4PA4/oxknCY+kQ9K34XAi8d37glA= +github.com/kataras/jwt v0.1.12/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/auth/jwt/tutorial/main.go b/auth/jwt/tutorial/main.go new file mode 100644 index 00000000..3246e20f --- /dev/null +++ b/auth/jwt/tutorial/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "myapp/api" + "myapp/domain/repository" + + "github.com/kataras/iris/v12" +) + +var ( + userRepo = repository.NewMemoryUserRepository() + todoRepo = repository.NewMemoryTodoRepository() +) + +func main() { + if err := repository.GenerateSamples(userRepo, todoRepo); err != nil { + panic(err) + } + + app := iris.New() + app.PartyFunc("/", api.NewRouter(userRepo, todoRepo)) + + // POST http://localhost:8080/signin (Form: username, password) + // GET http://localhost:8080/todos + // GET http://localhost:8080/todos/{id} + // POST http://localhost:8080/todos (JSON, Form or URL: title, body) + // GET http://localhost:8080/admin/todos + app.Listen(":8080") +} diff --git a/auth/jwt/tutorial/util/app.go b/auth/jwt/tutorial/util/app.go new file mode 100644 index 00000000..7a991f01 --- /dev/null +++ b/auth/jwt/tutorial/util/app.go @@ -0,0 +1,7 @@ +package util + +// Constants for the application. +const ( + Version = "0.0.1" + AppName = "myapp" +) diff --git a/auth/jwt/tutorial/util/clock.go b/auth/jwt/tutorial/util/clock.go new file mode 100644 index 00000000..34e35eb2 --- /dev/null +++ b/auth/jwt/tutorial/util/clock.go @@ -0,0 +1,7 @@ +package util + +import "time" + +// Now is the default current time for the whole application. +// Can be modified for testing or custom timezone. +var Now = time.Now diff --git a/auth/jwt/tutorial/util/password.go b/auth/jwt/tutorial/util/password.go new file mode 100644 index 00000000..c18d0a91 --- /dev/null +++ b/auth/jwt/tutorial/util/password.go @@ -0,0 +1,25 @@ +package util + +import "golang.org/x/crypto/bcrypt" + +// MustGeneratePassword same as GeneratePassword but panics on errors. +func MustGeneratePassword(userPassword string) []byte { + hashed, err := GeneratePassword(userPassword) + if err != nil { + panic(err) + } + + return hashed +} + +// GeneratePassword will generate a hashed password for us based on the +// user's input. +func GeneratePassword(userPassword string) ([]byte, error) { + return bcrypt.GenerateFromPassword([]byte(userPassword), bcrypt.DefaultCost) +} + +// ValidatePassword will check if passwords are matched. +func ValidatePassword(userPassword string, hashed []byte) bool { + err := bcrypt.CompareHashAndPassword(hashed, []byte(userPassword)) + return err == nil +} diff --git a/auth/jwt/tutorial/util/uuid.go b/auth/jwt/tutorial/util/uuid.go new file mode 100644 index 00000000..0269d62d --- /dev/null +++ b/auth/jwt/tutorial/util/uuid.go @@ -0,0 +1,23 @@ +package util + +import "github.com/google/uuid" + +// MustGenerateUUID returns a new v4 UUID or panics. +func MustGenerateUUID() string { + id, err := GenerateUUID() + if err != nil { + panic(err) + } + + return id +} + +// GenerateUUID returns a new v4 UUID. +func GenerateUUID() (string, error) { + id, err := uuid.NewRandom() + if err != nil { + return "", err + } + + return id.String(), nil +} diff --git a/auth/permissions/main.go b/auth/permissions/main.go new file mode 100644 index 00000000..026155b3 --- /dev/null +++ b/auth/permissions/main.go @@ -0,0 +1,118 @@ +package main + +import ( + "fmt" + "log" + "strings" + + "github.com/kataras/iris/v12" + + permissions "github.com/xyproto/permissionbolt" + // * PostgreSQL support: + // permissions "github.com/xyproto/pstore" and + // perm, err := permissions.New(...) + // + // * MariaDB/MySQL support: + // permissions "github.com/xyproto/permissionsql" and + // perm, err := permissions.New/NewWithDSN(...) + // * Redis support: + // permissions "github.com/xyproto/permissions2" + // perm, err := permissions.New2() + // * Bolt support (this one): + // permissions "github.com/xyproto/permissionbolt" and + // perm, err := permissions.New(...) +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + // New permissions middleware. + perm, err := permissions.New() + if err != nil { + log.Fatalln(err) + } + + // Blank slate, no default permissions + // perm.Clear() + + // Set up a middleware handler for Iris, with a custom "permission denied" message. + permissionHandler := func(ctx iris.Context) { + // Check if the user has the right admin/user rights + if perm.Rejected(ctx.ResponseWriter(), ctx.Request()) { + // Deny the request, don't call other middleware handlers + ctx.StopWithText(iris.StatusForbidden, "Permission denied!") + return + } + // Call the next middleware handler + ctx.Next() + } + + // Register the permissions middleware + app.Use(permissionHandler) + + // Get the userstate, used in the handlers below + userstate := perm.UserState() + + app.Get("/", func(ctx iris.Context) { + msg := "" + msg += fmt.Sprintf("Has user bob: %v\n", userstate.HasUser("bob")) + msg += fmt.Sprintf("Logged in on server: %v\n", userstate.IsLoggedIn("bob")) + msg += fmt.Sprintf("Is confirmed: %v\n", userstate.IsConfirmed("bob")) + msg += fmt.Sprintf("Username stored in cookies (or blank): %v\n", userstate.Username(ctx.Request())) + msg += fmt.Sprintf("Current user is logged in, has a valid cookie and *user rights*: %v\n", userstate.UserRights(ctx.Request())) + msg += fmt.Sprintf("Current user is logged in, has a valid cookie and *admin rights*: %v\n", userstate.AdminRights(ctx.Request())) + msg += fmt.Sprintln("\nTry: /register, /confirm, /remove, /login, /logout, /makeadmin, /clear, /data and /admin") + ctx.WriteString(msg) + }) + + app.Get("/register", func(ctx iris.Context) { + userstate.AddUser("bob", "hunter1", "bob@zombo.com") + ctx.Writef("User bob was created: %v\n", userstate.HasUser("bob")) + }) + + app.Get("/confirm", func(ctx iris.Context) { + userstate.MarkConfirmed("bob") + ctx.Writef("User bob was confirmed: %v\n", userstate.IsConfirmed("bob")) + }) + + app.Get("/remove", func(ctx iris.Context) { + userstate.RemoveUser("bob") + ctx.Writef("User bob was removed: %v\n", !userstate.HasUser("bob")) + }) + + app.Get("/login", func(ctx iris.Context) { + // Headers will be written, for storing a cookie + userstate.Login(ctx.ResponseWriter(), "bob") + ctx.Writef("bob is now logged in: %v\n", userstate.IsLoggedIn("bob")) + }) + + app.Get("/logout", func(ctx iris.Context) { + userstate.Logout("bob") + ctx.Writef("bob is now logged out: %v\n", !userstate.IsLoggedIn("bob")) + }) + + app.Get("/makeadmin", func(ctx iris.Context) { + userstate.SetAdminStatus("bob") + ctx.Writef("bob is now administrator: %v\n", userstate.IsAdmin("bob")) + }) + + app.Get("/clear", func(ctx iris.Context) { + userstate.ClearCookie(ctx.ResponseWriter()) + ctx.WriteString("Clearing cookie") + }) + + app.Get("/data", func(ctx iris.Context) { + ctx.WriteString("user page that only logged in users must see!") + }) + + app.Get("/admin", func(ctx iris.Context) { + ctx.WriteString("super secret information that only logged in administrators must see!\n\n") + if usernames, err := userstate.AllUsernames(); err == nil { + ctx.Writef("list of all users: %s" + strings.Join(usernames, ", ")) + } + }) + + // Serve + app.Listen(":8080") +} diff --git a/miscellaneous/recaptcha/custom_form/main.go b/auth/recaptcha/custom_form/main.go similarity index 89% rename from miscellaneous/recaptcha/custom_form/main.go rename to auth/recaptcha/custom_form/main.go index e5215261..395c7c45 100644 --- a/miscellaneous/recaptcha/custom_form/main.go +++ b/auth/recaptcha/custom_form/main.go @@ -3,9 +3,9 @@ package main import ( "fmt" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/middleware/recaptcha" + "github.com/kataras/iris/v12/middleware/recaptcha" ) // keys should be obtained by https://www.google.com/recaptcha @@ -24,7 +24,7 @@ func main() { // pass the middleware before the main handler or use the `recaptcha.SiteVerify`. app.Post("/comment", r, postComment) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } var htmlForm = `<form action="/comment" method="POST"> diff --git a/miscellaneous/recaptcha/main.go b/auth/recaptcha/main.go similarity index 82% rename from miscellaneous/recaptcha/main.go rename to auth/recaptcha/main.go index 3ecd161a..0648bede 100644 --- a/miscellaneous/recaptcha/main.go +++ b/auth/recaptcha/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/recaptcha" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/recaptcha" ) // keys should be obtained by https://www.google.com/recaptcha @@ -26,7 +26,7 @@ func main() { return } - result := recaptcha.SiteFerify(ctx, recaptchaSecret) + result := recaptcha.SiteVerify(ctx, recaptchaSecret) if !result.Success { /* redirect here if u want or do nothing */ ctx.HTML("<b> failed please try again </b>") @@ -36,5 +36,5 @@ func main() { ctx.Writef("succeed.") }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/authentication/README.md b/authentication/README.md deleted file mode 100644 index 497826a0..00000000 --- a/authentication/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Authentication - -- [Basic Authentication](basicauth/main.go) -- [OAUth2](oauth2/main.go) -- [JWT](https://github.com/kataras/iris/blob/master/_examples/experimental-handlers/jwt/main.go) -- [Sessions](https://github.com/kataras/iris/tree/master/_examples/#sessions) \ No newline at end of file diff --git a/structuring/bootstrap/bootstrap/bootstrapper.go b/bootstrapper/bootstrap/bootstrapper.go similarity index 79% rename from structuring/bootstrap/bootstrap/bootstrapper.go rename to bootstrapper/bootstrap/bootstrapper.go index 9efa7df6..4b2ddbf2 100644 --- a/structuring/bootstrap/bootstrap/bootstrapper.go +++ b/bootstrapper/bootstrap/bootstrapper.go @@ -5,11 +5,11 @@ import ( "github.com/gorilla/securecookie" - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/logger" - "github.com/kataras/iris/middleware/recover" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/logger" + "github.com/kataras/iris/v12/middleware/recover" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/websocket" ) type Configurator func(*Bootstrapper) @@ -54,18 +54,14 @@ func (b *Bootstrapper) SetupSessions(expires time.Duration, cookieHashKey, cooki } // SetupWebsockets prepares the websocket server. -func (b *Bootstrapper) SetupWebsockets(endpoint string, onConnection websocket.ConnectionFunc) { - ws := websocket.New(websocket.Config{}) - ws.OnConnection(onConnection) +func (b *Bootstrapper) SetupWebsockets(endpoint string, handler websocket.ConnHandler) { + ws := websocket.New(websocket.DefaultGorillaUpgrader, handler) - b.Get(endpoint, ws.Handler()) - b.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) - }) + b.Get(endpoint, websocket.Handler(ws)) } // SetupErrorHandlers prepares the http error handlers -// `(context.StatusCodeNotSuccessful`, which defaults to < 200 || >= 400 but you can change it). +// `(context.StatusCodeNotSuccessful`, which defaults to >=400 (but you can change it). func (b *Bootstrapper) SetupErrorHandlers() { b.OnAnyErrorCode(func(ctx iris.Context) { err := iris.Map{ @@ -81,7 +77,10 @@ func (b *Bootstrapper) SetupErrorHandlers() { ctx.ViewData("Err", err) ctx.ViewData("Title", "Error") - ctx.View("shared/error.html") + if err := ctx.View("shared/error.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) } @@ -112,7 +111,7 @@ func (b *Bootstrapper) Bootstrap() *Bootstrapper { // static files b.Favicon(StaticAssets + Favicon) - b.StaticWeb(StaticAssets[1:len(StaticAssets)-1], StaticAssets) + b.HandleDir("/public", iris.Dir(StaticAssets)) // middleware, after static files b.Use(recover.New()) diff --git a/structuring/bootstrap/folder_structure.png b/bootstrapper/folder_structure.png similarity index 100% rename from structuring/bootstrap/folder_structure.png rename to bootstrapper/folder_structure.png diff --git a/bootstrapper/go.mod b/bootstrapper/go.mod new file mode 100644 index 00000000..4bae89cc --- /dev/null +++ b/bootstrapper/go.mod @@ -0,0 +1,85 @@ +module github.com/kataras/iris/v12/_examples/bootstrapper + +go 1.22 + +require ( + github.com/gorilla/securecookie v1.1.2 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/ajg/form v1.5.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/imkira/go-interpol v1.1.0 // indirect + github.com/iris-contrib/httpexpect/v2 v2.15.2 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sanity-io/litter v1.5.5 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sergi/go-diff v1.0.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + moul.io/http2curl/v2 v2.3.0 // indirect +) diff --git a/bootstrapper/go.sum b/bootstrapper/go.sum new file mode 100644 index 00000000..d38b5562 --- /dev/null +++ b/bootstrapper/go.sum @@ -0,0 +1,235 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/structuring/bootstrap/main.go b/bootstrapper/main.go similarity index 56% rename from structuring/bootstrap/main.go rename to bootstrapper/main.go index 1086f627..4a8e1d1e 100644 --- a/structuring/bootstrap/main.go +++ b/bootstrapper/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/iris-contrib/examples/structuring/bootstrap/bootstrap" - "github.com/iris-contrib/examples/structuring/bootstrap/middleware/identity" - "github.com/iris-contrib/examples/structuring/bootstrap/routes" + "github.com/kataras/iris/v12/_examples/bootstrapper/bootstrap" + "github.com/kataras/iris/v12/_examples/bootstrapper/middleware/identity" + "github.com/kataras/iris/v12/_examples/bootstrapper/routes" ) func newApp() *bootstrap.Bootstrapper { diff --git a/structuring/bootstrap/main_test.go b/bootstrapper/main_test.go similarity index 69% rename from structuring/bootstrap/main_test.go rename to bootstrapper/main_test.go index 1fe5f562..df05c65f 100644 --- a/structuring/bootstrap/main_test.go +++ b/bootstrapper/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) // go test -v @@ -14,11 +14,11 @@ func TestApp(t *testing.T) { // test our routes e.GET("/").Expect().Status(httptest.StatusOK) e.GET("/follower/42").Expect().Status(httptest.StatusOK). - Body().Equal("from /follower/{id:long} with ID: 42") + Body().IsEqual("from /follower/{id:int64} with ID: 42") e.GET("/following/52").Expect().Status(httptest.StatusOK). - Body().Equal("from /following/{id:long} with ID: 52") + Body().IsEqual("from /following/{id:int64} with ID: 52") e.GET("/like/64").Expect().Status(httptest.StatusOK). - Body().Equal("from /like/{id:long} with ID: 64") + Body().IsEqual("from /like/{id:int64} with ID: 64") // test not found e.GET("/notfound").Expect().Status(httptest.StatusNotFound) @@ -28,5 +28,5 @@ func TestApp(t *testing.T) { "message": "", } e.GET("/anotfoundwithjson").WithQuery("json", nil). - Expect().Status(httptest.StatusNotFound).JSON().Equal(expectedErr) + Expect().Status(httptest.StatusNotFound).JSON().IsEqual(expectedErr) } diff --git a/structuring/bootstrap/middleware/identity/identity.go b/bootstrapper/middleware/identity/identity.go similarity index 89% rename from structuring/bootstrap/middleware/identity/identity.go rename to bootstrapper/middleware/identity/identity.go index 57b8f674..6ce7f309 100644 --- a/structuring/bootstrap/middleware/identity/identity.go +++ b/bootstrapper/middleware/identity/identity.go @@ -3,9 +3,9 @@ package identity import ( "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/iris-contrib/examples/structuring/bootstrap/bootstrap" + "github.com/kataras/iris/v12/_examples/bootstrapper/bootstrap" ) // New returns a new handler which adds some headers and view data diff --git a/file-server/embedding-gziped-files-into-app/assets/favicon.ico b/bootstrapper/public/favicon.ico similarity index 100% rename from file-server/embedding-gziped-files-into-app/assets/favicon.ico rename to bootstrapper/public/favicon.ico diff --git a/structuring/bootstrap/routes/follower.go b/bootstrapper/routes/follower.go similarity index 88% rename from structuring/bootstrap/routes/follower.go rename to bootstrapper/routes/follower.go index 3dd0f012..7c3113f6 100644 --- a/structuring/bootstrap/routes/follower.go +++ b/bootstrapper/routes/follower.go @@ -1,7 +1,7 @@ package routes import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // GetFollowerHandler handles the GET: /follower/{id} diff --git a/structuring/bootstrap/routes/following.go b/bootstrapper/routes/following.go similarity index 88% rename from structuring/bootstrap/routes/following.go rename to bootstrapper/routes/following.go index e81c9c24..affbbaf7 100644 --- a/structuring/bootstrap/routes/following.go +++ b/bootstrapper/routes/following.go @@ -1,7 +1,7 @@ package routes import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // GetFollowingHandler handles the GET: /following/{id} diff --git a/structuring/bootstrap/routes/index.go b/bootstrapper/routes/index.go similarity index 52% rename from structuring/bootstrap/routes/index.go rename to bootstrapper/routes/index.go index 18541ed0..5a314044 100644 --- a/structuring/bootstrap/routes/index.go +++ b/bootstrapper/routes/index.go @@ -1,11 +1,14 @@ package routes import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // GetIndexHandler handles the GET: / func GetIndexHandler(ctx iris.Context) { ctx.ViewData("Title", "Index Page") - ctx.View("index.html") + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } diff --git a/structuring/bootstrap/routes/like.go b/bootstrapper/routes/like.go similarity index 87% rename from structuring/bootstrap/routes/like.go rename to bootstrapper/routes/like.go index 631653c4..3e150938 100644 --- a/structuring/bootstrap/routes/like.go +++ b/bootstrapper/routes/like.go @@ -1,7 +1,7 @@ package routes import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // GetLikeHandler handles the GET: /like/{id} diff --git a/bootstrapper/routes/routes.go b/bootstrapper/routes/routes.go new file mode 100644 index 00000000..3f52ea75 --- /dev/null +++ b/bootstrapper/routes/routes.go @@ -0,0 +1,13 @@ +package routes + +import ( + "github.com/kataras/iris/v12/_examples/bootstrapper/bootstrap" +) + +// Configure registers the necessary routes to the app. +func Configure(b *bootstrap.Bootstrapper) { + b.Get("/", GetIndexHandler) + b.Get("/follower/{id:int64}", GetFollowerHandler) + b.Get("/following/{id:int64}", GetFollowingHandler) + b.Get("/like/{id:int64}", GetLikeHandler) +} diff --git a/structuring/bootstrap/views/index.html b/bootstrapper/views/index.html similarity index 100% rename from structuring/bootstrap/views/index.html rename to bootstrapper/views/index.html diff --git a/structuring/bootstrap/views/shared/error.html b/bootstrapper/views/shared/error.html similarity index 100% rename from structuring/bootstrap/views/shared/error.html rename to bootstrapper/views/shared/error.html diff --git a/structuring/bootstrap/views/shared/layout.html b/bootstrapper/views/shared/layout.html similarity index 95% rename from structuring/bootstrap/views/shared/layout.html rename to bootstrapper/views/shared/layout.html index cf920444..70891776 100644 --- a/structuring/bootstrap/views/shared/layout.html +++ b/bootstrapper/views/shared/layout.html @@ -12,7 +12,7 @@ <body> <div> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} <hr /> <footer> <p>© 2017 - {{.AppOwner}}</p> diff --git a/cache/simple/main.go b/cache/simple/main.go deleted file mode 100644 index 09f88881..00000000 --- a/cache/simple/main.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - "time" - - "github.com/kataras/iris" - - "github.com/kataras/iris/cache" -) - -var markdownContents = []byte(`## Hello Markdown - -This is a sample of Markdown contents - - - -Features --------- - -All features of Sundown are supported, including: - -* **Compatibility**. The Markdown v1.0.3 test suite passes with - the --tidy option. Without --tidy, the differences are - mostly in whitespace and entity escaping, where blackfriday is - more consistent and cleaner. - -* **Common extensions**, including table support, fenced code - blocks, autolinks, strikethroughs, non-strict emphasis, etc. - -* **Safety**. Blackfriday is paranoid when parsing, making it safe - to feed untrusted user input without fear of bad things - happening. The test suite stress tests this and there are no - known inputs that make it crash. If you find one, please let me - know and send me the input that does it. - - NOTE: "safety" in this context means *runtime safety only*. In order to - protect yourself against JavaScript injection in untrusted content, see - [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). - -* **Fast processing**. It is fast enough to render on-demand in - most web applications without having to cache the output. - -* **Routine safety**. You can run multiple parsers in different - goroutines without ill effect. There is no dependence on global - shared state. - -* **Minimal dependencies**. Blackfriday only depends on standard - library packages in Go. The source code is pretty - self-contained, so it is easy to add to any project, including - Google App Engine projects. - -* **Standards compliant**. Output successfully validates using the - W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. - - [this is a link](https://github.com/kataras/iris) `) - -// Cache should not be used on handlers that contain dynamic data. -// Cache is a good and a must-feature on static content, i.e "about page" or for a whole blog site. -func main() { - app := iris.New() - app.Logger().SetLevel("debug") - app.Get("/", cache.Handler(10*time.Second), writeMarkdown) - // saves its content on the first request and serves it instead of re-calculating the content. - // After 10 seconds it will be cleared and resetted. - - app.Run(iris.Addr(":8080")) -} - -func writeMarkdown(ctx iris.Context) { - // tap multiple times the browser's refresh button and you will - // see this println only once every 10 seconds. - println("Handler executed. Content refreshed.") - - ctx.Markdown(markdownContents) -} - -/* Note that `StaticWeb` does use the browser's disk caching by-default -therefore, register the cache handler AFTER any StaticWeb calls, -for a faster solution that server doesn't need to keep track of the response -navigate to https://github.com/kataras/iris/blob/master/_examples/cache/client-side/main.go */ diff --git a/tutorial/caddy/Caddyfile b/caddy/Caddyfile similarity index 100% rename from tutorial/caddy/Caddyfile rename to caddy/Caddyfile diff --git a/tutorial/caddy/README.md b/caddy/README.md similarity index 80% rename from tutorial/caddy/README.md rename to caddy/README.md index f3d7cfb6..e8c601c3 100644 --- a/tutorial/caddy/README.md +++ b/caddy/README.md @@ -4,15 +4,15 @@ The `Caddyfile` shows how you can use caddy to listen on ports 80 & 443 and sit ## Running our two web servers -1. Go to `$GOPATH/src/github.com/kataras/iris/_examples/tutorial/caddy/server1` +1. Go to `$GOPATH/src/github.com/kataras/iris/_examples/caddy/server1` 2. Open a terminal window and execute `go run main.go` -3. Go to `$GOPATH/src/github.com/kataras/iris/_examples/tutorial/caddy/server2` +3. Go to `$GOPATH/src/github.com/kataras/iris/_examples/caddy/server2` 4. Open a new terminal window and execute `go run main.go` ## Caddy installation 1. Download caddy: https://caddyserver.com/download -2. Extract its contents where the `Caddyfile` is located, the `$GOPATH/src/github.com/kataras/iris/_examples/tutorial/caddy` in this case +2. Extract its contents where the `Caddyfile` is located, the `$GOPATH/src/github.com/kataras/iris/_examples/caddy` in this case 3. Open, read and modify the `Caddyfile` to see by yourself how easy it is to configure the servers 4. Run `caddy` directly or open a terminal window and execute `caddy` 5. Go to `https://example.com` and `https://api.example.com/user/42` diff --git a/tutorial/caddy/server1/main.go b/caddy/server1/main.go similarity index 92% rename from tutorial/caddy/server1/main.go rename to caddy/server1/main.go index 3f674580..0f7f87ec 100644 --- a/tutorial/caddy/server1/main.go +++ b/caddy/server1/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) func main() { @@ -14,7 +14,7 @@ func main() { mvc.New(app).Handle(new(Controller)) // http://localhost:9091 - app.Run(iris.Addr(":9091")) + app.Listen(":9091") } // Layout contains all the binding properties for the shared/layout.html diff --git a/tutorial/caddy/server1/views/index.html b/caddy/server1/views/index.html similarity index 100% rename from tutorial/caddy/server1/views/index.html rename to caddy/server1/views/index.html diff --git a/tutorial/caddy/server1/views/shared/layout.html b/caddy/server1/views/shared/layout.html similarity index 82% rename from tutorial/caddy/server1/views/shared/layout.html rename to caddy/server1/views/shared/layout.html index 141a75f7..3854c7fd 100644 --- a/tutorial/caddy/server1/views/shared/layout.html +++ b/caddy/server1/views/shared/layout.html @@ -5,7 +5,7 @@ </head> <body> - {{ yield }} + {{ yield . }} </body> </html> \ No newline at end of file diff --git a/tutorial/caddy/server2/main.go b/caddy/server2/main.go similarity index 90% rename from tutorial/caddy/server2/main.go rename to caddy/server2/main.go index 260df112..45a9ed80 100644 --- a/tutorial/caddy/server2/main.go +++ b/caddy/server2/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) type postValue func(string) string @@ -21,7 +21,7 @@ func main() { // PUT http://localhost:9092/user/42 // DELETE http://localhost:9092/user/42 // GET http://localhost:9092/user/followers/42 - app.Run(iris.Addr(":9092")) + app.Listen(":9092") } // UserController is our user example controller. @@ -35,7 +35,7 @@ func (c *UserController) Get() string { // User is our test User model, nothing tremendous here. type User struct{ ID int64 } -// GetBy handles GET /user/42, equal to .Get("/user/{id:long}") +// GetBy handles GET /user/42, equal to .Get("/user/{id:int64}") func (c *UserController) GetBy(id int64) User { // Select User by ID == $id. return User{id} diff --git a/compression/client-using-iris/main.go b/compression/client-using-iris/main.go new file mode 100644 index 00000000..0083b571 --- /dev/null +++ b/compression/client-using-iris/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/kataras/iris/v12/context" +) + +const baseURL = "http://localhost:8080" + +// Available options: +// - "gzip", +// - "deflate", +// - "br" (for brotli), +// - "snappy" and +// - "s2" +const encoding = context.BROTLI + +var client = http.DefaultClient + +func main() { + fmt.Printf("Running client example on: %s\n", baseURL) + + getExample() + postExample() +} + +func getExample() { + endpoint := baseURL + "/" + req, err := http.NewRequest(http.MethodGet, endpoint, nil) + if err != nil { + panic(err) + } + // Required to receive server's compressed data. + req.Header.Set("Accept-Encoding", encoding) + + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + // decompress server's compressed reply. + cr, err := context.NewCompressReader(resp.Body, encoding) + if err != nil { + panic(err) + } + defer cr.Close() + + body, err := io.ReadAll(cr) + if err != nil { + panic(err) + } + + fmt.Printf("Received from server: %s", string(body)) +} + +type payload struct { + Username string `json:"username"` +} + +func postExample() { + buf := new(bytes.Buffer) + + // Compress client's data. + cw, err := context.NewCompressWriter(buf, encoding, -1) + if err != nil { + panic(err) + } + + json.NewEncoder(cw).Encode(payload{Username: "Edward"}) + + // `Close` or `Flush` required before `NewRequest` call. + cw.Close() + + endpoint := baseURL + "/" + + req, err := http.NewRequest(http.MethodPost, endpoint, buf) + if err != nil { + panic(err) + } + req.Header.Set("Content-Type", "application/json") + + // Required to send gzip compressed data to the server. + req.Header.Set("Content-Encoding", encoding) + // Required to receive server's compressed data. + req.Header.Set("Accept-Encoding", encoding) + + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + // Decompress server's compressed reply. + cr, err := context.NewCompressReader(resp.Body, encoding) + if err != nil { + panic(err) + } + defer cr.Close() + + body, err := io.ReadAll(cr) + if err != nil { + panic(err) + } + + fmt.Printf("Server replied with: %s", string(body)) +} diff --git a/compression/client/main.go b/compression/client/main.go new file mode 100644 index 00000000..0ee40aa3 --- /dev/null +++ b/compression/client/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "bytes" + "compress/gzip" + "encoding/json" + "fmt" + "io" + "net/http" +) + +var client = http.DefaultClient + +const baseURL = "http://localhost:8080" + +func main() { + fmt.Printf("Running client example on: %s\n", baseURL) + + getExample() + postExample() +} + +func getExample() { + endpoint := baseURL + "/" + req, err := http.NewRequest(http.MethodGet, endpoint, nil) + if err != nil { + panic(err) + } + // Required to receive server's compressed data. + req.Header.Set("Accept-Encoding", "gzip") + + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + // decompress server's compressed reply. + r, err := gzip.NewReader(resp.Body) + if err != nil { + panic(err) + } + defer r.Close() + + body, err := io.ReadAll(r) + if err != nil { + panic(err) + } + + fmt.Printf("Received from server: %s", string(body)) +} + +type payload struct { + Username string `json:"username"` +} + +func postExample() { + buf := new(bytes.Buffer) + + // Compress client's data. + w := gzip.NewWriter(buf) + + b, err := json.Marshal(payload{Username: "Edward"}) + if err != nil { + panic(err) + } + w.Write(b) + w.Close() + + endpoint := baseURL + "/" + + req, err := http.NewRequest(http.MethodPost, endpoint, buf) + if err != nil { + panic(err) + } + req.Header.Set("Content-Type", "application/json") + + // Required to send gzip compressed data to the server. + req.Header.Set("Content-Encoding", "gzip") + // Required to receive server's compressed data. + req.Header.Set("Accept-Encoding", "gzip") + + resp, err := client.Do(req) + if err != nil { + panic(err) + } + defer resp.Body.Close() + + // Decompress server's compressed reply. + r, err := gzip.NewReader(resp.Body) + if err != nil { + panic(err) + } + defer r.Close() + + body, err := io.ReadAll(r) + if err != nil { + panic(err) + } + + fmt.Printf("Server replied with: %s", string(body)) +} diff --git a/compression/main.go b/compression/main.go new file mode 100644 index 00000000..e1d989d7 --- /dev/null +++ b/compression/main.go @@ -0,0 +1,64 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + // HERE and you are ready to GO: + app.Use(iris.Compression) + + app.Get("/", send) + app.Post("/", receive) + + return app +} + +type payload struct { + Username string `json:"username"` +} + +func send(ctx iris.Context) { + ctx.JSON(payload{ + Username: "Makis", + }) +} + +func receive(ctx iris.Context) { + var p payload + if err := ctx.ReadJSON(&p); err != nil { + ctx.Application().Logger().Debugf("ReadJSON: %v", err) + } + + ctx.WriteString(p.Username) +} + +/* Manually: +func enableCompression(ctx iris.Context) { + // Enable writing using compression (deflate, gzip, brotli, snappy, s2): + err := ctx.CompressWriter(true) + if err != nil { + ctx.Application().Logger().Debugf("writer: %v", err) + // if you REQUIRE server to SEND compressed data then `return` here. + // return + } + + // Enable reading and binding request's compressed data: + err = ctx.CompressReader(true) + if err != nil && + // on GET we don't expect writing with gzip from client + ctx.Method() != iris.MethodGet { + ctx.Application().Logger().Debugf("reader: %v", err) + // if you REQUIRE server to RECEIVE only + // compressed data then `return` here. + // return + } + + ctx.Next() +} +*/ diff --git a/compression/main_test.go b/compression/main_test.go new file mode 100644 index 00000000..62cbb459 --- /dev/null +++ b/compression/main_test.go @@ -0,0 +1,84 @@ +package main + +import ( + "encoding/json" + "reflect" + "strings" + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" + "github.com/kataras/iris/v12/httptest" +) + +func TestCompression(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + var expectedReply = payload{Username: "Makis"} + testBody(t, e.GET("/"), expectedReply) +} + +func TestCompressionAfterRecorder(t *testing.T) { + var expectedReply = payload{Username: "Makis"} + + app := iris.New() + app.Use(func(ctx iris.Context) { + ctx.Record() + ctx.Next() + }) + app.Use(iris.Compression) + + app.Get("/", func(ctx iris.Context) { + ctx.JSON(expectedReply) + }) + + e := httptest.New(t, app) + testBody(t, e.GET("/"), expectedReply) +} + +func TestCompressionBeforeRecorder(t *testing.T) { + var expectedReply = payload{Username: "Makis"} + + app := iris.New() + app.Use(iris.Compression) + app.Use(func(ctx iris.Context) { + ctx.Record() + ctx.Next() + }) + + app.Get("/", func(ctx iris.Context) { + ctx.JSON(expectedReply) + }) + + e := httptest.New(t, app) + testBody(t, e.GET("/"), expectedReply) +} + +func testBody(t *testing.T, req *httptest.Request, expectedReply interface{}) { + t.Helper() + + body := req.WithHeader(context.AcceptEncodingHeaderKey, context.GZIP).Expect(). + Status(httptest.StatusOK). + ContentEncoding(context.GZIP). + ContentType(context.ContentJSONHeaderValue).Body().Raw() + + // Note that .Expect() consumes the response body + // and stores it to unexported "contents" field + // therefore, we retrieve it as string and put it to a new buffer. + r := strings.NewReader(body) + cr, err := context.NewCompressReader(r, context.GZIP) + if err != nil { + t.Fatal(err) + } + defer cr.Close() + + var got payload + if err = json.NewDecoder(cr).Decode(&got); err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(expectedReply, got) { + t.Fatalf("expected %#+v but got %#+v", expectedReply, got) + } +} diff --git a/configuration/README.md b/configuration/README.md deleted file mode 100644 index fa54b775..00000000 --- a/configuration/README.md +++ /dev/null @@ -1,283 +0,0 @@ -# Configuration - -All configuration's values have default values, things will work as you expected with `iris.New()`. - -Configuration is useless before listen functions, so it should be passed on `Application#Run/2` (second argument(s)). - -Iris has a type named `Configurator` which is a `func(*iris.Application)`, any function -which completes this can be passed at `Application#Configure` and/or `Application#Run/2`. - -`Application#ConfigurationReadOnly()` returns the configuration values. - -`.Run` **by `Configuration` struct** - -```go -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<b>Hello!</b>") - }) - // [...] - - // Good when you want to modify the whole configuration. - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{ - DisableStartupLog: false, - DisableInterruptHandler: false, - DisablePathCorrection: false, - EnablePathEscape: false, - FireMethodNotAllowed: false, - DisableBodyConsumptionOnUnmarshal: false, - DisableAutoFireStatusCode: false, - TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT", - Charset: "UTF-8", - })) -} -``` - -`.Run` **by options** - -```go -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<b>Hello!</b>") - }) - // [...] - - // Good when you want to change some of the configuration's field. - // Prefix: "With", code editors will help you navigate through all - // configuration options without even a glitch to the documentation. - - app.Run(iris.Addr(":8080"), iris.WithoutStartupLog, iris.WithCharset("UTF-8")) - - // or before run: - // app.Configure(iris.WithoutStartupLog, iris.WithCharset("UTF-8")) - // app.Run(iris.Addr(":8080")) -} -``` - -`.Run` **by TOML config file** - -```tml -DisablePathCorrection = false -EnablePathEscape = false -FireMethodNotAllowed = true -DisableBodyConsumptionOnUnmarshal = false -TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT" -Charset = "UTF-8" - -[Other] - MyServerName = "iris" - -``` - -```go -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<b>Hello!</b>") - }) - // [...] - - // Good when you have two configurations, one for development and a different one for production use. - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.TOML("./configs/iris.tml"))) -} -``` - - -`.Run` **by YAML config file** - -```yml -DisablePathCorrection: false -EnablePathEscape: false -FireMethodNotAllowed: true -DisableBodyConsumptionOnUnmarshal: true -TimeFormat: Mon, 01 Jan 2006 15:04:05 GMT -Charset: UTF-8 -``` - -```go -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<b>Hello!</b>") - }) - // [...] - - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.YAML("./configs/iris.yml"))) -} - -``` - -## Built'n Configurators - -```go -// WithoutServerError will cause to ignore the matched "errors" -// from the main application's `Run` function. -// -// Usage: -// err := app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) -// will return `nil` if the server's error was `http/iris#ErrServerClosed`. -// -// See `Configuration#IgnoreServerErrors []string` too. -// -// Example: https://github.com/kataras/iris/tree/master/_examples/http-listening/listen-addr/omit-server-errors -func WithoutServerError(errors ...error) Configurator - -// WithoutStartupLog turns off the information send, once, to the terminal when the main server is open. -var WithoutStartupLog - -// WithoutInterruptHandler disables the automatic graceful server shutdown -// when control/cmd+C pressed. -var WithoutInterruptHandler - -// WithoutPathCorrection disables the PathCorrection setting. -// -// See `Configuration`. -var WithoutPathCorrection - -// WithoutBodyConsumptionOnUnmarshal disables BodyConsumptionOnUnmarshal setting. -// -// See `Configuration`. -var WithoutBodyConsumptionOnUnmarshal - -// WithoutAutoFireStatusCode disables the AutoFireStatusCode setting. -// -// See `Configuration`. -var WithoutAutoFireStatusCode - -// WithPathEscape enanbles the PathEscape setting. -// -// See `Configuration`. -var WithPathEscape - -// WithOptimizations can force the application to optimize for the best performance where is possible. -// -// See `Configuration`. -var WithOptimizations - -// WithFireMethodNotAllowed enanbles the FireMethodNotAllowed setting. -// -// See `Configuration`. -var WithFireMethodNotAllowed - -// WithTimeFormat sets the TimeFormat setting. -// -// See `Configuration`. -func WithTimeFormat(timeformat string) Configurator - -// WithCharset sets the Charset setting. -// -// See `Configuration`. -func WithCharset(charset string) Configurator - -// WithRemoteAddrHeader enables or adds a new or existing request header name -// that can be used to validate the client's real IP. -// -// Existing values are: -// "X-Real-Ip": false, -// "X-Forwarded-For": false, -// "CF-Connecting-IP": false -// -// Look `context.RemoteAddr()` for more. -func WithRemoteAddrHeader(headerName string) Configurator - -// WithoutRemoteAddrHeader disables an existing request header name -// that can be used to validate the client's real IP. -// -// Existing values are: -// "X-Real-Ip": false, -// "X-Forwarded-For": false, -// "CF-Connecting-IP": false -// -// Look `context.RemoteAddr()` for more. -func WithoutRemoteAddrHeader(headerName string) Configurator - -// WithOtherValue adds a value based on a key to the Other setting. -// -// See `Configuration`. -func WithOtherValue(key string, val interface{}) Configurator -``` - -## Custom Configurator - -With the `Configurator` developers can modularize their applications with ease. - -Example Code: - -```go -// file counter/counter.go -package counter - -import ( - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/core/host" -) - -func Configurator(app *iris.Application) { - counterValue := 0 - - go func() { - ticker := time.NewTicker(time.Second) - - for range ticker.C { - counterValue++ - } - - app.ConfigureHost(func(h *host.Supervisor) { // <- HERE: IMPORTANT - h.RegisterOnShutdown(func() { - ticker.Stop() - }) - }) - }() - - app.Get("/counter", func(ctx iris.Context) { - ctx.Writef("Counter value = %d", counterValue) - }) -} -``` - -```go -// file: main.go -package main - -import ( - "counter" - - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - app.Configure(counter.Configurator) - - app.Run(iris.Addr(":8080")) -} -``` \ No newline at end of file diff --git a/configuration/from-configuration-structure/main.go b/configuration/from-configuration-structure/main.go index b3da663e..93908cb4 100644 --- a/configuration/from-configuration-structure/main.go +++ b/configuration/from-configuration-structure/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -12,7 +12,7 @@ func main() { // [...] // Good when you want to modify the whole configuration. - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{ // default configuration: + app.Listen(":8080", iris.WithConfiguration(iris.Configuration{ // default configuration: DisableStartupLog: false, DisableInterruptHandler: false, DisablePathCorrection: false, @@ -21,7 +21,7 @@ func main() { DisableBodyConsumptionOnUnmarshal: false, DisableAutoFireStatusCode: false, TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT", - Charset: "UTF-8", + Charset: "utf-8", })) // or before Run: diff --git a/configuration/from-toml-file/configs/iris.tml b/configuration/from-toml-file/configs/iris.tml index 34230c4c..7b4cc5af 100644 --- a/configuration/from-toml-file/configs/iris.tml +++ b/configuration/from-toml-file/configs/iris.tml @@ -3,7 +3,7 @@ EnablePathEscape = false FireMethodNotAllowed = true DisableBodyConsumptionOnUnmarshal = false TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT" -Charset = "UTF-8" - +Charset = "utf-8" +RemoteAddrHeaders = ["X-Real-Ip", "X-Forwarded-For", "CF-Connecting-IP"] [Other] MyServerName = "iris" diff --git a/configuration/from-toml-file/main.go b/configuration/from-toml-file/main.go index fe08b255..b0c02935 100644 --- a/configuration/from-toml-file/main.go +++ b/configuration/from-toml-file/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -13,9 +13,9 @@ func main() { // [...] // Good when you have two configurations, one for development and a different one for production use. - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.TOML("./configs/iris.tml"))) + app.Listen(":8080", iris.WithConfiguration(iris.TOML("./configs/iris.tml"))) // or before run: // app.Configure(iris.WithConfiguration(iris.TOML("./configs/iris.tml"))) - // app.Run(iris.Addr(":8080")) + // app.Listen(":8080") } diff --git a/configuration/from-yaml-file/configs/iris.yml b/configuration/from-yaml-file/configs/iris.yml index 5a4caa1f..af932146 100644 --- a/configuration/from-yaml-file/configs/iris.yml +++ b/configuration/from-yaml-file/configs/iris.yml @@ -3,4 +3,14 @@ EnablePathEscape: false FireMethodNotAllowed: true DisableBodyConsumptionOnUnmarshal: true TimeFormat: Mon, 01 Jan 2006 15:04:05 GMT -Charset: UTF-8 \ No newline at end of file +Charset: UTF-8 +SSLProxyHeaders: + X-Forwarded-Proto: https +HostProxyHeaders: + X-Host: true +RemoteAddrHeaders: + - X-Real-Ip + - X-Forwarded-For + - CF-Connecting-IP +Other: + Addr: :8080 diff --git a/configuration/from-yaml-file/main.go b/configuration/from-yaml-file/main.go index ad42e74b..a872d5bd 100644 --- a/configuration/from-yaml-file/main.go +++ b/configuration/from-yaml-file/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -14,9 +14,11 @@ func main() { // Good when you have two configurations, one for development and a different one for production use. // If iris.YAML's input string argument is "~" then it loads the configuration from the home directory // and can be shared between many iris instances. - app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.YAML("./configs/iris.yml"))) + cfg := iris.YAML("./configs/iris.yml") + addr := cfg.Other["Addr"].(string) + app.Listen(addr, iris.WithConfiguration(cfg)) // or before run: // app.Configure(iris.WithConfiguration(iris.YAML("./configs/iris.yml"))) - // app.Run(iris.Addr(":8080")) + // app.Listen(":8080") } diff --git a/configuration/from-yaml-file/shared-configuration/main.go b/configuration/from-yaml-file/shared-configuration/main.go index 25159af3..483cd7a5 100644 --- a/configuration/from-yaml-file/shared-configuration/main.go +++ b/configuration/from-yaml-file/shared-configuration/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -14,8 +14,8 @@ func main() { // Good when you share configuration between multiple iris instances. // This configuration file lives in your $HOME/iris.yml for unix hosts // or %HOMEDRIVE%+%HOMEPATH%/iris.yml for windows hosts, and you can modify it. - app.Run(iris.Addr(":8080"), iris.WithGlobalConfiguration) + app.Listen(":8080", iris.WithGlobalConfiguration) // or before run: // app.Configure(iris.WithGlobalConfiguration) - // app.Run(iris.Addr(":8080")) + // app.Listen(":8080") } diff --git a/configuration/functional/main.go b/configuration/functional/main.go index 9165b5d3..c5a3a473 100644 --- a/configuration/functional/main.go +++ b/configuration/functional/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -15,9 +15,9 @@ func main() { // Prefix: "With", code editors will help you navigate through all // configuration options without even a glitch to the documentation. - app.Run(iris.Addr(":8080"), iris.WithoutStartupLog, iris.WithCharset("UTF-8")) + app.Listen(":8080", iris.WithoutStartupLog, iris.WithCharset("utf-8")) // or before run: - // app.Configure(iris.WithoutStartupLog, iris.WithCharset("UTF-8")) - // app.Run(iris.Addr(":8080")) + // app.Configure(iris.WithoutStartupLog, iris.WithCharset("utf-8")) + // app.Listen(":8080") } diff --git a/configuration/multi-environments/README.md b/configuration/multi-environments/README.md new file mode 100644 index 00000000..30525578 --- /dev/null +++ b/configuration/multi-environments/README.md @@ -0,0 +1,13 @@ +# Environment-based Configuration + +## Run production server + +```sh +$ go run main.go --config=server.yml +``` + +## Run development server + +```sh +$ go run main.go --config=server.dev.yml +``` diff --git a/configuration/multi-environments/api/configuration.go b/configuration/multi-environments/api/configuration.go new file mode 100644 index 00000000..85498b73 --- /dev/null +++ b/configuration/multi-environments/api/configuration.go @@ -0,0 +1,27 @@ +package api + +import ( + "os" + + "github.com/kataras/iris/v12" + "gopkg.in/yaml.v3" +) + +type Configuration struct { + Host string `yaml:"Host"` + Port int `yaml:"Port"` + EnableCompression bool `yaml:"EnableCompression"` + AllowOrigin string `yaml:"AllowOrigin"` + // Iris specific configuration. + Iris iris.Configuration `yaml:"Iris"` +} + +// BindFile binds the yaml file's contents to this Configuration. +func (c *Configuration) BindFile(filename string) error { + contents, err := os.ReadFile(filename) + if err != nil { + return err + } + + return yaml.Unmarshal(contents, c) +} diff --git a/configuration/multi-environments/api/server.go b/configuration/multi-environments/api/server.go new file mode 100644 index 00000000..1878a517 --- /dev/null +++ b/configuration/multi-environments/api/server.go @@ -0,0 +1,120 @@ +package api + +import ( + "context" + "fmt" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/cors" + "github.com/kataras/iris/v12/x/errors" +) + +type Server struct { + *iris.Application + + config Configuration + closers []func() // See "AddCloser" method. +} + +// NewServer returns a new server instance. +// See its "Start" method. +func NewServer(congig Configuration) *Server { + app := iris.New() + app.Configure(iris.WithConfiguration(congig.Iris)) + + s := &Server{ + config: congig, + Application: app, + } + + return s +} + +func (s *Server) Build() error { + if err := s.Application.Build(); err != nil { + return err + } + + // Register your 3rd-party drivers. + // if err := s.registerDatabase(); err != nil { + // return err + // }s + + return s.configureRouter() +} + +func (s *Server) configureRouter() error { + s.SetContextErrorHandler(errors.DefaultContextErrorHandler) + s.Macros().SetErrorHandler(errors.DefaultPathParameterTypeErrorHandler) + + s.registerMiddlewares() + s.registerRoutes() + + return nil +} + +func (s *Server) registerMiddlewares() { + s.UseRouter(cors.New().AllowOrigin(s.config.AllowOrigin).Handler()) + + s.UseRouter(func(ctx iris.Context) { + ctx.Header("Server", "Iris") + ctx.Header("X-Developer", "kataras") + ctx.Next() + }) + + if s.config.EnableCompression { + s.Use(iris.Compression) // .Use instead of .UseRouter to let it run only on registered routes and not on 404 errors and e.t.c. + } +} + +func (s *Server) registerRoutes() { + // register your routes... + + s.Get("/health", func(ctx iris.Context) { + ctx.WriteString("OK") + }) + +} + +// AddCloser adds one or more function that should be called on +// manual server shutdown or OS interrupt signals. +func (s *Server) AddCloser(closers ...func()) { + for _, closer := range closers { + if closer == nil { + continue + } + + // Terminate any opened connections on OS interrupt signals. + iris.RegisterOnInterrupt(closer) + } + + s.closers = append(s.closers, closers...) +} + +// Shutdown gracefully terminates the HTTP server and calls the closers afterwards. +func (s *Server) Shutdown() error { + ctx, cancelCtx := context.WithTimeout(context.Background(), 5*time.Second) + err := s.Application.Shutdown(ctx) + cancelCtx() + + for _, closer := range s.closers { + if closer == nil { + continue + } + + closer() + } + + return err +} + +// Start starts the http server based on the config's host and port. +func (s *Server) Listen() error { + if err := s.Build(); err != nil { + return err + } + + addr := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port) + return s.Application.Listen(addr) +} diff --git a/configuration/multi-environments/cmd/root_command.go b/configuration/multi-environments/cmd/root_command.go new file mode 100644 index 00000000..6e960644 --- /dev/null +++ b/configuration/multi-environments/cmd/root_command.go @@ -0,0 +1,50 @@ +package cmd + +import ( + "github.com/kataras/my-iris-app/api" + + "github.com/spf13/cobra" +) + +const defaultConfigFilename = "server.dev.yml" + +var ( + serverConfig api.Configuration +) + +// New returns a new root command. +// Usage: +// $ my-iris-app --config=server.yml +func New() *cobra.Command { + configFile := defaultConfigFilename + + rootCmd := &cobra.Command{ + Use: "my-iris-app", + Short: "My Command Line App", + Long: "The root command will start the HTTP server.", + Version: "v0.0.1", + SilenceErrors: true, + SilenceUsage: true, + TraverseChildren: true, + SuggestionsMinimumDistance: 1, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + return serverConfig.BindFile(configFile) + }, + RunE: func(cmd *cobra.Command, args []string) error { + return startServer() + }, + } + + // Shared flags. + flags := rootCmd.PersistentFlags() + flags.StringVar(&configFile, "config", configFile, "--config=server.yml a filepath which contains the YAML config format") + + // Subcommands here. + + return rootCmd +} + +func startServer() error { + srv := api.NewServer(serverConfig) + return srv.Listen() +} diff --git a/configuration/multi-environments/go.mod b/configuration/multi-environments/go.mod new file mode 100644 index 00000000..dcf1a81d --- /dev/null +++ b/configuration/multi-environments/go.mod @@ -0,0 +1,56 @@ +module github.com/kataras/my-iris-app + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/spf13/cobra v1.8.0 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect +) diff --git a/configuration/multi-environments/go.sum b/configuration/multi-environments/go.sum new file mode 100644 index 00000000..c84b4c17 --- /dev/null +++ b/configuration/multi-environments/go.sum @@ -0,0 +1,185 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/configuration/multi-environments/main.go b/configuration/multi-environments/main.go new file mode 100644 index 00000000..bd71229b --- /dev/null +++ b/configuration/multi-environments/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "os" + + "github.com/kataras/my-iris-app/cmd" +) + +func main() { + app := cmd.New() + if err := app.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/configuration/multi-environments/server.dev.yml b/configuration/multi-environments/server.dev.yml new file mode 100644 index 00000000..5eb64e29 --- /dev/null +++ b/configuration/multi-environments/server.dev.yml @@ -0,0 +1,22 @@ +ServerName: "my-iris-app" + +Host: 0.0.0.0 +Port: 8080 +EnableCompression: false +AllowOrigin: "*" + +# Your development environment's +# database connection configuration here... + +#### + +# Iris configuration. +Iris: + LogLevel: info + EnableOptimizations: true + RemoteAddrHeaders: + - "X-Real-Ip" + - "X-Forwarded-For" + - "CF-Connecting-IP" + - "True-Client-Ip" + - "X-Appengine-Remote-Addr" diff --git a/configuration/multi-environments/server.yml b/configuration/multi-environments/server.yml new file mode 100644 index 00000000..199c7e3b --- /dev/null +++ b/configuration/multi-environments/server.yml @@ -0,0 +1,19 @@ +Host: 0.0.0.0 +Port: 80 +EnableCompression: true +AllowOrigin: "*" + +# Your production's database connection configuration here... + +#### + +# Iris configuration. +Iris: + LogLevel: info + EnableOptimizations: true + RemoteAddrHeaders: + - "X-Real-Ip" + - "X-Forwarded-For" + - "CF-Connecting-IP" + - "True-Client-Ip" + - "X-Appengine-Remote-Addr" diff --git a/configuration/viper/config.yml b/configuration/viper/config.yml new file mode 100644 index 00000000..e0a913c1 --- /dev/null +++ b/configuration/viper/config.yml @@ -0,0 +1,50 @@ +Addr: + Internal: + IP: 127.0.0.1 + Plain: 8080 + Secure: 443 +Locale: + Pattern: "./locales/*/*.ini" + Default: "en-US" + Supported: + - "en-US" + - "el-GR" +Iris: + LogLevel: debug + SocketSharding: true + EnableOptimizations: true + DisableStartupLog: false + FireMethodNotAllowed: true + ForceLowercaseRouting: true + EnablePathIntelligence: true + Charset: "utf-8" + TimeFormat: "2006-01-02 15:04:05" + DisableBodyConsumptionOnUnmarshal: true + FireEmptyFormError: true + PostMaxMemory: 67108864 + RemoteAddrHeaders: + - "X-Real-Ip" + - "X-Forwarded-For" + - "CF-Connecting-IP" + - "True-Client-Ip" + IgnoreServerErrors: + - "http: Server closed" + # Tunneling: + # WebInterface: "http://127.0.0.1:4040" + # AuthToken: "<secret>" + # Tunnels: + # - Name: "My awesome App" + # Addr: "localhost:8080" + # - Name: "My Second awesome App" + # Addr: "localhost:9090" + RemoteAddrPrivateSubnets: + - Start: "192.168.0.0" + End: "192.168.255.255" + - Start: "198.18.0.0" + End: "198.19.255.255" + SSLProxyHeaders: + X-Forwarded-Proto: "https" + HostProxyHeaders: + X-Host: true + Other: + ServerName: "My awesome Iris web server" \ No newline at end of file diff --git a/configuration/viper/config/config.go b/configuration/viper/config/config.go new file mode 100644 index 00000000..33a0575b --- /dev/null +++ b/configuration/viper/config/config.go @@ -0,0 +1,54 @@ +package config + +import ( + "fmt" + + "github.com/kataras/iris/v12" + // Viper is a third-party package: + // go get github.com/spf13/viper + "github.com/spf13/viper" +) + +func init() { + loadConfiguration() +} + +// C is the configuration of the app. +var C = struct { + Iris iris.Configuration + Addr struct { + Internal struct { + IP string + Plain int + Secure int + } + } + Locale struct { + Pattern string + Default string + Supported []string + } +}{ + Iris: iris.DefaultConfiguration(), + // other default values... +} + +func loadConfiguration() { + viper.SetConfigName("config") // name of config file (without extension) + viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name + viper.AddConfigPath("/etc/app/") // path to look for the config file in + viper.AddConfigPath("$HOME/.app") // call multiple times to add many search paths + viper.AddConfigPath(".") // optionally look for config in the working directory + err := viper.ReadInConfig() // Find and read the config file + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + } else { + panic(fmt.Errorf("load configuration: %w", err)) + } + } + + err = viper.Unmarshal(&C) + if err != nil { + panic(fmt.Errorf("load configuration: unmarshal: %w", err)) + } +} diff --git a/configuration/viper/go.mod b/configuration/viper/go.mod new file mode 100644 index 00000000..dede57bc --- /dev/null +++ b/configuration/viper/go.mod @@ -0,0 +1,67 @@ +module app + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/spf13/viper v1.18.2 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/configuration/viper/go.sum b/configuration/viper/go.sum new file mode 100644 index 00000000..f2940e56 --- /dev/null +++ b/configuration/viper/go.sum @@ -0,0 +1,223 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/configuration/viper/main.go b/configuration/viper/main.go new file mode 100644 index 00000000..97f6730d --- /dev/null +++ b/configuration/viper/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + + "app/config" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.TextYAML(config.C) + }) + + addr := fmt.Sprintf("%s:%d", config.C.Addr.Internal.IP, config.C.Addr.Internal.Plain) + app.Listen(addr, iris.WithConfiguration(config.C.Iris)) +} diff --git a/convert-handlers/negroni-like/main.go b/convert-handlers/negroni-like/main.go index 6de768ff..be09c9e3 100644 --- a/convert-handlers/negroni-like/main.go +++ b/convert-handlers/negroni-like/main.go @@ -3,7 +3,7 @@ package main import ( "net/http" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -26,7 +26,7 @@ func main() { // http://localhost:8080 // http://localhost:8080/ok - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func negronilikeTestMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { @@ -39,6 +39,3 @@ func negronilikeTestMiddleware(w http.ResponseWriter, r *http.Request, next http w.WriteHeader(iris.StatusBadRequest) w.Write([]byte("Bad request")) } - -// Look "routing/custom-context" if you want to convert a custom handler with a custom Context -// to a context.Handler. diff --git a/convert-handlers/nethttp/main.go b/convert-handlers/nethttp/main.go index 49fffabf..d78c14ee 100644 --- a/convert-handlers/nethttp/main.go +++ b/convert-handlers/nethttp/main.go @@ -3,7 +3,7 @@ package main import ( "net/http" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -23,12 +23,9 @@ func main() { // http://localhost:8080 // http://localhost:8080/ok - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func nativeTestMiddleware(w http.ResponseWriter, r *http.Request) { println("Request path: " + r.URL.Path) } - -// Look "routing/custom-context" if you want to convert a custom handler with a custom Context -// to a context.Handler. diff --git a/convert-handlers/nethttp/wrapper/main.go b/convert-handlers/nethttp/wrapper/main.go new file mode 100644 index 00000000..3bf03453 --- /dev/null +++ b/convert-handlers/nethttp/wrapper/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "context" + "net/http" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + httpThirdPartyWrapper := StandardWrapper(Options{ + Message: "test_value", + }) + + // This case + app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) { + httpThirdPartyWrapper(router).ServeHTTP(w, r) + // If was func(http.HandlerFunc) http.HandlerFunc: + // httpThirdPartyWrapper(router.ServeHTTP).ServeHTTP(w, r) + }) + + app.Get("/", index) + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.Writef("Message: %s\n", ctx.Value(msgContextKey)) +} + +type Options struct { + Message string +} + +type contextKey uint8 + +var ( + msgContextKey contextKey = 1 +) + +func StandardWrapper(opts Options) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // ... + req := r.WithContext(context.WithValue(r.Context(), msgContextKey, opts.Message)) + next.ServeHTTP(w, req) + }) + } +} diff --git a/convert-handlers/real-usecase-raven/wrapping-the-router/main.go b/convert-handlers/real-usecase-raven/wrapping-the-router/main.go index 1155dc1d..a7c86a31 100644 --- a/convert-handlers/real-usecase-raven/wrapping-the-router/main.go +++ b/convert-handlers/real-usecase-raven/wrapping-the-router/main.go @@ -6,7 +6,7 @@ import ( "net/http" "runtime/debug" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" "github.com/getsentry/raven-go" ) @@ -23,7 +23,7 @@ func main() { }) // Example for WrapRouter is already here: - // https://github.com/kataras/iris/blob/master/_examples/routing/custom-wrapper/main.go#L53 + // https://github.com/kataras/iris/blob/main/_examples/routing/custom-wrapper/main.go#L53 app.WrapRouter(func(w http.ResponseWriter, r *http.Request, irisRouter http.HandlerFunc) { // Exactly the same source code: // https://github.com/getsentry/raven-go/blob/379f8d0a68ca237cf8893a1cdfd4f574125e2c51/http.go#L70 @@ -41,5 +41,5 @@ func main() { irisRouter(w, r) }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/convert-handlers/real-usecase-raven/writing-middleware/main.go b/convert-handlers/real-usecase-raven/writing-middleware/main.go index 5360c816..82ef598b 100644 --- a/convert-handlers/real-usecase-raven/writing-middleware/main.go +++ b/convert-handlers/real-usecase-raven/writing-middleware/main.go @@ -5,7 +5,7 @@ import ( "fmt" "runtime/debug" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" "github.com/getsentry/raven-go" ) @@ -53,5 +53,5 @@ func main() { ctx.Writef("Hi") }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/cookies/basic/main.go b/cookies/basic/main.go index 9b3eee42..f9b789e3 100644 --- a/cookies/basic/main.go +++ b/cookies/basic/main.go @@ -1,6 +1,6 @@ package main -import "github.com/kataras/iris" +import "github.com/kataras/iris/v12" func newApp() *iris.Application { app := iris.New() @@ -60,5 +60,5 @@ func main() { // GET: http://localhost:8080/cookies/my_name/my_value // GET: http://localhost:8080/cookies/my_name // DELETE: http://localhost:8080/cookies/my_name - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/cookies/basic/main_test.go b/cookies/basic/main_test.go index f2edd2e4..bd82d9c3 100644 --- a/cookies/basic/main_test.go +++ b/cookies/basic/main_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestCookiesBasic(t *testing.T) { @@ -13,20 +13,20 @@ func TestCookiesBasic(t *testing.T) { cookieName, cookieValue := "my_cookie_name", "my_cookie_value" - // Test Set A Cookie. + // Test set a Cookie. t1 := e.GET(fmt.Sprintf("/cookies/%s/%s", cookieName, cookieValue)).Expect().Status(httptest.StatusOK) t1.Cookie(cookieName).Value().Equal(cookieValue) // validate cookie's existence, it should be there now. t1.Body().Contains(cookieValue) - // Test Retrieve A Cookie. + // Test retrieve a Cookie. t2 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) - t2.Body().Equal(cookieValue) + t2.Body().IsEqual(cookieValue) - // Test Remove A Cookie. + // Test remove a Cookie. t3 := e.DELETE(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) t3.Body().Contains(cookieName) t4 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) t4.Cookies().Empty() - t4.Body().Empty() + t4.Body().IsEmpty() } diff --git a/cookies/options/main.go b/cookies/options/main.go new file mode 100644 index 00000000..d45973b2 --- /dev/null +++ b/cookies/options/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + + // http://localhost:8080/set/name1/value1 + // http://localhost:8080/get/name1 + // http://localhost:8080/remove/name1 + app.Listen(":8080", iris.WithLogLevel("debug")) +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(withCookieOptions) + + app.Get("/set/{name}/{value}", setCookie) + app.Get("/get/{name}", getCookie) + app.Get("/remove/{name}", removeCookie) + + return app +} + +func withCookieOptions(ctx iris.Context) { + // Register cookie options for request-lifecycle. + // To register per cookie, just add the CookieOption + // on the last variadic input argument of + // SetCookie, SetCookieKV, UpsertCookie, RemoveCookie + // and GetCookie Context methods. + // + // * CookieAllowReclaim + // * CookieAllowSubdomains + // * CookieSecure + // * CookieHTTPOnly + // * CookieSameSite + // * CookiePath + // * CookieCleanPath + // * CookieExpires + // * CookieEncoding + ctx.AddCookieOptions(iris.CookieAllowReclaim()) + // ctx.AddCookieOptions(iris.CookieSecure) + // OR for a specific cookie: + // ctx.SetCookieKV("cookie_name", "cookie_value", iris.CookieScure) + // OR by passing a a &http.Cookie: + // ctx.SetCookie(&http.Cookie{ + // Name: "cookie_name", + // Value: "cookie_value", + // Secure: true, + // }) + ctx.Next() +} + +func setCookie(ctx iris.Context) { + name := ctx.Params().Get("name") + value := ctx.Params().Get("value") + + ctx.SetCookieKV(name, value) + + // By-default net/http does not remove or set the Cookie on the Request object. + // + // With the `CookieAllowReclaim` option, whenever you set or remove a cookie + // it will be also reflected in the Request object immediately (of the same request lifecycle) + // therefore, any of the next handlers in the chain are not holding the old value. + valueIsAvailableInRequestObject := ctx.GetCookie(name) + ctx.Writef("cookie %s=%s", name, valueIsAvailableInRequestObject) +} + +func getCookie(ctx iris.Context) { + name := ctx.Params().Get("name") + + value := ctx.GetCookie(name) + ctx.WriteString(value) +} + +func removeCookie(ctx iris.Context) { + name := ctx.Params().Get("name") + + ctx.RemoveCookie(name) + + removedFromRequestObject := ctx.GetCookie(name) // CookieAllowReclaim feature. + ctx.Writef("cookie %s removed, value should be empty=%s", name, removedFromRequestObject) +} diff --git a/cookies/options/main_test.go b/cookies/options/main_test.go new file mode 100644 index 00000000..5a543832 --- /dev/null +++ b/cookies/options/main_test.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestCookieOptions(t *testing.T) { + app := newApp() + e := httptest.New(t, app, httptest.URL("http://example.com")) + + cookieName, cookieValue := "my_cookie_name", "my_cookie_value" + + // Test set a Cookie. + t1 := e.GET(fmt.Sprintf("/set/%s/%s", cookieName, cookieValue)).Expect().Status(httptest.StatusOK) + t1.Cookie(cookieName).Value().Equal(cookieValue) + t1.Body().Contains(fmt.Sprintf("%s=%s", cookieName, cookieValue)) + + // Test retrieve a Cookie. + t2 := e.GET(fmt.Sprintf("/get/%s", cookieName)).Expect().Status(httptest.StatusOK) + t2.Body().IsEqual(cookieValue) + + // Test remove a Cookie. + t3 := e.GET(fmt.Sprintf("/remove/%s", cookieName)).Expect().Status(httptest.StatusOK) + t3.Body().Contains(fmt.Sprintf("cookie %s removed, value should be empty=%s", cookieName, "")) + + t4 := e.GET(fmt.Sprintf("/get/%s", cookieName)).Expect().Status(httptest.StatusOK) + t4.Cookies().Empty() + t4.Body().IsEmpty() +} diff --git a/cookies/securecookie/main.go b/cookies/securecookie/main.go index 9e5dd5cd..bca6e0a5 100644 --- a/cookies/securecookie/main.go +++ b/cookies/securecookie/main.go @@ -6,54 +6,67 @@ package main // $ go run main.go import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" "github.com/gorilla/securecookie" ) -var ( - // AES only supports key sizes of 16, 24 or 32 bytes. - // You either need to provide exactly that amount or you derive the key from what you type in. - hashKey = []byte("the-big-and-secret-fash-key-here") - blockKey = []byte("lot-secret-of-characters-big-too") - sc = securecookie.New(hashKey, blockKey) -) +func main() { + app := newApp() + // http://localhost:8080/cookies/name/value + // http://localhost:8080/cookies/name + // http://localhost:8080/cookies/remove/name + app.Listen(":8080") +} func newApp() *iris.Application { app := iris.New() - // Set A Cookie. - app.Get("/cookies/{name}/{value}", func(ctx iris.Context) { - name := ctx.Params().Get("name") - value := ctx.Params().Get("value") + r := app.Party("/cookies") + { + r.Use(useSecureCookies()) + + // Set A Cookie. + r.Get("/{name}/{value}", func(ctx iris.Context) { + name := ctx.Params().Get("name") + value := ctx.Params().Get("value") - ctx.SetCookieKV(name, value, iris.CookieEncode(sc.Encode)) // <-- + ctx.SetCookieKV(name, value) - ctx.Writef("cookie added: %s = %s", name, value) - }) + ctx.Writef("cookie added: %s = %s", name, value) + }) - // Retrieve A Cookie. - app.Get("/cookies/{name}", func(ctx iris.Context) { - name := ctx.Params().Get("name") + // Retrieve A Cookie. + r.Get("/{name}", func(ctx iris.Context) { + name := ctx.Params().Get("name") - value := ctx.GetCookie(name, iris.CookieDecode(sc.Decode)) // <-- + value := ctx.GetCookie(name) - ctx.WriteString(value) - }) + ctx.WriteString(value) + }) - // Delete A Cookie. - app.Delete("/cookies/{name}", func(ctx iris.Context) { - name := ctx.Params().Get("name") + r.Get("/remove/{name}", func(ctx iris.Context) { + name := ctx.Params().Get("name") - ctx.RemoveCookie(name) // <-- + ctx.RemoveCookie(name) - ctx.Writef("cookie %s removed", name) - }) + ctx.Writef("cookie %s removed", name) + }) + } return app } -func main() { - app := newApp() - app.Run(iris.Addr(":8080")) +func useSecureCookies() iris.Handler { + var ( + hashKey = securecookie.GenerateRandomKey(64) + blockKey = securecookie.GenerateRandomKey(32) + + s = securecookie.New(hashKey, blockKey) + ) + + return func(ctx iris.Context) { + ctx.AddCookieOptions(iris.CookieEncoding(s)) + ctx.Next() + } } diff --git a/cookies/securecookie/main_test.go b/cookies/securecookie/main_test.go index 1298e310..bd8b682f 100644 --- a/cookies/securecookie/main_test.go +++ b/cookies/securecookie/main_test.go @@ -4,31 +4,31 @@ import ( "fmt" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) -func TestCookiesBasic(t *testing.T) { +func TestSecureCookie(t *testing.T) { app := newApp() e := httptest.New(t, app, httptest.URL("http://example.com")) cookieName, cookieValue := "my_cookie_name", "my_cookie_value" - // Test Set A Cookie. + // Test set a Cookie. t1 := e.GET(fmt.Sprintf("/cookies/%s/%s", cookieName, cookieValue)).Expect().Status(httptest.StatusOK) // note that this will not work because it doesn't always returns the same value: // cookieValueEncoded, _ := sc.Encode(cookieName, cookieValue) t1.Cookie(cookieName).Value().NotEqual(cookieValue) // validate cookie's existence and value is not on its raw form. t1.Body().Contains(cookieValue) - // Test Retrieve A Cookie. + // Test retrieve a Cookie. t2 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) - t2.Body().Equal(cookieValue) + t2.Body().IsEqual(cookieValue) - // Test Remove A Cookie. - t3 := e.DELETE(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) + // Test remove a Cookie. + t3 := e.GET(fmt.Sprintf("/cookies/remove/%s", cookieName)).Expect().Status(httptest.StatusOK) t3.Body().Contains(cookieName) t4 := e.GET(fmt.Sprintf("/cookies/%s", cookieName)).Expect().Status(httptest.StatusOK) t4.Cookies().Empty() - t4.Body().Empty() + t4.Body().IsEmpty() } diff --git a/database/mongodb/.env b/database/mongodb/.env new file mode 100644 index 00000000..c41f59a0 --- /dev/null +++ b/database/mongodb/.env @@ -0,0 +1,2 @@ +PORT=8080 +DSN=mongodb://localhost:27017 \ No newline at end of file diff --git a/database/mongodb/0_create_movie.png b/database/mongodb/0_create_movie.png new file mode 100644 index 00000000..17e8a71e Binary files /dev/null and b/database/mongodb/0_create_movie.png differ diff --git a/database/mongodb/1_update_movie.png b/database/mongodb/1_update_movie.png new file mode 100644 index 00000000..d0482aa6 Binary files /dev/null and b/database/mongodb/1_update_movie.png differ diff --git a/database/mongodb/2_get_all_movies.png b/database/mongodb/2_get_all_movies.png new file mode 100644 index 00000000..1360c0a8 Binary files /dev/null and b/database/mongodb/2_get_all_movies.png differ diff --git a/database/mongodb/3_get_movie.png b/database/mongodb/3_get_movie.png new file mode 100644 index 00000000..71eca41e Binary files /dev/null and b/database/mongodb/3_get_movie.png differ diff --git a/database/mongodb/4_delete_movie.png b/database/mongodb/4_delete_movie.png new file mode 100644 index 00000000..185b730a Binary files /dev/null and b/database/mongodb/4_delete_movie.png differ diff --git a/database/mongodb/Dockerfile b/database/mongodb/Dockerfile new file mode 100644 index 00000000..dec864fe --- /dev/null +++ b/database/mongodb/Dockerfile @@ -0,0 +1,17 @@ +# docker build -t myapp . +# docker run --rm -it -p 8080:8080 myapp:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/myapp . +ENTRYPOINT ["./myapp"] \ No newline at end of file diff --git a/database/mongodb/README.md b/database/mongodb/README.md new file mode 100644 index 00000000..4953dd17 --- /dev/null +++ b/database/mongodb/README.md @@ -0,0 +1,64 @@ +# Build RESTful API with the official MongoDB Go Driver and Iris + +Article is coming soon, follow and stay tuned + +- <https://medium.com/@kataras> +- <https://dev.to/kataras> + +Read [the fully functional example](main.go). + +## Run + +### Docker + +Install [Docker](https://www.docker.com/) and execute the command below + +```sh +$ docker-compose up +``` + +### Manually + +```sh +# .env file contents +PORT=8080 +DSN=mongodb://localhost:27017 +``` + +```sh +$ go run main.go +> 2019/01/28 05:17:59 Loading environment variables from file: .env +> 2019/01/28 05:17:59 ◽ Port=8080 +> 2019/01/28 05:17:59 ◽ DSN=mongodb://localhost:27017 +> Now listening on: http://localhost:8080 +``` + +```sh +GET : http://localhost:8080/api/store/movies +POST : http://localhost:8080/api/store/movies +GET : http://localhost:8080/api/store/movies/{id} +PUT : http://localhost:8080/api/store/movies/{id} +DELETE : http://localhost:8080/api/store/movies/{id} +``` + +## Screens + +### Add a Movie + + +### Update a Movie + + + +### Get all Movies + + + +### Get a Movie by its ID + + + +### Delete a Movie by its ID + + + diff --git a/database/mongodb/api/store/movie.go b/database/mongodb/api/store/movie.go new file mode 100644 index 00000000..3a2d9fb2 --- /dev/null +++ b/database/mongodb/api/store/movie.go @@ -0,0 +1,101 @@ +package storeapi + +import ( + "myapp/httputil" + "myapp/store" + + "github.com/kataras/iris/v12" +) + +type MovieHandler struct { + service store.MovieService +} + +func NewMovieHandler(service store.MovieService) *MovieHandler { + return &MovieHandler{service: service} +} + +func (h *MovieHandler) GetAll(ctx iris.Context) { + movies, err := h.service.GetAll(nil) + if err != nil { + httputil.InternalServerErrorJSON(ctx, err, "Server was unable to retrieve all movies") + return + } + + if movies == nil { + // will return "null" if empty, with this "trick" we return "[]" json. + movies = make([]store.Movie, 0) + } + + ctx.JSON(movies) +} + +func (h *MovieHandler) Get(ctx iris.Context) { + id := ctx.Params().Get("id") + + m, err := h.service.GetByID(nil, id) + if err != nil { + if err == store.ErrNotFound { + ctx.NotFound() + } else { + httputil.InternalServerErrorJSON(ctx, err, "Server was unable to retrieve movie [%s]", id) + } + return + } + + ctx.JSON(m) +} + +func (h *MovieHandler) Add(ctx iris.Context) { + m := new(store.Movie) + + err := ctx.ReadJSON(m) + if err != nil { + httputil.FailJSON(ctx, iris.StatusBadRequest, err, "Malformed request payload") + return + } + + err = h.service.Create(nil, m) + if err != nil { + httputil.InternalServerErrorJSON(ctx, err, "Server was unable to create a movie") + return + } + + ctx.StatusCode(iris.StatusCreated) + ctx.JSON(m) +} + +func (h *MovieHandler) Update(ctx iris.Context) { + id := ctx.Params().Get("id") + + var m store.Movie + err := ctx.ReadJSON(&m) + if err != nil { + httputil.FailJSON(ctx, iris.StatusBadRequest, err, "Malformed request payload") + return + } + + err = h.service.Update(nil, id, m) + if err != nil { + if err == store.ErrNotFound { + ctx.NotFound() + return + } + httputil.InternalServerErrorJSON(ctx, err, "Server was unable to update movie [%s]", id) + return + } +} + +func (h *MovieHandler) Delete(ctx iris.Context) { + id := ctx.Params().Get("id") + + err := h.service.Delete(nil, id) + if err != nil { + if err == store.ErrNotFound { + ctx.NotFound() + return + } + httputil.InternalServerErrorJSON(ctx, err, "Server was unable to delete movie [%s]", id) + return + } +} diff --git a/database/mongodb/docker-compose.yml b/database/mongodb/docker-compose.yml new file mode 100644 index 00000000..a9eec93e --- /dev/null +++ b/database/mongodb/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.1" + +services: + app: + build: . + environment: + Port: 8080 + DSN: db:27017 + ports: + - 8080:8080 + depends_on: + - db + db: + image: mongo + environment: + MONGO_INITDB_DATABASE: store + ports: + - 27017:27017 diff --git a/database/mongodb/env/env.go b/database/mongodb/env/env.go new file mode 100644 index 00000000..46aa73f0 --- /dev/null +++ b/database/mongodb/env/env.go @@ -0,0 +1,85 @@ +package env + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/joho/godotenv" +) + +var ( + // Port is the PORT environment variable or 8080 if missing. + // Used to open the tcp listener for our web server. + Port string + // DSN is the DSN environment variable or mongodb://localhost:27017 if missing. + // Used to connect to the mongodb. + DSN string +) + +func parse() { + Port = getDefault("PORT", "8080") + DSN = getDefault("DSN", "mongodb://localhost:27017") + + log.Printf("• Port=%s\n", Port) + log.Printf("• DSN=%s\n", DSN) +} + +// Load loads environment variables that are being used across the whole app. +// Loading from file(s), i.e .env or dev.env +// +// Example of a 'dev.env': +// PORT=8080 +// DSN=mongodb://localhost:27017 +// +// After `Load` the callers can get an environment variable via `os.Getenv`. +func Load(envFileName string) { + if args := os.Args; len(args) > 1 && args[1] == "help" { + fmt.Fprintln(os.Stderr, "https://github.com/kataras/iris/blob/main/_examples/database/mongodb/README.md") + os.Exit(-1) + } + + // If more than one filename passed with comma separated then load from all + // of these, a env file can be a partial too. + envFiles := strings.Split(envFileName, ",") + for _, envFile := range envFiles { + if filepath.Ext(envFile) == "" { + envFile += ".env" + } + + if fileExists(envFile) { + log.Printf("Loading environment variables from file: %s\n", envFile) + + if err := godotenv.Load(envFile); err != nil { + panic(fmt.Sprintf("error loading environment variables from [%s]: %v", envFile, err)) + } + } + } + + // envMap, _ := godotenv.Read(envFiles...) + // for k, v := range envMap { + // log.Printf("◽ %s=%s\n", k, v) + // } + + parse() +} + +func getDefault(key string, def string) string { + value := os.Getenv(key) + if value == "" { + os.Setenv(key, def) + value = def + } + + return value +} + +func fileExists(filename string) bool { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + return false + } + return !info.IsDir() +} diff --git a/database/mongodb/go.mod b/database/mongodb/go.mod new file mode 100644 index 00000000..1a21970e --- /dev/null +++ b/database/mongodb/go.mod @@ -0,0 +1,61 @@ +module myapp + +go 1.22 + +require ( + github.com/joho/godotenv v1.5.1 + github.com/kataras/iris/v12 v12.2.11 + go.mongodb.org/mongo-driver v1.15.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/yosssi/ace v0.0.5 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/database/mongodb/go.sum b/database/mongodb/go.sum new file mode 100644 index 00000000..ee6ec6af --- /dev/null +++ b/database/mongodb/go.sum @@ -0,0 +1,207 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/database/mongodb/httputil/error.go b/database/mongodb/httputil/error.go new file mode 100644 index 00000000..4bcc740f --- /dev/null +++ b/database/mongodb/httputil/error.go @@ -0,0 +1,130 @@ +package httputil + +import ( + "errors" + "fmt" + "io" + "net/http" + "os" + "runtime" + "runtime/debug" + "strings" + "time" + + "github.com/kataras/iris/v12" +) + +var validStackFuncs = []func(string) bool{ + func(file string) bool { + return strings.Contains(file, "/mongodb/api/") + }, +} + +// RuntimeCallerStack returns the app's `file:line` stacktrace +// to give more information about an error cause. +func RuntimeCallerStack() (s string) { + var pcs [10]uintptr + n := runtime.Callers(1, pcs[:]) + frames := runtime.CallersFrames(pcs[:n]) + + for { + frame, more := frames.Next() + for _, fn := range validStackFuncs { + if fn(frame.File) { + s += fmt.Sprintf("\n\t\t\t%s:%d", frame.File, frame.Line) + } + } + + if !more { + break + } + } + + return s +} + +// HTTPError describes an HTTP error. +type HTTPError struct { + error + Stack string `json:"-"` // the whole stacktrace. + CallerStack string `json:"-"` // the caller, file:lineNumber + When time.Time `json:"-"` // the time that the error occurred. + // ErrorCode int: maybe a collection of known error codes. + StatusCode int `json:"statusCode"` + // could be named as "reason" as well + // it's the message of the error. + Description string `json:"description"` +} + +func newError(statusCode int, err error, format string, args ...interface{}) HTTPError { + if format == "" { + format = http.StatusText(statusCode) + } + + desc := fmt.Sprintf(format, args...) + if err == nil { + err = errors.New(desc) + } + + return HTTPError{ + err, + string(debug.Stack()), + RuntimeCallerStack(), + time.Now(), + statusCode, + desc, + } +} + +func (err HTTPError) writeHeaders(ctx iris.Context) { + ctx.StatusCode(err.StatusCode) + ctx.Header("X-Content-Type-Options", "nosniff") +} + +// LogFailure will print out the failure to the "logger". +func LogFailure(logger io.Writer, ctx iris.Context, err HTTPError) { + timeFmt := err.When.Format("2006/01/02 15:04:05") + firstLine := fmt.Sprintf("%s %s: %s", timeFmt, http.StatusText(err.StatusCode), err.Error()) + whitespace := strings.Repeat(" ", len(timeFmt)+1) + fmt.Fprintf(logger, "%s\n%sIP: %s\n%sURL: %s\n%sSource: %s\n", + firstLine, whitespace, ctx.RemoteAddr(), whitespace, ctx.FullRequestURI(), whitespace, err.CallerStack) +} + +// Fail will send the status code, write the error's reason +// and return the HTTPError for further use, i.e logging, see `InternalServerError`. +func Fail(ctx iris.Context, statusCode int, err error, format string, args ...interface{}) HTTPError { + httpErr := newError(statusCode, err, format, args...) + httpErr.writeHeaders(ctx) + + ctx.WriteString(httpErr.Description) + return httpErr +} + +// FailJSON will send to the client the error data as JSON. +// Useful for APIs. +func FailJSON(ctx iris.Context, statusCode int, err error, format string, args ...interface{}) HTTPError { + httpErr := newError(statusCode, err, format, args...) + httpErr.writeHeaders(ctx) + + ctx.JSON(httpErr) + + return httpErr +} + +// InternalServerError logs to the server's terminal +// and dispatches to the client the 500 Internal Server Error. +// Internal Server errors are critical, so we log them to the `os.Stderr`. +func InternalServerError(ctx iris.Context, err error, format string, args ...interface{}) { + LogFailure(os.Stderr, ctx, Fail(ctx, iris.StatusInternalServerError, err, format, args...)) +} + +// InternalServerErrorJSON acts exactly like `InternalServerError` but instead it sends the data as JSON. +// Useful for APIs. +func InternalServerErrorJSON(ctx iris.Context, err error, format string, args ...interface{}) { + LogFailure(os.Stderr, ctx, FailJSON(ctx, iris.StatusInternalServerError, err, format, args...)) +} + +// UnauthorizedJSON sends JSON format of StatusUnauthorized(401) HTTPError value. +func UnauthorizedJSON(ctx iris.Context, err error, format string, args ...interface{}) HTTPError { + return FailJSON(ctx, iris.StatusUnauthorized, err, format, args...) +} diff --git a/database/mongodb/main.go b/database/mongodb/main.go new file mode 100644 index 00000000..185d08f6 --- /dev/null +++ b/database/mongodb/main.go @@ -0,0 +1,83 @@ +package main + +// go get -u go.mongodb.org/mongo-driver +// go get -u github.com/joho/godotenv + +import ( + "context" + "flag" + "fmt" + "log" + "os" + + // APIs + storeapi "myapp/api/store" + + // + "myapp/env" + "myapp/store" + + "github.com/kataras/iris/v12" + + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +const version = "0.0.1" + +func init() { + envFileName := ".env" + + flagset := flag.CommandLine + flagset.StringVar(&envFileName, "env", envFileName, "the env file which web app will use to extract its environment variables") + flagset.Parse(os.Args[1:]) + + env.Load(envFileName) +} + +func main() { + clientOptions := options.Client().SetHosts([]string{env.DSN}) + client, err := mongo.Connect(context.Background(), clientOptions) + if err != nil { + log.Fatal(err) + } + + err = client.Ping(context.Background(), nil) + if err != nil { + log.Fatal(err) + } + defer client.Disconnect(context.TODO()) + + db := client.Database("store") + + var ( + // Collections. + moviesCollection = db.Collection("movies") + + // Services. + movieService = store.NewMovieService(moviesCollection) + ) + + app := iris.New() + app.Use(func(ctx iris.Context) { + ctx.Header("Server", "Iris MongoDB/"+version) + ctx.Next() + }) + + storeAPI := app.Party("/api/store") + { + movieHandler := storeapi.NewMovieHandler(movieService) + storeAPI.Get("/movies", movieHandler.GetAll) + storeAPI.Post("/movies", movieHandler.Add) + storeAPI.Get("/movies/{id}", movieHandler.Get) + storeAPI.Put("/movies/{id}", movieHandler.Update) + storeAPI.Delete("/movies/{id}", movieHandler.Delete) + } + + // GET: http://localhost:8080/api/store/movies + // POST: http://localhost:8080/api/store/movies + // GET: http://localhost:8080/api/store/movies/{id} + // PUT: http://localhost:8080/api/store/movies/{id} + // DELETE: http://localhost:8080/api/store/movies/{id} + app.Listen(fmt.Sprintf(":%s", env.Port), iris.WithOptimizations) +} diff --git a/database/mongodb/store/movie.go b/database/mongodb/store/movie.go new file mode 100644 index 00000000..133cddc9 --- /dev/null +++ b/database/mongodb/store/movie.go @@ -0,0 +1,180 @@ +package store + +import ( + "context" + "errors" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" + // up to you: + // "go.mongodb.org/mongo-driver/mongo/options" +) + +type Movie struct { + ID primitive.ObjectID `json:"_id" bson:"_id"` /* you need the bson:"_id" to be able to retrieve with ID filled */ + Name string `json:"name"` + Cover string `json:"cover"` + Description string `json:"description"` +} + +type MovieService interface { + GetAll(ctx context.Context) ([]Movie, error) + GetByID(ctx context.Context, id string) (Movie, error) + Create(ctx context.Context, m *Movie) error + Update(ctx context.Context, id string, m Movie) error + Delete(ctx context.Context, id string) error +} + +type movieService struct { + C *mongo.Collection +} + +var _ MovieService = (*movieService)(nil) + +func NewMovieService(collection *mongo.Collection) MovieService { + // up to you: + // indexOpts := new(options.IndexOptions) + // indexOpts.SetName("movieIndex"). + // SetUnique(true). + // SetBackground(true). + // SetSparse(true) + + // collection.Indexes().CreateOne(context.Background(), mongo.IndexModel{ + // Keys: []string{"_id", "name"}, + // Options: indexOpts, + // }) + + return &movieService{C: collection} +} + +func (s *movieService) GetAll(ctx context.Context) ([]Movie, error) { + // Note: + // The mongodb's go-driver's docs says that you can pass `nil` to "find all" but this gives NilDocument error, + // probably it's a bug or a documentation's mistake, you have to pass `bson.D{}` instead. + cur, err := s.C.Find(ctx, bson.D{}) + if err != nil { + return nil, err + } + defer cur.Close(ctx) + + var results []Movie + + for cur.Next(ctx) { + if err = cur.Err(); err != nil { + return nil, err + } + + // elem := bson.D{} + var elem Movie + err = cur.Decode(&elem) + if err != nil { + return nil, err + } + + // results = append(results, Movie{ID: elem[0].Value.(primitive.ObjectID)}) + + results = append(results, elem) + } + + return results, nil +} + +func matchID(id string) (bson.D, error) { + objectID, err := primitive.ObjectIDFromHex(id) + if err != nil { + return nil, err + } + + filter := bson.D{{Key: "_id", Value: objectID}} + return filter, nil +} + +var ErrNotFound = errors.New("not found") + +func (s *movieService) GetByID(ctx context.Context, id string) (Movie, error) { + var movie Movie + filter, err := matchID(id) + if err != nil { + return movie, err + } + + err = s.C.FindOne(ctx, filter).Decode(&movie) + if err == mongo.ErrNoDocuments { + return movie, ErrNotFound + } + return movie, err +} + +func (s *movieService) Create(ctx context.Context, m *Movie) error { + if m.ID.IsZero() { + m.ID = primitive.NewObjectID() + } + + _, err := s.C.InsertOne(ctx, m) + if err != nil { + return err + } + + // The following doesn't work if you have the `bson:"_id` on Movie.ID field, + // therefore we manually generate a new ID (look above). + // res, err := ...InsertOne + // objectID := res.InsertedID.(primitive.ObjectID) + // m.ID = objectID + return nil +} + +func (s *movieService) Update(ctx context.Context, id string, m Movie) error { + filter, err := matchID(id) + if err != nil { + return err + } + + // update := bson.D{ + // {Key: "$set", Value: m}, + // } + // ^ this will override all fields, you can do that, depending on your design. but let's check each field: + elem := bson.D{} + + if m.Name != "" { + elem = append(elem, bson.E{Key: "name", Value: m.Name}) + } + + if m.Description != "" { + elem = append(elem, bson.E{Key: "description", Value: m.Description}) + } + + if m.Cover != "" { + elem = append(elem, bson.E{Key: "cover", Value: m.Cover}) + } + + update := bson.D{ + {Key: "$set", Value: elem}, + } + + _, err = s.C.UpdateOne(ctx, filter, update) + if err != nil { + if err == mongo.ErrNoDocuments { + return ErrNotFound + } + return err + } + + return nil +} + +func (s *movieService) Delete(ctx context.Context, id string) error { + filter, err := matchID(id) + if err != nil { + return err + } + _, err = s.C.DeleteOne(ctx, filter) + if err != nil { + if err == mongo.ErrNoDocuments { + return ErrNotFound + } + return err + } + + return nil +} diff --git a/database/mysql/Dockerfile b/database/mysql/Dockerfile new file mode 100644 index 00000000..dec864fe --- /dev/null +++ b/database/mysql/Dockerfile @@ -0,0 +1,17 @@ +# docker build -t myapp . +# docker run --rm -it -p 8080:8080 myapp:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/myapp . +ENTRYPOINT ["./myapp"] \ No newline at end of file diff --git a/database/mysql/README.md b/database/mysql/README.md new file mode 100644 index 00000000..1f218aac --- /dev/null +++ b/database/mysql/README.md @@ -0,0 +1,146 @@ +# Iris, MySQL, Groupcache & Docker Example + +## 📘 Endpoints + +| Method | Path | Description | URL Parameters | Body | Auth Required | +|--------|---------------------|------------------------|--------------- |----------------------------|---------------| +| ANY | /token | Prints a new JWT Token | - | - | - | +| GET | /category | Lists a set of Categories | offset, limit, order | - | Token | +| POST | /category | Creates a Category | - | JSON [Full Category](migration/api_category/create_category.json) | Token | +| PUT | /category | Fully-Updates a Category | - | JSON [Full Category](migration/api_category/update_category.json) | Token | +| PATCH | /category/{id} | Partially-Updates a Category | - | JSON [Partial Category](migration/api_category/update_partial_category.json) | Token | +| GET | /category/{id} | Prints a Category | - | - | Token | +| DELETE | /category/{id} | Deletes a Category | - | - | Token | +| GET | /category/{id}/products | Lists all Products from a Category | offset, limit, order | - | Token | +| POST | /category/{id}/products | (Batch) Assigns one or more Products to a Category | - | JSON [Products](migration/api_category/insert_products_category.json) | Token | +| GET | /product | Lists a set of Products (cache) | offset, limit, order | - | Token | +| POST | /product | Creates a Product | - | JSON [Full Product](migration/api_product/create_product.json) | Token | +| PUT | /product | Fully-Updates a Product | - | JSON [Full Product](migration/api_product/update_product.json) | Token | +| PATCH | /product/{id} | Partially-Updates a Product | - | JSON [Partial Product](migration/api_product/update_partial_product.json) | Token | +| GET | /product/{id} | Prints a Product (cache) | - | - | Token | +| DELETE | /product/{id} | Deletes a Product | - | - | Token | + + + +## 📑 Responses + +* **Content-Type** of `"application/json;charset=utf-8"`, snake_case naming (identical to the database columns) +* **Status Codes** + * 500 for server(db) errors, + * 422 for validation errors, e.g. + ```json + { + "code": 422, + "message": "required fields are missing", + "timestamp": 1589306271 + } + ``` + * 400 for malformed syntax, e.g. + ```json + { + "code": 400, + "message": "json: cannot unmarshal number -2 into Go struct field Category.position of type uint64", + "timestamp": 1589306325 + } + ``` + ```json + { + "code": 400, + "message": "json: unknown field \"field_not_exists\"", + "timestamp": 1589306367 + } + ``` + * 404 for entity not found, e.g. + ```json + { + "code": 404, + "message": "entity does not exist", + "timestamp": 1589306199 + } + ``` + * 304 for unaffected UPDATE or DELETE, + * 201 for CREATE with the last inserted ID, + * 200 for GET, UPDATE and DELETE + +## ⚡ Get Started + +Download the folder. + +### Install (Docker) + +Install [Docker](https://www.docker.com/) and execute the command below + +```sh +$ docker-compose up --build +``` + +### Install (Manually) + +Run `go build -mod=mod` or `go run -mod=mod main.go` and read below. + +#### MySQL + +Environment variables: + +```sh +MYSQL_USER=user_myapp +MYSQL_PASSWORD=dbpassword +MYSQL_HOST=localhost +MYSQL_DATABASE=myapp +``` + +Download the schema from [migration/db.sql](migration/db.sql) and execute it against your MySQL server instance. + +```sql +CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE myapp; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS categories; +CREATE TABLE categories ( + id int(11) NOT NULL AUTO_INCREMENT, + title varchar(255) NOT NULL, + position int(11) NOT NULL, + image_url varchar(255) NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); + +DROP TABLE IF EXISTS products; +CREATE TABLE products ( + id int(11) NOT NULL AUTO_INCREMENT, + category_id int, + title varchar(255) NOT NULL, + image_url varchar(255) NOT NULL, + price decimal(10,2) NOT NULL, + description text NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + FOREIGN KEY (category_id) REFERENCES categories(id) +); + +SET FOREIGN_KEY_CHECKS = 1; +``` + +### Requests + +Some request bodies can be found at: [migration/api_category](migration/api_category) and [migration/api_product](migration/api_product). **However** I've provided a [postman.json](migration/myapp_postman.json) Collection that you can import to your [POSTMAN](https://learning.postman.com/docs/postman/collections/importing-and-exporting-data/#collections) and start playing with the API. + +All write-access endpoints are "protected" via JWT, a client should "verify" itself. You'll need to manually take the **token** from the `http://localhost:8080/token` and put it on url parameter `?token=$token` or to the `Authentication: Bearer $token` request header. + +### Unit or End-To-End Testing? + +Testing is important. The code is written in a way that testing should be trivial (Pseudo/memory Database or SQLite local file could be integrated as well, for end-to-end tests a Docker image with MySQL and fire tests against that server). However, there is [nothing(?)](service/category_service_test.go) to see here. + +## Packages + +- https://github.com/kataras/jwt (JWT parsing) +- https://github.com/go-sql-driver/mysql (Go Driver for MySQL) +- https://github.com/DATA-DOG/go-sqlmock (Testing DB see [service/category_service_test.go](service/category_service_test.go)) +- https://github.com/kataras/iris (HTTP) +- https://github.com/mailgun/groupcache (Caching) diff --git a/database/mysql/api/api.go b/database/mysql/api/api.go new file mode 100644 index 00000000..23f16696 --- /dev/null +++ b/database/mysql/api/api.go @@ -0,0 +1,92 @@ +// Package api contains the handlers for our HTTP Endpoints. +package api + +import ( + "time" + + "myapp/service" + "myapp/sql" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" + "github.com/kataras/iris/v12/middleware/requestid" +) + +// Router accepts any required dependencies and returns the main server's handler. +func Router(db sql.Database, secret string) func(iris.Party) { + return func(r iris.Party) { + r.Use(requestid.New()) + + signer := jwt.NewSigner(jwt.HS256, secret, 15*time.Minute) + r.Get("/token", writeToken(signer)) + + verify := jwt.NewVerifier(jwt.HS256, secret).Verify(nil) + r.Use(verify) + // Generate a token for testing by navigating to + // http://localhost:8080/token endpoint. + // Copy-paste it to a ?token=$token url parameter or + // open postman and put an Authentication: Bearer $token to get + // access on create, update and delete endpoinds. + + var ( + categoryService = service.NewCategoryService(db) + productService = service.NewProductService(db) + ) + + cat := r.Party("/category") + { + // TODO: new Use to add middlewares to specific + // routes per METHOD ( we already have the per path through parties.) + handler := NewCategoryHandler(categoryService) + + cat.Get("/", handler.List) + cat.Post("/", handler.Create) + cat.Put("/", handler.Update) + + cat.Get("/{id:int64}", handler.GetByID) + cat.Patch("/{id:int64}", handler.PartialUpdate) + cat.Delete("/{id:int64}", handler.Delete) + /* You can also do something like that: + cat.PartyFunc("/{id:int64}", func(c iris.Party) { + c.Get("/", handler.GetByID) + c.Post("/", handler.PartialUpdate) + c.Delete("/", handler.Delete) + }) + */ + + cat.Get("/{id:int64}/products", handler.ListProducts) + cat.Post("/{id:int64}/products", handler.InsertProducts(productService)) + } + + prod := r.Party("/product") + { + handler := NewProductHandler(productService) + + prod.Get("/", handler.List) + prod.Post("/", handler.Create) + prod.Put("/", handler.Update) + + prod.Get("/{id:int64}", handler.GetByID) + prod.Patch("/{id:int64}", handler.PartialUpdate) + prod.Delete("/{id:int64}", handler.Delete) + } + + } +} + +func writeToken(signer *jwt.Signer) iris.Handler { + return func(ctx iris.Context) { + claims := jwt.Claims{ + Issuer: "https://iris-go.com", + Audience: []string{requestid.Get(ctx)}, + } + + token, err := signer.Sign(claims) + if err != nil { + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + ctx.Write(token) + } +} diff --git a/database/mysql/api/category_handler.go b/database/mysql/api/category_handler.go new file mode 100644 index 00000000..fcddbd95 --- /dev/null +++ b/database/mysql/api/category_handler.go @@ -0,0 +1,256 @@ +package api + +import ( + "myapp/entity" + "myapp/service" + "myapp/sql" + + "github.com/kataras/iris/v12" +) + +// CategoryHandler is the http mux for categories. +type CategoryHandler struct { + // [...options] + + service *service.CategoryService +} + +// NewCategoryHandler returns the main controller for the categories API. +func NewCategoryHandler(service *service.CategoryService) *CategoryHandler { + return &CategoryHandler{service} +} + +// GetByID fetches a single record from the database and sends it to the client. +// Method: GET. +func (h *CategoryHandler) GetByID(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + var cat entity.Category + err := h.service.GetByID(ctx.Request().Context(), &cat, id) + if err != nil { + if err == sql.ErrNoRows { + writeEntityNotFound(ctx) + return + } + + debugf("CategoryHandler.GetByID(id=%d): %v", id, err) + writeInternalServerError(ctx) + return + } + + ctx.JSON(cat) +} + +/* + +type ( + List struct { + Data interface{} `json:"data"` + Order string `json:"order"` + Next Range `json:"next,omitempty"` + Prev Range `json:"prev,omitempty"` + } + + Range struct { + Offset int64 `json:"offset"` + Limit int64 `json:"limit` + } +) +*/ + +// List lists a set of records from the database. +// Method: GET. +func (h *CategoryHandler) List(ctx iris.Context) { + q := ctx.Request().URL.Query() + opts := sql.ParseListOptions(q) + + // initialize here in order to return an empty json array `[]` instead of `null`. + categories := entity.Categories{} + err := h.service.List(ctx.Request().Context(), &categories, opts) + if err != nil && err != sql.ErrNoRows { + debugf("CategoryHandler.List(DB) (limit=%d offset=%d where=%s=%v): %v", + opts.Limit, opts.Offset, opts.WhereColumn, opts.WhereValue, err) + + writeInternalServerError(ctx) + return + } + + ctx.JSON(categories) +} + +// Create adds a record to the database. +// Method: POST. +func (h *CategoryHandler) Create(ctx iris.Context) { + var cat entity.Category + if err := ctx.ReadJSON(&cat); err != nil { + return + } + + id, err := h.service.Insert(ctx.Request().Context(), cat) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "required fields are missing")) + return + } + + debugf("CategoryHandler.Create(DB): %v", err) + writeInternalServerError(ctx) + return + } + + // Send 201 with body of {"id":$last_inserted_id"}. + ctx.StatusCode(iris.StatusCreated) + ctx.JSON(iris.Map{cat.PrimaryKey(): id}) +} + +// Update performs a full-update of a record in the database. +// Method: PUT. +func (h *CategoryHandler) Update(ctx iris.Context) { + var cat entity.Category + if err := ctx.ReadJSON(&cat); err != nil { + return + } + + affected, err := h.service.Update(ctx.Request().Context(), cat) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "required fields are missing")) + return + } + + debugf("CategoryHandler.Update(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} + +// PartialUpdate is the handler for partially update one or more fields of the record. +// Method: PATCH. +func (h *CategoryHandler) PartialUpdate(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + var attrs map[string]interface{} + if err := ctx.ReadJSON(&attrs); err != nil { + return + } + + affected, err := h.service.PartialUpdate(ctx.Request().Context(), id, attrs) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "unsupported value(s)")) + return + } + + debugf("CategoryHandler.PartialUpdate(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} + +// Delete removes a record from the database. +// Method: DELETE. +func (h *CategoryHandler) Delete(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + affected, err := h.service.DeleteByID(ctx.Request().Context(), id) + if err != nil { + if err == sql.ErrNoRows { + writeEntityNotFound(ctx) + return + } + + debugf("CategoryHandler.Delete(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK // StatusNoContent + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} + +// Products. + +// ListProducts lists products of a Category. +// Example: from cheap to expensive: +// http://localhost:8080/category/3/products?offset=0&limit=30&by=price&order=asc +// Method: GET. +func (h *CategoryHandler) ListProducts(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + // NOTE: could add cache here too. + + q := ctx.Request().URL.Query() + opts := sql.ParseListOptions(q).Where("category_id", id) + opts.Table = "products" + if opts.OrderByColumn == "" { + opts.OrderByColumn = "updated_at" + } + + var products entity.Products + err := h.service.List(ctx.Request().Context(), &products, opts) + if err != nil && err != sql.ErrNoRows { + debugf("CategoryHandler.ListProducts(DB) (table=%s where=%s=%v limit=%d offset=%d): %v", + opts.Table, opts.WhereColumn, opts.WhereValue, opts.Limit, opts.Offset, err) + + writeInternalServerError(ctx) + return + } + + ctx.JSON(products) +} + +// InsertProducts assigns new products to a Category (accepts a list of products). +// Method: POST. +func (h *CategoryHandler) InsertProducts(productService *service.ProductService) iris.Handler { + return func(ctx iris.Context) { + categoryID := ctx.Params().GetInt64Default("id", 0) + + var products []entity.Product + if err := ctx.ReadJSON(&products); err != nil { + return + } + + for i := range products { + products[i].CategoryID = categoryID + } + + inserted, err := productService.BatchInsert(ctx.Request().Context(), products) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "required fields are missing")) + return + } + + debugf("CategoryHandler.InsertProducts(DB): %v", err) + writeInternalServerError(ctx) + return + } + + if inserted == 0 { + ctx.StatusCode(iris.StatusNotModified) + return + } + + // Send 201 with body of {"inserted":$inserted"}. + ctx.StatusCode(iris.StatusCreated) + ctx.JSON(iris.Map{"inserted": inserted}) + } +} diff --git a/database/mysql/api/helper.go b/database/mysql/api/helper.go new file mode 100644 index 00000000..8ee14c0f --- /dev/null +++ b/database/mysql/api/helper.go @@ -0,0 +1,25 @@ +package api + +import ( + "log" + + "github.com/kataras/iris/v12" +) + +const debug = true + +func debugf(format string, args ...interface{}) { + if !debug { + return + } + + log.Printf(format, args...) +} + +func writeInternalServerError(ctx iris.Context) { + ctx.StopWithJSON(iris.StatusInternalServerError, newError(iris.StatusInternalServerError, ctx.Request().Method, ctx.Path(), "")) +} + +func writeEntityNotFound(ctx iris.Context) { + ctx.StopWithJSON(iris.StatusNotFound, newError(iris.StatusNotFound, ctx.Request().Method, ctx.Path(), "entity does not exist")) +} diff --git a/database/mysql/api/httperror.go b/database/mysql/api/httperror.go new file mode 100644 index 00000000..7b599eeb --- /dev/null +++ b/database/mysql/api/httperror.go @@ -0,0 +1,60 @@ +package api + +import ( + "fmt" + "time" + + "github.com/kataras/iris/v12" +) + +// Error holds the error sent by server to clients (JSON). +type Error struct { + StatusCode int `json:"code"` + Method string `json:"-"` + Path string `json:"-"` + Message string `json:"message"` + Timestamp int64 `json:"timestamp"` +} + +func newError(statusCode int, method, path, format string, args ...interface{}) Error { + msg := format + if len(args) > 0 { + // why we check for that? If the original error message came from our database + // and it contains fmt-reserved words + // like %s or %d we will get MISSING(=...) in our error message and we don't want that. + msg = fmt.Sprintf(msg, args...) + } + + if msg == "" { + msg = iris.StatusText(statusCode) + } + + return Error{ + StatusCode: statusCode, + Method: method, + Path: path, + Message: msg, + Timestamp: time.Now().Unix(), + } +} + +// Error implements the internal Go error interface. +func (e Error) Error() string { + return fmt.Sprintf("[%d] %s: %s: %s", e.StatusCode, e.Method, e.Path, e.Message) +} + +// Is implements the standard `errors.Is` internal interface. +// Usage: errors.Is(e, target) +func (e Error) Is(target error) bool { + if target == nil { + return false + } + + err, ok := target.(Error) + if !ok { + return false + } + + return (err.StatusCode == e.StatusCode || e.StatusCode == 0) && + (err.Message == e.Message || e.Message == "") +} diff --git a/http_request/upload-file/uploads/.gitkeep b/database/mysql/api/middleware/.gitkeep similarity index 100% rename from http_request/upload-file/uploads/.gitkeep rename to database/mysql/api/middleware/.gitkeep diff --git a/database/mysql/api/product_handler.go b/database/mysql/api/product_handler.go new file mode 100644 index 00000000..31250bf3 --- /dev/null +++ b/database/mysql/api/product_handler.go @@ -0,0 +1,173 @@ +package api + +import ( + "time" + + "myapp/cache" + "myapp/entity" + "myapp/service" + "myapp/sql" + + "github.com/kataras/iris/v12" +) + +// ProductHandler is the http mux for products. +type ProductHandler struct { + service *service.ProductService + cache *cache.Cache +} + +// NewProductHandler returns the main controller for the products API. +func NewProductHandler(service *service.ProductService) *ProductHandler { + return &ProductHandler{ + service: service, + cache: cache.New(service, "products", time.Minute), + } +} + +// GetByID fetches a single record from the database and sends it to the client. +// Method: GET. +func (h *ProductHandler) GetByID(ctx iris.Context) { + id := ctx.Params().GetString("id") + + var product []byte + err := h.cache.GetByID(ctx.Request().Context(), id, &product) + if err != nil { + if err == sql.ErrNoRows { + writeEntityNotFound(ctx) + return + } + + debugf("ProductHandler.GetByID(id=%v): %v", id, err) + writeInternalServerError(ctx) + return + } + + ctx.ContentType("application/json") + ctx.Write(product) + + // ^ Could use our simple `noCache` or implement a Cache-Control (see kataras/iris/cache for that) + // but let's keep it simple. +} + +// List lists a set of records from the database. +// Method: GET. +func (h *ProductHandler) List(ctx iris.Context) { + key := ctx.Request().URL.RawQuery + + products := []byte("[]") + err := h.cache.List(ctx.Request().Context(), key, &products) + if err != nil && err != sql.ErrNoRows { + debugf("ProductHandler.List(DB) (%s): %v", + key, err) + + writeInternalServerError(ctx) + return + } + + ctx.ContentType("application/json") + ctx.Write(products) +} + +// Create adds a record to the database. +// Method: POST. +func (h *ProductHandler) Create(ctx iris.Context) { + var product entity.Product + if err := ctx.ReadJSON(&product); err != nil { + return + } + + id, err := h.service.Insert(ctx.Request().Context(), product) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "required fields are missing")) + return + } + + debugf("ProductHandler.Create(DB): %v", err) + writeInternalServerError(ctx) + return + } + + // Send 201 with body of {"id":$last_inserted_id"}. + ctx.StatusCode(iris.StatusCreated) + ctx.JSON(iris.Map{product.PrimaryKey(): id}) +} + +// Update performs a full-update of a record in the database. +// Method: PUT. +func (h *ProductHandler) Update(ctx iris.Context) { + var product entity.Product + if err := ctx.ReadJSON(&product); err != nil { + return + } + + affected, err := h.service.Update(ctx.Request().Context(), product) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "required fields are missing")) + return + } + + debugf("ProductHandler.Update(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} + +// PartialUpdate is the handler for partially update one or more fields of the record. +// Method: PATCH. +func (h *ProductHandler) PartialUpdate(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + var attrs map[string]interface{} + if err := ctx.ReadJSON(&attrs); err != nil { + return + } + + affected, err := h.service.PartialUpdate(ctx.Request().Context(), id, attrs) + if err != nil { + if err == sql.ErrUnprocessable { + ctx.StopWithJSON(iris.StatusUnprocessableEntity, newError(iris.StatusUnprocessableEntity, ctx.Request().Method, ctx.Path(), "unsupported value(s)")) + return + } + + debugf("ProductHandler.PartialUpdate(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} + +// Delete removes a record from the database. +// Method: DELETE. +func (h *ProductHandler) Delete(ctx iris.Context) { + id := ctx.Params().GetInt64Default("id", 0) + + affected, err := h.service.DeleteByID(ctx.Request().Context(), id) + if err != nil { + debugf("ProductHandler.Delete(DB): %v", err) + writeInternalServerError(ctx) + return + } + + status := iris.StatusOK // StatusNoContent + if affected == 0 { + status = iris.StatusNotModified + } + + ctx.StatusCode(status) +} diff --git a/database/mysql/cache/groupcache.go b/database/mysql/cache/groupcache.go new file mode 100644 index 00000000..4fb4e30d --- /dev/null +++ b/database/mysql/cache/groupcache.go @@ -0,0 +1,120 @@ +package cache + +import ( + "context" + "encoding/json" + "net/url" + "strconv" + "time" + + "myapp/entity" + "myapp/sql" + + "github.com/mailgun/groupcache/v2" +) + +// Service that cache will use to retrieve data. +type Service interface { + RecordInfo() sql.Record + GetByID(ctx context.Context, dest interface{}, id int64) error + List(ctx context.Context, dest interface{}, opts sql.ListOptions) error +} + +// Cache is a simple structure which holds the groupcache and the database service, exposes +// `GetByID` and `List` which returns cached (or stores new) items. +type Cache struct { + service Service + maxAge time.Duration + group *groupcache.Group +} + +// Size default size to use on groupcache, defaults to 3MB. +var Size int64 = 3 << (10 * 3) + +// New returns a new cache service which exposes `GetByID` and `List` methods to work with. +// The "name" should be unique, "maxAge" for cache expiration. +func New(service Service, name string, maxAge time.Duration) *Cache { + c := new(Cache) + c.service = service + c.maxAge = maxAge + c.group = groupcache.NewGroup(name, Size, c) + return c +} + +const ( + prefixID = "#" + prefixList = "[" +) + +// Get implements the groupcache.Getter interface. +// Use `GetByID` and `List` instead. +func (c *Cache) Get(ctx context.Context, key string, dest groupcache.Sink) error { + if len(key) < 2 { // empty or missing prefix+key, should never happen. + return sql.ErrUnprocessable + } + + var v interface{} + + prefix := key[0:1] + key = key[1:] + switch prefix { + case prefixID: + // Get by ID. + id, err := strconv.ParseInt(key, 10, 64) + if err != nil || id <= 0 { + return err + } + + switch c.service.RecordInfo().(type) { + case *entity.Category: + v = new(entity.Category) + case *entity.Product: + v = new(entity.Product) + } + + err = c.service.GetByID(ctx, v, id) + if err != nil { + return err + } + + case prefixList: + // Get a set of records, list. + q, err := url.ParseQuery(key) + if err != nil { + return err + } + opts := sql.ParseListOptions(q) + + switch c.service.RecordInfo().(type) { + case *entity.Category: + v = new(entity.Categories) + case *entity.Product: + v = new(entity.Products) + } + + err = c.service.List(ctx, v, opts) + if err != nil { + return err + } + + default: + return sql.ErrUnprocessable + } + + b, err := json.Marshal(v) + if err != nil { + return err + } + + return dest.SetBytes(b, time.Now().Add(c.maxAge)) +} + +// GetByID binds an item to "dest" an item based on its "id". +func (c *Cache) GetByID(ctx context.Context, id string, dest *[]byte) error { + return c.group.Get(ctx, prefixID+id, groupcache.AllocatingByteSliceSink(dest)) +} + +// List binds item to "dest" based on the "rawQuery" of `url.Values` for `ListOptions`. +func (c *Cache) List(ctx context.Context, rawQuery string, dest *[]byte) error { + return c.group.Get(ctx, prefixList+rawQuery, groupcache.AllocatingByteSliceSink(dest)) +} diff --git a/database/mysql/docker-compose.yml b/database/mysql/docker-compose.yml new file mode 100644 index 00000000..715a20d4 --- /dev/null +++ b/database/mysql/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.1' + +services: + db: + image: mysql + command: --default-authentication-plugin=mysql_native_password + environment: + MYSQL_ROOT_PASSWORD: dbpassword + MYSQL_DATABASE: myapp + MYSQL_USER: user_myapp + MYSQL_PASSWORD: dbpassword + tty: true + volumes: + - ./migration:/docker-entrypoint-initdb.d + app: + build: . + ports: + - 8080:8080 + environment: + PORT: 8080 + MYSQL_USER: user_myapp + MYSQL_PASSWORD: dbpassword + MYSQL_DATABASE: myapp + MYSQL_HOST: db + restart: on-failure + healthcheck: + test: ["CMD", "curl", "-f", "tcp://db:3306"] + interval: 30s + timeout: 10s + retries: 5 + depends_on: + - db \ No newline at end of file diff --git a/database/mysql/entity/category.go b/database/mysql/entity/category.go new file mode 100644 index 00000000..61dae29f --- /dev/null +++ b/database/mysql/entity/category.go @@ -0,0 +1,89 @@ +package entity + +import ( + "database/sql" + "time" +) + +// Category represents the categories entity. +// Each product belongs to a category, see `Product.CategoryID` field. +// It implements the `sql.Record` and `sql.Sorted` interfaces. +type Category struct { + ID int64 `db:"id" json:"id"` + Title string `db:"title" json:"title"` + Position uint64 `db:"position" json:"position"` + ImageURL string `db:"image_url" json:"image_url"` + + // We could use: sql.NullTime or unix time seconds (as int64), + // note that the dsn parameter "parseTime=true" is required now in order to fill this field correctly. + CreatedAt *time.Time `db:"created_at" json:"created_at"` + UpdatedAt *time.Time `db:"updated_at" json:"updated_at"` +} + +// TableName returns the database table name of a Category. +func (c *Category) TableName() string { + return "categories" +} + +// PrimaryKey returns the primary key of a Category. +func (c *Category) PrimaryKey() string { + return "id" +} + +// SortBy returns the column name that +// should be used as a fallback for sorting a set of Category. +func (c *Category) SortBy() string { + return "position" +} + +// Scan binds mysql rows to this Category. +func (c *Category) Scan(rows *sql.Rows) error { + c.CreatedAt = new(time.Time) + c.UpdatedAt = new(time.Time) + return rows.Scan(&c.ID, &c.Title, &c.Position, &c.ImageURL, &c.CreatedAt, &c.UpdatedAt) +} + +// Categories a list of categories. Implements the `Scannable` interface. +type Categories []*Category + +// Scan binds mysql rows to this Categories. +func (cs *Categories) Scan(rows *sql.Rows) (err error) { + cp := *cs + for rows.Next() { + c := new(Category) + if err = c.Scan(rows); err != nil { + return + } + cp = append(cp, c) + } + + if len(cp) == 0 { + return sql.ErrNoRows + } + + *cs = cp + + return rows.Err() +} + +/* +// The requests. +type ( + CreateCategoryRequest struct { + Title string `json:"title"` // all required. + Position uint64 `json:"position"` + ImageURL string `json:"imageURL"` + } + + UpdateCategoryRequest CreateCategoryRequest // at least 1 required. + + GetCategoryRequest struct { + ID int64 `json:"id"` // required. + } + + DeleteCategoryRequest GetCategoryRequest + + GetCategoriesRequest struct { + // [limit, offset...] + } +)*/ diff --git a/database/mysql/entity/product.go b/database/mysql/entity/product.go new file mode 100644 index 00000000..bb352fba --- /dev/null +++ b/database/mysql/entity/product.go @@ -0,0 +1,95 @@ +package entity + +import ( + "database/sql" + "time" +) + +// Product represents the products entity. +// It implements the `sql.Record` and `sql.Sorted` interfaces. +type Product struct { + ID int64 `db:"id" json:"id"` + CategoryID int64 `db:"category_id" json:"category_id"` + Title string `db:"title" json:"title"` + ImageURL string `db:"image_url" json:"image_url"` + Price float32 `db:"price" json:"price"` + Description string `db:"description" json:"description"` + CreatedAt *time.Time `db:"created_at" json:"created_at"` + UpdatedAt *time.Time `db:"updated_at" json:"updated_at"` +} + +// TableName returns the database table name of a Product. +func (p Product) TableName() string { + return "products" +} + +// PrimaryKey returns the primary key of a Product. +func (p *Product) PrimaryKey() string { + return "id" +} + +// SortBy returns the column name that +// should be used as a fallback for sorting a set of Product. +func (p *Product) SortBy() string { + return "updated_at" +} + +// ValidateInsert simple check for empty fields that should be required. +func (p *Product) ValidateInsert() bool { + return p.CategoryID > 0 && p.Title != "" && p.ImageURL != "" && p.Price > 0 /* decimal* */ && p.Description != "" +} + +// Scan binds mysql rows to this Product. +func (p *Product) Scan(rows *sql.Rows) error { + p.CreatedAt = new(time.Time) + p.UpdatedAt = new(time.Time) + return rows.Scan(&p.ID, &p.CategoryID, &p.Title, &p.ImageURL, &p.Price, &p.Description, &p.CreatedAt, &p.UpdatedAt) +} + +// Products is a list of products. Implements the `Scannable` interface. +type Products []*Product + +// Scan binds mysql rows to this Categories. +func (ps *Products) Scan(rows *sql.Rows) (err error) { + cp := *ps + for rows.Next() { + p := new(Product) + if err = p.Scan(rows); err != nil { + return + } + cp = append(cp, p) + } + + if len(cp) == 0 { + return sql.ErrNoRows + } + + *ps = cp + + return rows.Err() +} + +/* +// The requests. +type ( + CreateProductRequest struct { // all required. + CategoryID int64 `json:"categoryID"` + Title string `json:"title"` + ImageURL string `json:"imageURL"` + Price float32 `json:"price"` + Description string `json:"description"` + } + + UpdateProductRequest CreateProductRequest // at least 1 required. + + GetProductRequest struct { + ID int64 `json:"id"` // required. + } + + DeleteProductRequest GetProductRequest + + GetProductsRequest struct { + // [page, offset...] + } +) +*/ diff --git a/database/mysql/go.mod b/database/mysql/go.mod new file mode 100644 index 00000000..654c903e --- /dev/null +++ b/database/mysql/go.mod @@ -0,0 +1,60 @@ +module myapp + +go 1.22 + +require ( + github.com/DATA-DOG/go-sqlmock v1.5.2 + github.com/go-sql-driver/mysql v1.8.1 + github.com/kataras/iris/v12 v12.2.11 + github.com/mailgun/groupcache/v2 v2.5.0 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/jwt v0.1.12 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/segmentio/fasthash v1.0.3 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/database/mysql/go.sum b/database/mysql/go.sum new file mode 100644 index 00000000..f0662bc5 --- /dev/null +++ b/database/mysql/go.sum @@ -0,0 +1,200 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/jwt v0.1.12 h1:FHPgTTj5UqjlBye4PA4/oxknCY+kQ9K34XAi8d37glA= +github.com/kataras/jwt v0.1.12/go.mod h1:xkimAtDhU/aGlQqjwvgtg+VyuPwMiyZHaY8LJRh0mYo= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/groupcache/v2 v2.5.0 h1:FoNR52GyTQ4jLoliSuyXDANMEoxts6M8ql9jW3htvq8= +github.com/mailgun/groupcache/v2 v2.5.0/go.mod h1:7+O6vXEKAhloSTOJOmkhyksS8l/gIs15fv0ER1ZuhPA= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/database/mysql/main.go b/database/mysql/main.go new file mode 100644 index 00000000..a135a317 --- /dev/null +++ b/database/mysql/main.go @@ -0,0 +1,44 @@ +package main // Look README.md + +import ( + "fmt" + "log" + "os" + + "myapp/api" + "myapp/sql" + + "github.com/kataras/iris/v12" +) + +func main() { + dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true&charset=utf8mb4&collation=utf8mb4_unicode_ci", + getenv("MYSQL_USER", "user_myapp"), + getenv("MYSQL_PASSWORD", "dbpassword"), + getenv("MYSQL_HOST", "localhost"), + getenv("MYSQL_DATABASE", "myapp"), + ) + + db, err := sql.ConnectMySQL(dsn) + if err != nil { + log.Fatalf("error connecting to the MySQL database: %v", err) + } + + secret := getenv("JWT_SECRET", "EbnJO3bwmX") + + app := iris.New() + subRouter := api.Router(db, secret) + app.PartyFunc("/", subRouter) + + addr := fmt.Sprintf(":%s", getenv("PORT", "8080")) + app.Listen(addr) +} + +func getenv(key string, def string) string { + v := os.Getenv(key) + if v == "" { + return def + } + + return v +} diff --git a/database/mysql/migration/api_category/create_category.json b/database/mysql/migration/api_category/create_category.json new file mode 100644 index 00000000..3ea1efa5 --- /dev/null +++ b/database/mysql/migration/api_category/create_category.json @@ -0,0 +1,5 @@ +{ + "title": "computer-internet", + "position": 2, + "image_url": "https://bp.pstatic.gr/public/dist/images/1mOPxYtw1k.webp" +} \ No newline at end of file diff --git a/database/mysql/migration/api_category/insert_products_category.json b/database/mysql/migration/api_category/insert_products_category.json new file mode 100644 index 00000000..02051b7d --- /dev/null +++ b/database/mysql/migration/api_category/insert_products_category.json @@ -0,0 +1,31 @@ +[{ + "title": "product-1", + "image_url": "https://images.product1.png", + "price": 42.42, + "description": "a description for product-1" +}, { + "title": "product-2", + "image_url": "https://images.product2.png", + "price": 32.1, + "description": "a description for product-2" +}, { + "title": "product-3", + "image_url": "https://images.product3.png", + "price": 52321321.32, + "description": "a description for product-3" +}, { + "title": "product-4", + "image_url": "https://images.product4.png", + "price": 77.4221, + "description": "a description for product-4" +}, { + "title": "product-5", + "image_url": "https://images.product5.png", + "price": 55.1, + "description": "a description for product-5" +}, { + "title": "product-6", + "image_url": "https://images.product6.png", + "price": 53.32, + "description": "a description for product-6" +}] \ No newline at end of file diff --git a/database/mysql/migration/api_category/update_category.json b/database/mysql/migration/api_category/update_category.json new file mode 100644 index 00000000..a3ea1397 --- /dev/null +++ b/database/mysql/migration/api_category/update_category.json @@ -0,0 +1,6 @@ +{ + "id": 2, + "position": 1, + "title": "computers", + "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Desktop_computer_clipart_-_Yellow_theme.svg/1200px-Desktop_computer_clipart_-_Yellow_theme.svg.png" +} \ No newline at end of file diff --git a/database/mysql/migration/api_category/update_partial_category.json b/database/mysql/migration/api_category/update_partial_category.json new file mode 100644 index 00000000..730c7166 --- /dev/null +++ b/database/mysql/migration/api_category/update_partial_category.json @@ -0,0 +1,3 @@ +{ + "title": "computers-technology" +} \ No newline at end of file diff --git a/database/mysql/migration/api_postman.json b/database/mysql/migration/api_postman.json new file mode 100644 index 00000000..dfdd84d1 --- /dev/null +++ b/database/mysql/migration/api_postman.json @@ -0,0 +1,567 @@ +{ + "info": { + "_postman_id": "7b8b53f8-859a-425a-aa9c-28bc2a2d5ef7", + "name": "myapp (api-test)", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Category", + "item": [ + { + "name": "Create", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"computer-internet\",\r\n \"position\": 1,\r\n \"image_url\": \"https://bp.pstatic.gr/public/dist/images/1mOPxYtw1k.webp\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/category", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category" + ] + }, + "description": "Create a Category" + }, + "response": [] + }, + { + "name": "Get By ID", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/category/1", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category", + "1" + ] + }, + "description": "Get By ID" + }, + "response": [] + }, + { + "name": "List", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8080/category?offset=0&limit=30&order=asc", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category" + ], + "query": [ + { + "key": "offset", + "value": "0" + }, + { + "key": "limit", + "value": "30" + }, + { + "key": "order", + "value": "asc" + } + ] + }, + "description": "Get many with limit offset" + }, + "response": [] + }, + { + "name": "Update (Full)", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n\t\"id\": 1,\r\n\t\"position\": 3,\r\n \"title\": \"computers\",\r\n \"image_url\":\"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Desktop_computer_clipart_-_Yellow_theme.svg/1200px-Desktop_computer_clipart_-_Yellow_theme.svg.png\"\r\n}" + }, + "url": { + "raw": "http://localhost:8080/category", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category" + ], + "query": [ + { + "key": "", + "value": null, + "disabled": true + } + ] + }, + "description": "Update a Category (full update)" + }, + "response": [] + }, + { + "name": "Delete By ID", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/category/1", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category", + "1" + ] + }, + "description": "Delete a Category" + }, + "response": [] + }, + { + "name": "Update (Partial)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"computers-technology\"\r\n}" + }, + "url": { + "raw": "http://localhost:8080/category/3", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category", + "3" + ] + }, + "description": "Update a Category partially, e.g. title only" + }, + "response": [] + }, + { + "name": "List Products", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/category/1/products?offset=0&limit=30&by=price&order=asc", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category", + "1", + "products" + ], + "query": [ + { + "key": "offset", + "value": "0" + }, + { + "key": "limit", + "value": "30" + }, + { + "key": "by", + "value": "price" + }, + { + "key": "order", + "value": "asc" + } + ] + }, + "description": "Get products from cheap to expensive" + }, + "response": [] + }, + { + "name": "Insert Products", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "[{\r\n \"title\": \"product-1\",\r\n \"image_url\": \"https://images.product1.png\",\r\n \"price\": 42.42,\r\n \"description\": \"a description for product-1\"\r\n}, {\r\n \"title\": \"product-2\",\r\n \"image_url\": \"https://images.product2.png\",\r\n \"price\": 32.1,\r\n \"description\": \"a description for product-2\"\r\n}, {\r\n \"title\": \"product-3\",\r\n \"image_url\": \"https://images.product3.png\",\r\n \"price\": 52321321.32,\r\n \"description\": \"a description for product-3\"\r\n}, {\r\n \"title\": \"product-4\",\r\n \"image_url\": \"https://images.product4.png\",\r\n \"price\": 77.4221,\r\n \"description\": \"a description for product-4\"\r\n}, {\r\n \"title\": \"product-5\",\r\n \"image_url\": \"https://images.product5.png\",\r\n \"price\": 55.1,\r\n \"description\": \"a description for product-5\"\r\n}, {\r\n \"title\": \"product-6\",\r\n \"image_url\": \"https://images.product6.png\",\r\n \"price\": 53.32,\r\n \"description\": \"a description for product-6\"\r\n}]" + }, + "url": { + "raw": "http://localhost:8080/category/3/products", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "category", + "3", + "products" + ] + }, + "description": "Batch Insert Products to a Category" + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + }, + { + "name": "Product", + "item": [ + { + "name": "List", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/product?offset=0&limit=30&by=price&order=asc", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product" + ], + "query": [ + { + "key": "offset", + "value": "0" + }, + { + "key": "limit", + "value": "30" + }, + { + "key": "by", + "value": "price" + }, + { + "key": "order", + "value": "asc" + } + ] + }, + "description": "List products" + }, + "response": [] + }, + { + "name": "Get By ID", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/product/1", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product", + "1" + ] + }, + "description": "Get a Product" + }, + "response": [] + }, + { + "name": "Delete By ID", + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "http://localhost:8080/product/3", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product", + "3" + ] + }, + "description": "Delete a Product" + }, + "response": [] + }, + { + "name": "Create", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"product-1\",\r\n \"category_id\": 1,\r\n \"image_url\": \"https://images.product1.png\",\r\n \"price\": 42.42,\r\n \"description\": \"a description for product-1\"\r\n}" + }, + "url": { + "raw": "http://localhost:8080/product", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product" + ] + }, + "description": "Create a Product (and assign a category)" + }, + "response": [] + }, + { + "name": "Update (Full)", + "request": { + "method": "PUT", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n\t\"id\":19,\r\n \"title\": \"product-9-new\",\r\n \"category_id\": 1,\r\n \"image_url\": \"https://images.product19.png\",\r\n \"price\": 20,\r\n \"description\": \"a description for product-9-new\"\r\n}" + }, + "url": { + "raw": "http://localhost:8080/product", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product" + ] + }, + "description": "Update a Product (full-update)" + }, + "response": [] + }, + { + "name": "Update (Partial)", + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1ODU1NjN9.PtfDS1niGoZ7pV6kplI-_q1fVKLnknQ3IwcrLZhoVCU", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"title\": \"product-9-new-title\"\r\n}" + }, + "url": { + "raw": "http://localhost:8080/product/9", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "product", + "9" + ] + }, + "description": "Update a Product (partially)" + }, + "response": [] + } + ], + "description": "Product Client API", + "protocolProfileBehavior": {} + }, + { + "name": "Get Token", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/token", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "token" + ] + }, + "description": "Get Token to access \"write\" (create, update and delete) endpoints" + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2lyaXMtZ28uY29tIiwiYXVkIjpbIjljOTY5ZDg5LTBkZGYtNDlkMC1hYzcxLTI3MmU3YmY5NjkwMCJdLCJpYXQiOjE2MDYyNzE1NDYsImV4cCI6MTYwNjI3MjQ0Nn0.l2_5iqfEaC68UySTQNoDx2sfzn031tHiTdm2kZoNkWQ", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "id": "f27c3c2d-efdc-4922-b70c-258784a1d59b", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "44d94797-9cc6-4ecd-adc5-7ad5329d79c4", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "id": "38156b9f-e623-4974-a315-51c931670f23", + "key": "token", + "value": "token" + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/database/mysql/migration/api_product/create_product.json b/database/mysql/migration/api_product/create_product.json new file mode 100644 index 00000000..46b6a5c8 --- /dev/null +++ b/database/mysql/migration/api_product/create_product.json @@ -0,0 +1,7 @@ +{ + "title": "product-1", + "category_id": 3, + "image_url": "https://images.product1.png", + "price": 42.42, + "description": "a description for product-1" +} \ No newline at end of file diff --git a/database/mysql/migration/api_product/update_partial_product.json b/database/mysql/migration/api_product/update_partial_product.json new file mode 100644 index 00000000..71413c13 --- /dev/null +++ b/database/mysql/migration/api_product/update_partial_product.json @@ -0,0 +1,3 @@ +{ + "title": "product-19-new-title" +} \ No newline at end of file diff --git a/database/mysql/migration/api_product/update_product.json b/database/mysql/migration/api_product/update_product.json new file mode 100644 index 00000000..d8e52662 --- /dev/null +++ b/database/mysql/migration/api_product/update_product.json @@ -0,0 +1,8 @@ +{ + "id":19, + "title": "product-19", + "category_id": 3, + "image_url": "https://images.product19.png", + "price": 20, + "description": "a description for product-19" +} \ No newline at end of file diff --git a/database/mysql/migration/db.sql b/database/mysql/migration/db.sql new file mode 100644 index 00000000..eab35314 --- /dev/null +++ b/database/mysql/migration/db.sql @@ -0,0 +1,33 @@ +CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE myapp; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS categories; +CREATE TABLE categories ( + id int(11) NOT NULL AUTO_INCREMENT, + title varchar(255) NOT NULL, + position int(11) NOT NULL, + image_url varchar(255) NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); + +DROP TABLE IF EXISTS products; +CREATE TABLE products ( + id int(11) NOT NULL AUTO_INCREMENT, + category_id int, + title varchar(255) NOT NULL, + image_url varchar(255) NOT NULL, + price decimal(10,2) NOT NULL, + description text NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + FOREIGN KEY (category_id) REFERENCES categories(id) +); + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/database/mysql/service/category_service.go b/database/mysql/service/category_service.go new file mode 100644 index 00000000..2a151d83 --- /dev/null +++ b/database/mysql/service/category_service.go @@ -0,0 +1,74 @@ +package service + +import ( + "context" + "fmt" + "reflect" + + "myapp/entity" + "myapp/sql" +) + +// CategoryService represents the category entity service. +// Note that the given entity (request) should be already validated +// before service's calls. +type CategoryService struct { + *sql.Service +} + +// NewCategoryService returns a new category service to communicate with the database. +func NewCategoryService(db sql.Database) *CategoryService { + return &CategoryService{Service: sql.NewService(db, new(entity.Category))} +} + +// Insert stores a category to the database and returns its ID. +func (s *CategoryService) Insert(ctx context.Context, e entity.Category) (int64, error) { + if e.Title == "" || e.ImageURL == "" { + return 0, sql.ErrUnprocessable + } + + q := fmt.Sprintf(`INSERT INTO %s (title, position, image_url) + VALUES (?,?,?);`, e.TableName()) + + res, err := s.DB().Exec(ctx, q, e.Title, e.Position, e.ImageURL) + if err != nil { + return 0, err + } + + return res.LastInsertId() +} + +// Update updates a category based on its `ID`. +func (s *CategoryService) Update(ctx context.Context, e entity.Category) (int, error) { + if e.ID == 0 || e.Title == "" || e.ImageURL == "" { + return 0, sql.ErrUnprocessable + } + + q := fmt.Sprintf(`UPDATE %s + SET + title = ?, + position = ?, + image_url = ? + WHERE %s = ?;`, e.TableName(), e.PrimaryKey()) + + res, err := s.DB().Exec(ctx, q, e.Title, e.Position, e.ImageURL, e.ID) + if err != nil { + return 0, err + } + + n := sql.GetAffectedRows(res) + return n, nil +} + +// The updatable fields, separately from that we create for any possible future necessities. +var categoryUpdateSchema = map[string]reflect.Kind{ + "title": reflect.String, + "image_url": reflect.String, + "position": reflect.Int, +} + +// PartialUpdate accepts a key-value map to +// update the record based on the given "id". +func (s *CategoryService) PartialUpdate(ctx context.Context, id int64, attrs map[string]interface{}) (int, error) { + return s.Service.PartialUpdate(ctx, id, categoryUpdateSchema, attrs) +} diff --git a/database/mysql/service/category_service_test.go b/database/mysql/service/category_service_test.go new file mode 100644 index 00000000..24c6ef86 --- /dev/null +++ b/database/mysql/service/category_service_test.go @@ -0,0 +1,42 @@ +package service + +import ( + "context" + "testing" + + "myapp/entity" + "myapp/sql" + + "github.com/DATA-DOG/go-sqlmock" +) + +func TestCategoryServiceInsert(t *testing.T) { + conn, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual)) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + db := &sql.MySQL{Conn: conn} + service := NewCategoryService(db) + newCategory := entity.Category{ + Title: "computer-internet", + Position: 2, + ImageURL: "https://animage", + } + mock.ExpectExec("INSERT INTO categories (title, position, image_url) VALUES (?,?,?);"). + WithArgs(newCategory.Title, newCategory.Position, newCategory.ImageURL).WillReturnResult(sqlmock.NewResult(1, 1)) + + id, err := service.Insert(context.TODO(), newCategory) + if err != nil { + t.Fatal(err) + } + + if id != 1 { + t.Fatalf("expected ID to be 1 as this is the first entry") + } + + if err = mock.ExpectationsWereMet(); err != nil { + t.Fatal(err) + } +} diff --git a/database/mysql/service/product_service.go b/database/mysql/service/product_service.go new file mode 100644 index 00000000..15d7bfdc --- /dev/null +++ b/database/mysql/service/product_service.go @@ -0,0 +1,110 @@ +package service + +import ( + "context" + "fmt" + "reflect" + "strings" + + "myapp/entity" + "myapp/sql" +) + +// ProductService represents the product entity service. +// Note that the given entity (request) should be already validated +// before service's calls. +type ProductService struct { + *sql.Service + rec sql.Record +} + +// NewProductService returns a new product service to communicate with the database. +func NewProductService(db sql.Database) *ProductService { + return &ProductService{Service: sql.NewService(db, new(entity.Product))} +} + +// Insert stores a product to the database and returns its ID. +func (s *ProductService) Insert(ctx context.Context, e entity.Product) (int64, error) { + if !e.ValidateInsert() { + return 0, sql.ErrUnprocessable + } + + q := fmt.Sprintf(`INSERT INTO %s (category_id, title, image_url, price, description) + VALUES (?,?,?,?,?);`, e.TableName()) + + res, err := s.DB().Exec(ctx, q, e.CategoryID, e.Title, e.ImageURL, e.Price, e.Description) + if err != nil { + return 0, err + } + + return res.LastInsertId() +} + +// BatchInsert inserts one or more products at once and returns the total length created. +func (s *ProductService) BatchInsert(ctx context.Context, products []entity.Product) (int, error) { + if len(products) == 0 { + return 0, nil + } + + var ( + valuesLines []string + args []interface{} + ) + + for _, p := range products { + if !p.ValidateInsert() { + // all products should be "valid", we don't skip, we cancel. + return 0, sql.ErrUnprocessable + } + + valuesLines = append(valuesLines, "(?,?,?,?,?)") + args = append(args, []interface{}{p.CategoryID, p.Title, p.ImageURL, p.Price, p.Description}...) + } + + q := fmt.Sprintf("INSERT INTO %s (category_id, title, image_url, price, description) VALUES %s;", + s.RecordInfo().TableName(), + strings.Join(valuesLines, ", ")) + + res, err := s.DB().Exec(ctx, q, args...) + if err != nil { + return 0, err + } + + n := sql.GetAffectedRows(res) + return n, nil +} + +// Update updates a product based on its `ID` from the database +// and returns the affected numbrer (0 when nothing changed otherwise 1). +func (s *ProductService) Update(ctx context.Context, e entity.Product) (int, error) { + q := fmt.Sprintf(`UPDATE %s + SET + category_id = ?, + title = ?, + image_url = ?, + price = ?, + description = ? + WHERE %s = ?;`, e.TableName(), e.PrimaryKey()) + + res, err := s.DB().Exec(ctx, q, e.CategoryID, e.Title, e.ImageURL, e.Price, e.Description, e.ID) + if err != nil { + return 0, err + } + + n := sql.GetAffectedRows(res) + return n, nil +} + +var productUpdateSchema = map[string]reflect.Kind{ + "category_id": reflect.Int, + "title": reflect.String, + "image_url": reflect.String, + "price": reflect.Float32, + "description": reflect.String, +} + +// PartialUpdate accepts a key-value map to +// update the record based on the given "id". +func (s *ProductService) PartialUpdate(ctx context.Context, id int64, attrs map[string]interface{}) (int, error) { + return s.Service.PartialUpdate(ctx, id, productUpdateSchema, attrs) +} diff --git a/database/mysql/sql/mysql.go b/database/mysql/sql/mysql.go new file mode 100644 index 00000000..9d93b5cd --- /dev/null +++ b/database/mysql/sql/mysql.go @@ -0,0 +1,123 @@ +package sql + +import ( + "context" + "database/sql" + "fmt" + + _ "github.com/go-sql-driver/mysql" // lint: mysql driver. +) + +// MySQL holds the underline connection of a MySQL (or MariaDB) database. +// See the `ConnectMySQL` package-level function. +type MySQL struct { + Conn *sql.DB +} + +var _ Database = (*MySQL)(nil) + +var ( + // DefaultCharset default charset parameter for new databases. + DefaultCharset = "utf8mb4" + // DefaultCollation default collation parameter for new databases. + DefaultCollation = "utf8mb4_unicode_ci" +) + +// ConnectMySQL returns a new ready to use MySQL Database instance. +// Accepts a single argument of "dsn", i.e: +// username:password@tcp(localhost:3306)/myapp?parseTime=true&charset=utf8mb4&collation=utf8mb4_unicode_ci +func ConnectMySQL(dsn string) (*MySQL, error) { + conn, err := sql.Open("mysql", dsn) + if err != nil { + return nil, err + } + err = conn.Ping() + if err != nil { + conn.Close() + return nil, err + } + + return &MySQL{ + Conn: conn, + }, nil +} + +// CreateDatabase executes the CREATE DATABASE query. +func (db *MySQL) CreateDatabase(database string) error { + q := fmt.Sprintf("CREATE DATABASE %s DEFAULT CHARSET = %s COLLATE = %s;", database, DefaultCharset, DefaultCollation) + _, err := db.Conn.Exec(q) + return err +} + +// Drop executes the DROP DATABASE query. +func (db *MySQL) Drop(database string) error { + q := fmt.Sprintf("DROP DATABASE %s;", database) + _, err := db.Conn.Exec(q) + return err +} + +// Select performs the SELECT query for this database (dsn database name is required). +func (db *MySQL) Select(ctx context.Context, dest interface{}, query string, args ...interface{}) error { + rows, err := db.Conn.QueryContext(ctx, query, args...) + if err != nil { + return err + } + defer rows.Close() + + if scannable, ok := dest.(Scannable); ok { + return scannable.Scan(rows) + } + + if !rows.Next() { + return ErrNoRows + } + return rows.Scan(dest) + + /* Uncomment this and pass a slice if u want to see reflection powers <3 + v, ok := dest.(reflect.Value) + if !ok { + v = reflect.Indirect(reflect.ValueOf(dest)) + } + + sliceTyp := v.Type() + + if sliceTyp.Kind() != reflect.Slice { + sliceTyp = reflect.SliceOf(sliceTyp) + } + + sliceElementTyp := deref(sliceTyp.Elem()) + for rows.Next() { + obj := reflect.New(sliceElementTyp) + obj.Interface().(Scannable).Scan(rows) + if err != nil { + return err + } + + v.Set(reflect.Append(v, reflect.Indirect(obj))) + } + */ +} + +// Get same as `Select` but it moves the cursor to the first result. +func (db *MySQL) Get(ctx context.Context, dest interface{}, query string, args ...interface{}) error { + rows, err := db.Conn.QueryContext(ctx, query, args...) + if err != nil { + return err + } + defer rows.Close() + if !rows.Next() { + return ErrNoRows + } + + if scannable, ok := dest.(Scannable); ok { + return scannable.Scan(rows) + } + + return rows.Scan(dest) +} + +// Exec executes a query. It does not return any rows. +// Use the first output parameter to count the affected rows on UPDATE, INSERT, or DELETE. +func (db *MySQL) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { + return db.Conn.ExecContext(ctx, query, args...) +} diff --git a/database/mysql/sql/service.go b/database/mysql/sql/service.go new file mode 100644 index 00000000..17ba3780 --- /dev/null +++ b/database/mysql/sql/service.go @@ -0,0 +1,241 @@ +package sql + +import ( + "context" + "database/sql" + "errors" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" +) + +// Service holder for common queries. +// Note: each entity service keeps its own base Service instance. +type Service struct { + db Database + rec Record // see `Count`, `List` and `DeleteByID` methods. +} + +// NewService returns a new (SQL) base service for common operations. +func NewService(db Database, of Record) *Service { + return &Service{db: db, rec: of} +} + +// DB exposes the database instance. +func (s *Service) DB() Database { + return s.db +} + +// RecordInfo returns the record info provided through `NewService`. +func (s *Service) RecordInfo() Record { + return s.rec +} + +// ErrNoRows is returned when GET doesn't return a row. +// A shortcut of sql.ErrNoRows. +var ErrNoRows = sql.ErrNoRows + +// GetByID binds a single record from the databases to the "dest". +func (s *Service) GetByID(ctx context.Context, dest interface{}, id int64) error { + q := fmt.Sprintf("SELECT * FROM %s WHERE %s = ? LIMIT 1", s.rec.TableName(), s.rec.PrimaryKey()) + err := s.db.Get(ctx, dest, q, id) + return err + // if err != nil { + // if err == sql.ErrNoRows { + // return false, nil + // } + + // return false, err + // } + + // return true, nil +} + +// Count returns the total records count in the table. +func (s *Service) Count(ctx context.Context) (total int64, err error) { + q := fmt.Sprintf("SELECT COUNT(DISTINCT %s) FROM %s", s.rec.PrimaryKey(), s.rec.TableName()) + if err = s.db.Select(ctx, &total, q); err == sql.ErrNoRows { + err = nil + } + return +} + +// ListOptions holds the options to be passed on the `Service.List` method. +type ListOptions struct { + Table string // the table name. + Offset uint64 // inclusive. + Limit uint64 + OrderByColumn string + Order string // "ASC" or "DESC" (could be a bool type instead). + WhereColumn string + WhereValue interface{} +} + +// Where accepts a column name and column value to set +// on the WHERE clause of the result query. +// It returns a new `ListOptions` value. +// Note that this is a basic implementation which just takes care our current needs. +func (opt ListOptions) Where(colName string, colValue interface{}) ListOptions { + opt.WhereColumn = colName + opt.WhereValue = colValue + return opt +} + +// BuildQuery returns the query and the arguments that +// should be form a SELECT command. +func (opt ListOptions) BuildQuery() (q string, args []interface{}) { + q = fmt.Sprintf("SELECT * FROM %s", opt.Table) + + if opt.WhereColumn != "" && opt.WhereValue != nil { + q += fmt.Sprintf(" WHERE %s = ?", opt.WhereColumn) + args = append(args, opt.WhereValue) + } + + if opt.OrderByColumn != "" { + q += fmt.Sprintf(" ORDER BY %s %s", opt.OrderByColumn, ParseOrder(opt.Order)) + } + + if opt.Limit > 0 { + q += fmt.Sprintf(" LIMIT %d", opt.Limit) // offset below. + } + + if opt.Offset > 0 { + q += fmt.Sprintf(" OFFSET %d", opt.Offset) + } + + return +} + +// const defaultLimit = 30 // default limit if not set. + +// ParseListOptions returns a `ListOptions` from a map[string][]string. +func ParseListOptions(q url.Values) ListOptions { + offset, _ := strconv.ParseUint(q.Get("offset"), 10, 64) + limit, _ := strconv.ParseUint(q.Get("limit"), 10, 64) + order := q.Get("order") // empty, asc(...) or desc(...). + + return ListOptions{Offset: offset, Limit: limit, Order: order} +} + +// List binds one or more records from the database to the "dest". +// If the record supports ordering then it will sort by the `Sorted.OrderBy` column name(s). +// Use the "order" input parameter to set a descending order ("DESC"). +func (s *Service) List(ctx context.Context, dest interface{}, opts ListOptions) error { + // Set table and order by column from record info for `List` by options + // so it can be more flexible to perform read-only calls of other table's too. + if opts.Table == "" { + // If missing then try to set it by record info. + opts.Table = s.rec.TableName() + } + + if b, ok := s.rec.(Sorted); ok { + opts.OrderByColumn = b.SortBy() + } + + q, args := opts.BuildQuery() + return s.db.Select(ctx, dest, q, args...) +} + +// DeleteByID removes a single record of "dest" from the database. +func (s *Service) DeleteByID(ctx context.Context, id int64) (int, error) { + q := fmt.Sprintf("DELETE FROM %s WHERE %s = ? LIMIT 1", s.rec.TableName(), s.rec.PrimaryKey()) + res, err := s.db.Exec(ctx, q, id) + if err != nil { + return 0, err + } + + return GetAffectedRows(res), nil +} + +// ErrUnprocessable indicates error caused by invalid entity (entity's key-values). +// The syntax of the request entity is correct, but it was unable to process the contained instructions +// e.g. empty or unsupported value. +// +// See `../service/XService.Insert` and `../service/XService.Update` +// and `PartialUpdate`. +var ErrUnprocessable = errors.New("invalid entity") + +// PartialUpdate accepts a columns schema and a key-value map to +// update the record based on the given "id". +// Note: Trivial string, int and boolean type validations are performed here. +func (s *Service) PartialUpdate(ctx context.Context, id int64, schema map[string]reflect.Kind, attrs map[string]interface{}) (int, error) { + if len(schema) == 0 || len(attrs) == 0 { + return 0, nil + } + + var ( + keyLines []string + values []interface{} + ) + + for key, kind := range schema { + v, ok := attrs[key] + if !ok { + continue + } + + switch v.(type) { + case string: + if kind != reflect.String { + return 0, ErrUnprocessable + } + case int: + if kind != reflect.Int { + return 0, ErrUnprocessable + } + case bool: + if kind != reflect.Bool { + return 0, ErrUnprocessable + } + } + + keyLines = append(keyLines, fmt.Sprintf("%s = ?", key)) + values = append(values, v) + } + + if len(values) == 0 { + return 0, nil + } + + q := fmt.Sprintf("UPDATE %s SET %s WHERE %s = ?;", + s.rec.TableName(), strings.Join(keyLines, ", "), s.rec.PrimaryKey()) + + res, err := s.DB().Exec(ctx, q, append(values, id)...) + if err != nil { + return 0, err + } + + n := GetAffectedRows(res) + return n, nil +} + +// GetAffectedRows returns the number of affected rows after +// a DELETE or UPDATE operation. +func GetAffectedRows(result sql.Result) int { + if result == nil { + return 0 + } + + n, _ := result.RowsAffected() + return int(n) +} + +const ( + ascending = "ASC" + descending = "DESC" +) + +// ParseOrder accept an order string and returns a valid mysql ORDER clause. +// Defaults to "ASC". Two possible outputs: "ASC" and "DESC". +func ParseOrder(order string) string { + order = strings.TrimSpace(order) + if len(order) >= 4 { + if strings.HasPrefix(strings.ToUpper(order), descending) { + return descending + } + } + + return ascending +} diff --git a/database/mysql/sql/sql.go b/database/mysql/sql/sql.go new file mode 100644 index 00000000..4ac6ec9c --- /dev/null +++ b/database/mysql/sql/sql.go @@ -0,0 +1,40 @@ +package sql + +import ( + "context" + "database/sql" +) + +// Database is an interface which a database(sql) should implement. +type Database interface { + Get(ctx context.Context, dest interface{}, q string, args ...interface{}) error + Select(ctx context.Context, dest interface{}, q string, args ...interface{}) error + Exec(ctx context.Context, q string, args ...interface{}) (sql.Result, error) +} + +// Record should represent a database record. +// It holds the table name and the primary key. +// Entities should implement that +// in order to use the BaseService's methods. +type Record interface { + TableName() string // the table name which record belongs to. + PrimaryKey() string // the primary key of the record. +} + +// Sorted should represent a set of database records +// that should be rendered with order. +// +// It does NOT support the form of +// column1 ASC, +// column2 DESC +// The OrderBy method should return text in form of: +// column1 +// or column1, column2 +type Sorted interface { + SortBy() string // column names separated by comma. +} + +// Scannable for go structs to bind their fields. +type Scannable interface { + Scan(*sql.Rows) error +} diff --git a/database/orm/gorm/REAMDE.md b/database/orm/gorm/REAMDE.md new file mode 100644 index 00000000..7e684d63 --- /dev/null +++ b/database/orm/gorm/REAMDE.md @@ -0,0 +1,5 @@ +# GORM + +This example is pull by [#1275 PR](https://github.com/kataras/iris/pull/1275) by [@wuxiaoxiaoshen](https://github.com/wuxiaoxiaoshen). + +A more complete and real-world example can be found at the <https://github.com/snowlyg/IrisApiProject> project created by [@snowlyg](https://github.com/snowlyg). diff --git a/database/orm/gorm/main.go b/database/orm/gorm/main.go new file mode 100644 index 00000000..00a10b3c --- /dev/null +++ b/database/orm/gorm/main.go @@ -0,0 +1,177 @@ +package main + +import ( + "net/http" + "os" + "time" + + "github.com/jinzhu/gorm" + "github.com/kataras/iris/v12" + _ "github.com/mattn/go-sqlite3" +) + +type User struct { + gorm.Model + Salt string `gorm:"type:varchar(255)" json:"salt"` + Username string `gorm:"type:varchar(32)" json:"username"` + Password string `gorm:"type:varchar(200);column:password" json:"-"` + Languages string `gorm:"type:varchar(200);column:languages" json:"languages"` +} + +func (u User) TableName() string { + return "gorm_user" +} + +type UserSerializer struct { + ID uint `json:"id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Salt string `json:"salt"` + UserName string `json:"user_name"` + Password string `json:"-"` + Languages string `json:"languages"` +} + +func (self User) Serializer() UserSerializer { + return UserSerializer{ + ID: self.ID, + CreatedAt: self.CreatedAt.Truncate(time.Second), + UpdatedAt: self.UpdatedAt.Truncate(time.Second), + Salt: self.Salt, + Password: self.Password, + Languages: self.Languages, + UserName: self.Username, + } +} + +func main() { + app := iris.Default() + db, err := gorm.Open("sqlite3", "test.db") + db.LogMode(true) // show SQL logger + if err != nil { + app.Logger().Fatalf("connect to sqlite3 failed") + return + } + iris.RegisterOnInterrupt(func() { + defer db.Close() + }) + + if os.Getenv("ENV") != "" { + db.DropTableIfExists(&User{}) // drop table + } + db.AutoMigrate(&User{}) // create table: // AutoMigrate run auto migration for given models, will only add missing fields, won't delete/change current data + + app.Post("/post_user", func(ctx iris.Context) { + var user User + user = User{ + Username: "gorm", + Salt: "hash---", + Password: "admin", + Languages: "gorm", + } + if err := db.FirstOrCreate(&user); err == nil { + app.Logger().Fatalf("created one record failed: %s", err.Error) + ctx.JSON(iris.Map{ + "code": http.StatusBadRequest, + "error": err.Error, + }) + return + } + ctx.JSON( + iris.Map{ + "code": http.StatusOK, + "data": user.Serializer(), + }) + }) + + app.Get("/get_user/{id:uint}", func(ctx iris.Context) { + var user User + id, _ := ctx.Params().GetUint("id") + app.Logger().Println(id) + if err := db.Where("id = ?", int(id)).First(&user).Error; err != nil { + app.Logger().Fatalf("find one record failed: %t", err == nil) + ctx.JSON(iris.Map{ + "code": http.StatusBadRequest, + "error": err.Error, + }) + return + } + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "data": user.Serializer(), + }) + }) + + app.Delete("/delete_user/{id:uint}", func(ctx iris.Context) { + id, _ := ctx.Params().GetUint("id") + if id == 0 { + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "detail": "query param id should not be nil", + }) + return + } + var user User + if err := db.Where("id = ?", id).First(&user).Error; err != nil { + app.Logger().Fatalf("record not found") + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "detail": err.Error, + }) + return + } + db.Delete(&user) + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "data": user.Serializer(), + }) + }) + + app.Patch("/patch_user/{id:uint}", func(ctx iris.Context) { + id, _ := ctx.Params().GetUint("id") + if id == 0 { + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "detail": "query param id should not be nil", + }) + return + } + var user User + tx := db.Begin() + if err := tx.Where("id = ?", id).First(&user).Error; err != nil { + app.Logger().Fatalf("record not found") + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "detail": err.Error, + }) + return + } + + var body patchParam + ctx.ReadJSON(&body) + app.Logger().Println(body) + if err := tx.Model(&user).Updates(map[string]interface{}{"username": body.Data.UserName, "password": body.Data.Password}).Error; err != nil { + app.Logger().Fatalf("update record failed") + tx.Rollback() + ctx.JSON(iris.Map{ + "code": http.StatusBadRequest, + "error": err.Error, + }) + return + } + tx.Commit() + ctx.JSON(iris.Map{ + "code": http.StatusOK, + "data": user.Serializer(), + }) + }) + + app.Listen(":8080") +} + +type patchParam struct { + Data struct { + UserName string `json:"user_name" form:"user_name"` + Password string `json:"password" form:"password"` + } `json:"data"` +} diff --git a/database/orm/reform/controllers/person_controller.go b/database/orm/reform/controllers/person_controller.go new file mode 100644 index 00000000..97f9dbb6 --- /dev/null +++ b/database/orm/reform/controllers/person_controller.go @@ -0,0 +1,47 @@ +package controllers + +import ( + "net" + "time" + + "myapp/models" + + "github.com/kataras/golog" + "gopkg.in/reform.v1" +) + +// PersonController is the model.Person's web controller. +type PersonController struct { + DB *reform.DB + + // Logger and IP fields are automatically binded by the framework. + Logger *golog.Logger // binds to the application's logger. + IP net.IP // binds to the client's IP. +} + +// Get handles +// GET /persons +func (c *PersonController) Get() ([]reform.Struct, error) { + return c.DB.SelectAllFrom(models.PersonTable, "") +} + +// GetBy handles +// GET /persons/{ID} +func (c *PersonController) GetBy(id int32) (reform.Record, error) { + return c.DB.FindByPrimaryKeyFrom(models.PersonTable, id) +} + +// Post handles +// POST /persons with JSON request body of model.Person. +func (c *PersonController) Post(p *models.Person) int { + p.CreatedAt = time.Now() + + if err := c.DB.Save(p); err != nil { + c.Logger.Errorf("[%s] create person: %v", c.IP.String(), err) + return 500 // iris.StatusInternalServerError + } + + c.Logger.Debugf("[%s] create person [%s] succeed", c.IP.String(), p.Name) + + return 201 // iris.StatusCreated +} diff --git a/database/orm/reform/go.mod b/database/orm/reform/go.mod new file mode 100644 index 00000000..07c66317 --- /dev/null +++ b/database/orm/reform/go.mod @@ -0,0 +1,66 @@ +module myapp + +go 1.22 + +require ( + github.com/kataras/golog v0.1.11 + github.com/kataras/iris/v12 v12.2.11 + github.com/mattn/go-sqlite3 v1.14.22 + gopkg.in/reform.v1 v1.5.1 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/database/orm/reform/go.sum b/database/orm/reform/go.sum new file mode 100644 index 00000000..ef249929 --- /dev/null +++ b/database/orm/reform/go.sum @@ -0,0 +1,234 @@ +github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= +github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/brianvoe/gofakeit v3.18.0+incompatible h1:wDOmHc9DLG4nRjUVVaxA+CEglKOW72Y5+4WNxUIkjM8= +github.com/brianvoe/gofakeit v3.18.0+incompatible/go.mod h1:kfwdRA90vvNhPutZWfH7WPaDzUjz+CZFqG+rPkOjGOc= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= +github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/reform.v1 v1.5.1 h1:7vhDFW1n1xAPC6oDSvIvVvpRkaRpXlxgJ4QB4s3aDdo= +gopkg.in/reform.v1 v1.5.1/go.mod h1:AIv0CbDRJ0ljQwptGeaIXfpDRo02uJwTq92aMFELEeU= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/database/orm/reform/main.go b/database/orm/reform/main.go new file mode 100644 index 00000000..9be385b4 --- /dev/null +++ b/database/orm/reform/main.go @@ -0,0 +1,50 @@ +package main + +/* +$ go get gopkg.in/reform.v1/reform +$ go generate ./models +$ go run . + +Read more at: https://github.com/go-reform/reform +*/ + +import ( + "database/sql" + + "myapp/controllers" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + + _ "github.com/mattn/go-sqlite3" + "gopkg.in/reform.v1" + "gopkg.in/reform.v1/dialects/sqlite3" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + sqlDB, err := sql.Open("sqlite3", "./myapp.db") + if err != nil { + panic(err) + } + defer sqlDB.Close() + sqlStmt := ` + drop table people; + create table people (id integer not null primary key, name text, email text, created_at datetime not null, updated_at datetime null); + delete from people; + ` + _, err = sqlDB.Exec(sqlStmt) + if err != nil { + panic(err) + } + + db := reform.NewDB(sqlDB, sqlite3.Dialect, reform.NewPrintfLogger(app.Logger().Debugf)) + + mvcApp := mvc.New(app.Party("/persons")) + mvcApp.Register(db) + mvcApp.Handle(new(controllers.PersonController)) + + app.Listen(":8080") +} diff --git a/database/orm/reform/models/person.go b/database/orm/reform/models/person.go new file mode 100644 index 00000000..6b852748 --- /dev/null +++ b/database/orm/reform/models/person.go @@ -0,0 +1,13 @@ +//go:generate reform +package models + +import "time" + +//reform:people +type Person struct { + ID int32 `reform:"id,pk" json:"id"` + Name string `reform:"name" json:"name"` + Email *string `reform:"email" json:"email"` + CreatedAt time.Time `reform:"created_at" json:"created_at"` + UpdatedAt *time.Time `reform:"updated_at" json:"updated_at"` +} diff --git a/database/orm/reform/models/person_reform.go b/database/orm/reform/models/person_reform.go new file mode 100644 index 00000000..537d2b5d --- /dev/null +++ b/database/orm/reform/models/person_reform.go @@ -0,0 +1,136 @@ +// Code generated by gopkg.in/reform.v1. DO NOT EDIT. + +package models + +import ( + "fmt" + "strings" + + "gopkg.in/reform.v1" + "gopkg.in/reform.v1/parse" +) + +type personTableType struct { + s parse.StructInfo + z []interface{} +} + +// Schema returns a schema name in SQL database (""). +func (v *personTableType) Schema() string { + return v.s.SQLSchema +} + +// Name returns a view or table name in SQL database ("people"). +func (v *personTableType) Name() string { + return v.s.SQLName +} + +// Columns returns a new slice of column names for that view or table in SQL database. +func (v *personTableType) Columns() []string { + return []string{"id", "name", "email", "created_at", "updated_at"} +} + +// NewStruct makes a new struct for that view or table. +func (v *personTableType) NewStruct() reform.Struct { + return new(Person) +} + +// NewRecord makes a new record for that table. +func (v *personTableType) NewRecord() reform.Record { + return new(Person) +} + +// PKColumnIndex returns an index of primary key column for that table in SQL database. +func (v *personTableType) PKColumnIndex() uint { + return uint(v.s.PKFieldIndex) +} + +// PersonTable represents people view or table in SQL database. +var PersonTable = &personTableType{ + s: parse.StructInfo{Type: "Person", SQLSchema: "", SQLName: "people", Fields: []parse.FieldInfo{{Name: "ID", Type: "int32", Column: "id"}, {Name: "Name", Type: "string", Column: "name"}, {Name: "Email", Type: "*string", Column: "email"}, {Name: "CreatedAt", Type: "time.Time", Column: "created_at"}, {Name: "UpdatedAt", Type: "*time.Time", Column: "updated_at"}}, PKFieldIndex: 0}, + z: new(Person).Values(), +} + +// String returns a string representation of this struct or record. +func (s Person) String() string { + res := make([]string, 5) + res[0] = "ID: " + reform.Inspect(s.ID, true) + res[1] = "Name: " + reform.Inspect(s.Name, true) + res[2] = "Email: " + reform.Inspect(s.Email, true) + res[3] = "CreatedAt: " + reform.Inspect(s.CreatedAt, true) + res[4] = "UpdatedAt: " + reform.Inspect(s.UpdatedAt, true) + return strings.Join(res, ", ") +} + +// Values returns a slice of struct or record field values. +// Returned interface{} values are never untyped nils. +func (s *Person) Values() []interface{} { + return []interface{}{ + s.ID, + s.Name, + s.Email, + s.CreatedAt, + s.UpdatedAt, + } +} + +// Pointers returns a slice of pointers to struct or record fields. +// Returned interface{} values are never untyped nils. +func (s *Person) Pointers() []interface{} { + return []interface{}{ + &s.ID, + &s.Name, + &s.Email, + &s.CreatedAt, + &s.UpdatedAt, + } +} + +// View returns View object for that struct. +func (s *Person) View() reform.View { + return PersonTable +} + +// Table returns Table object for that record. +func (s *Person) Table() reform.Table { + return PersonTable +} + +// PKValue returns a value of primary key for that record. +// Returned interface{} value is never untyped nil. +func (s *Person) PKValue() interface{} { + return s.ID +} + +// PKPointer returns a pointer to primary key field for that record. +// Returned interface{} value is never untyped nil. +func (s *Person) PKPointer() interface{} { + return &s.ID +} + +// HasPK returns true if record has non-zero primary key set, false otherwise. +func (s *Person) HasPK() bool { + return s.ID != PersonTable.z[PersonTable.s.PKFieldIndex] +} + +// SetPK sets record primary key. +func (s *Person) SetPK(pk interface{}) { + if i64, ok := pk.(int64); ok { + s.ID = int32(i64) + } else { + s.ID = pk.(int32) + } +} + +// check interfaces +var ( + _ reform.View = PersonTable + _ reform.Struct = (*Person)(nil) + _ reform.Table = PersonTable + _ reform.Record = (*Person)(nil) + _ fmt.Stringer = (*Person)(nil) +) + +func init() { + parse.AssertUpToDate(&PersonTable.s, new(Person)) +} diff --git a/database/orm/reform/postman_collection.json b/database/orm/reform/postman_collection.json new file mode 100644 index 00000000..b72a9bd5 --- /dev/null +++ b/database/orm/reform/postman_collection.json @@ -0,0 +1,58 @@ +{ + "info": { + "_postman_id": "6b66000d-9c04-4d0a-b55c-8a493bf59015", + "name": "iris-reform-example", + "description": "Example API calls for iris reform example.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "http://localhost:8080/persons", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"name\": \"John\",\r\n \"email\": \"example@example.com\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/persons", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "persons" + ] + } + }, + "response": [] + }, + { + "name": "http://localhost:8080/persons", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/persons", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "persons" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/database/orm/sqlx/main.go b/database/orm/sqlx/main.go new file mode 100644 index 00000000..2779b43c --- /dev/null +++ b/database/orm/sqlx/main.go @@ -0,0 +1,113 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/jmoiron/sqlx" + _ "github.com/mattn/go-sqlite3" +) + +/* + go get -u github.com/mattn/go-sqlite3 + go get -u github.com/jmoiron/sqlx + + If you're on win64 and you can't install go-sqlite3: + 1. Download: https://sourceforge.net/projects/mingw-w64/files/latest/download + 2. Select "x86_x64" and "posix" + 3. Add C:\Program Files\mingw-w64\x86_64-7.1.0-posix-seh-rt_v5-rev1\mingw64\bin + to your PATH env variable. + + Docs: https://github.com/jmoiron/sqlx +*/ + +// Person is our person table structure. +type Person struct { + ID int64 `db:"person_id"` + FirstName string `db:"first_name"` + LastName string `db:"last_name"` + Email string +} + +const schema = ` +CREATE TABLE IF NOT EXISTS person ( + person_id INTEGER PRIMARY KEY, + first_name text, + last_name text, + email text +);` + +func main() { + app := iris.New() + + db, err := sqlx.Connect("sqlite3", "./test.db") + if err != nil { + app.Logger().Fatalf("db failed to initialized: %v", err) + } + iris.RegisterOnInterrupt(func() { + db.Close() + }) + + db.MustExec(schema) + + app.Get("/insert", func(ctx iris.Context) { + res, err := db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, + map[string]interface{}{ + "first": "John", + "last": "Doe", + "email": "johndoe@example.com", + }) + + if err != nil { + // Note: on production, don't give the error back to the user. + // However for the sake of the example we do: + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + id, err := res.LastInsertId() + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("person inserted: id: %d", id) + }) + + app.Get("/get", func(ctx iris.Context) { + // Select all persons. + people := []Person{} + db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC") + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + if len(people) == 0 { + ctx.Writef("no persons found, use /insert first.") + return + } + + ctx.Writef("persons found: %#v", people) + /* Select a single or more with a first name of John from the database: + person := Person{FirstName: "John"} + rows, err := db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, person) + if err != nil { ... } + defer rows.Close() + for rows.Next() { + if err := rows.StructScan(&person); err != nil { + if err == sql.ErrNoRows { + ctx.StopWithText(iris.StatusNotFound, "Person: %s not found", person.FirstName) + } else { + ctx.StopWithError(iris.StatusInternalServerError, err) + } + + return + } + } + */ + }) + + // http://localhost:8080/insert + // http://localhost:8080/get + app.Listen(":8080") +} diff --git a/database/sqlx/main.go b/database/sqlx/main.go new file mode 100644 index 00000000..c320970c --- /dev/null +++ b/database/sqlx/main.go @@ -0,0 +1,186 @@ +package main + +import ( + "context" + "database/sql" + "encoding/json" + "fmt" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/errors" + "github.com/kataras/iris/v12/x/sqlx" + + _ "github.com/lib/pq" +) + +const ( + host = "localhost" + port = 5432 + user = "postgres" + password = "admin!123" + dbname = "test" +) + +func main() { + app := iris.New() + + db := mustConnectDB() + mustCreateExtensions(context.Background(), db) + mustCreateTables(context.Background(), db) + + app.Post("/", insert(db)) + app.Get("/", list(db)) + app.Get("/{event_id:uuid}", getByID(db)) + + /* + curl --location --request POST 'http://localhost:8080' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "name": "second_test_event", + "data": { + "key": "value", + "year": 2022 + } + }' + + curl --location --request GET 'http://localhost:8080' + + curl --location --request GET 'http://localhost:8080/4fc0363f-1d1f-4a43-8608-5ed266485645' + */ + app.Listen(":8080") +} + +func mustConnectDB() *sql.DB { + connString := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", + host, port, user, password, dbname) + db, err := sql.Open("postgres", connString) + if err != nil { + panic(err) + } + + err = db.Ping() + if err != nil { + panic(err) + } + + return db +} + +func mustCreateExtensions(ctx context.Context, db *sql.DB) { + query := `CREATE EXTENSION IF NOT EXISTS pgcrypto;` + _, err := db.ExecContext(ctx, query) + if err != nil { + panic(err) + } +} + +func mustCreateTables(ctx context.Context, db *sql.DB) { + query := `CREATE TABLE IF NOT EXISTS "events" ( + "id" uuid PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(), + "created_at" timestamp(6) DEFAULT now(), + "name" text COLLATE "pg_catalog"."default", + "data" jsonb + );` + + _, err := db.ExecContext(ctx, query) + if err != nil { + panic(err) + } + + sqlx.Register("events", Event{}) +} + +type Event struct { + ID string `json:"id"` + CreatedAt time.Time `json:"created_at"` + Name string `json:"name"` + Data json.RawMessage `json:"data"` + + Presenter string `db:"-" json:"-"` +} + +func insertEvent(ctx context.Context, db *sql.DB, evt Event) (id string, err error) { + query := `INSERT INTO events(name,data) VALUES($1,$2) RETURNING id;` + err = db.QueryRowContext(ctx, query, evt.Name, evt.Data).Scan(&id) + return +} + +func listEvents(ctx context.Context, db *sql.DB) ([]Event, error) { + list := make([]Event, 0) + query := `SELECT * FROM events ORDER BY created_at;` + rows, err := db.QueryContext(ctx, query) + if err != nil { + return nil, err + } + // Not required. See sqlx.DefaultSchema.AutoCloseRows field. + // defer rows.Close() + + if err = sqlx.Bind(&list, rows); err != nil { + return nil, err + } + + return list, nil +} + +func getEvent(ctx context.Context, db *sql.DB, id string) (evt Event, err error) { + query := `SELECT * FROM events WHERE id = $1 LIMIT 1;` + err = sqlx.Query(ctx, db, &evt, query, id) + return + // + // Same as: + // + // rows, err := db.QueryContext(ctx, query, id) + // if err != nil { + // return Event{}, err + // } + // + // var evt Event + // err = sqlx.Bind(&evt, rows) + // + // return evt, err +} + +func insert(db *sql.DB) iris.Handler { + return func(ctx iris.Context) { + var evt Event + if err := ctx.ReadJSON(&evt); err != nil { + errors.InvalidArgument.Details(ctx, "unable to read body", err.Error()) + return + } + + id, err := insertEvent(ctx, db, evt) + if err != nil { + errors.Internal.LogErr(ctx, err) + return + } + + ctx.JSON(iris.Map{"id": id}) + } +} + +func list(db *sql.DB) iris.Handler { + return func(ctx iris.Context) { + events, err := listEvents(ctx, db) + if err != nil { + errors.Internal.LogErr(ctx, err) + return + } + + ctx.JSON(events) + } +} + +func getByID(db *sql.DB) iris.Handler { + return func(ctx iris.Context) { + eventID := ctx.Params().Get("event_id") + + evt, err := getEvent(ctx, db, eventID) + if err != nil { + errors.Internal.LogErr(ctx, err) + return + } + + ctx.JSON(evt) + } +} diff --git a/dependency-injection/basic/main.go b/dependency-injection/basic/main.go new file mode 100644 index 00000000..58138fa5 --- /dev/null +++ b/dependency-injection/basic/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/go-playground/validator/v10" +) + +type ( + testInput struct { + Email string `json:"email" validate:"required"` + } + + testOutput struct { + ID int `json:"id"` + Name string `json:"name"` + } +) + +func handler(id int, in testInput) testOutput { + return testOutput{ + ID: id, + Name: in.Email, + } +} + +func configureAPI(api *iris.APIContainer) { + /* Here is how you can inject a return value from a handler, + in this case the "testOutput": + api.UseResultHandler(func(next iris.ResultHandler) iris.ResultHandler { + return func(ctx iris.Context, v interface{}) error { + return next(ctx, map[string]interface{}{"injected": true}) + } + }) + */ + + api.Post("/{id:int}", handler) +} + +func main() { + app := iris.New() + app.Validator = validator.New() + app.Logger().SetLevel("debug") + + app.ConfigureContainer(configureAPI) + app.Listen(":8080") +} diff --git a/dependency-injection/basic/middleware/main.go b/dependency-injection/basic/middleware/main.go new file mode 100644 index 00000000..9c9d0e53 --- /dev/null +++ b/dependency-injection/basic/middleware/main.go @@ -0,0 +1,71 @@ +package main + +import ( + "errors" + + "github.com/kataras/iris/v12" +) + +type ( + testInput struct { + Email string `json:"email"` + } + + testOutput struct { + ID int `json:"id"` + Name string `json:"name"` + } +) + +func handler(id int, in testInput) testOutput { + return testOutput{ + ID: id, + Name: in.Email, + } +} + +var errCustom = errors.New("my_error") + +func middleware(in testInput) (int, error) { + if in.Email == "invalid" { + // stop the execution and don't continue to "handler" + // without firing an error. + return iris.StatusAccepted, iris.ErrStopExecution + } else if in.Email == "error" { + // stop the execution and fire a custom error. + return iris.StatusConflict, errCustom + } + + return iris.StatusOK, nil +} + +func newApp() *iris.Application { + app := iris.New() + + // handle the route, respond with + // a JSON and 200 status code + // or 202 status code and empty body + // or a 409 status code and "my_error" body. + app.ConfigureContainer(func(api *iris.APIContainer) { + // Enable execution of middlewares without ctx.Next requirement. + api.Self.SetExecutionRules(iris.ExecutionRules{ + Begin: iris.ExecutionOptions{ + Force: true, + }, + }) + api.Use(middleware) + api.Post("/{id:int}", handler) + }) + + app.Configure( + iris.WithOptimizations, /* optional */ + iris.WithoutBodyConsumptionOnUnmarshal, /* required when more than one handler is consuming request payload(testInput) */ + ) + + return app +} + +func main() { + app := newApp() + app.Listen(":8080") +} diff --git a/dependency-injection/basic/middleware/main_test.go b/dependency-injection/basic/middleware/main_test.go new file mode 100644 index 00000000..fdacc32d --- /dev/null +++ b/dependency-injection/basic/middleware/main_test.go @@ -0,0 +1,25 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestDependencyInjectionBasic_Middleware(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + e.POST("/42").WithJSON(testInput{Email: "my_email"}).Expect(). + Status(httptest.StatusOK). + JSON().IsEqual(testOutput{ID: 42, Name: "my_email"}) + + // it should stop the execution at the middleware and return the middleware's status code, + // because the error is `ErrStopExecution`. + e.POST("/42").WithJSON(testInput{Email: "invalid"}).Expect(). + Status(httptest.StatusAccepted).Body().IsEmpty() + + // it should stop the execution at the middleware and return the error's text. + e.POST("/42").WithJSON(testInput{Email: "error"}).Expect(). + Status(httptest.StatusConflict).Body().IsEqual("my_error") +} diff --git a/dependency-injection/context-register-dependency/main.go b/dependency-injection/context-register-dependency/main.go new file mode 100644 index 00000000..8d73bbae --- /dev/null +++ b/dependency-injection/context-register-dependency/main.go @@ -0,0 +1,95 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.Use(RoleMiddleware) + + app.Get("/", commonHandler) + c := app.ConfigureContainer() + /* + When you do NOT have access to the middleware code itself + then you can register a request dependency + which retrieves the value from the Context + and returns it, so handler/function's input arguments + with that `Role` type can be binded. + + c.RegisterDependency(func(ctx iris.Context) Role { + role, ok := GetRole(ctx) + if !ok { + // This codeblock will never be executed here + // but you can stop executing a handler which depends on + // that dependency with `ctx.StopExecution/ctx.StopWithXXX` methods + // or by returning a second output argument of `error` type. + ctx.StopExecution() + return Role{} + } + + return role + }) + */ + c.Get("/dep", handlerWithDependencies) + + // http://localhost:8080?name=kataras + // http://localhost:8080/dep?name=kataras + app.Listen(":8080") +} + +func commonHandler(ctx iris.Context) { + role, _ := GetRole(ctx) + ctx.WriteString(role.Name) +} + +func handlerWithDependencies(role Role) string { + return role.Name +} + +// Code for an example middleware. + +// Role struct value example. +type Role struct { + Name string +} + +const roleContextKey = "myapp.role" + +// RoleMiddleware example of a custom middleware. +func RoleMiddleware(ctx iris.Context) { + // [do it yourself: extract the role from the request...] + if ctx.URLParam("name") != "kataras" { + ctx.StopWithStatus(iris.StatusUnauthorized) + return + } + // + + role := Role{Name: "admin"} + + ctx.Values().Set(roleContextKey, role) + + // When you have access to the middleware itself: + // Use the `RegisterDependency` to register + // struct type values as dependencies at request-time for + // any potential dependency injection-ed user handler. + // This way the user of your middleware can get rid of + // manually register a dependency for that `Role` type with calls of + // `APIContainer.RegisterDependency` (and `mvc.Application.Register`). + ctx.RegisterDependency(role) + + ctx.Next() +} + +// GetRole returns the role inside the context values, +// the `roleMiddleware` should be executed first. +func GetRole(ctx iris.Context) (Role, bool) { + v := ctx.Values().Get(roleContextKey) + if v != nil { + if role, ok := v.(Role); ok { + return role, true + } + } + + return Role{}, false +} + +// End Code of our example middleware. diff --git a/dependency-injection/jwt/contrib/go.mod b/dependency-injection/jwt/contrib/go.mod new file mode 100644 index 00000000..bb6157cf --- /dev/null +++ b/dependency-injection/jwt/contrib/go.mod @@ -0,0 +1,55 @@ +module github.com/kataras/iris/_examples/dependency-injection/jwt/contrib + +go 1.22 + +require ( + github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/dependency-injection/jwt/contrib/go.sum b/dependency-injection/jwt/contrib/go.sum new file mode 100644 index 00000000..a17ca885 --- /dev/null +++ b/dependency-injection/jwt/contrib/go.sum @@ -0,0 +1,182 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee h1:23N+vuMpu0Dh3fbtrWkf/+uIt9zAyPtqJa3fb3M0bp0= +github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee/go.mod h1:0l8Dv+O13+WeimDdbTzwpOqjtcHYrFfNVBcZbBTV/v8= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/dependency-injection/jwt/contrib/main.go b/dependency-injection/jwt/contrib/main.go new file mode 100644 index 00000000..171f2ed1 --- /dev/null +++ b/dependency-injection/jwt/contrib/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/iris-contrib/middleware/jwt" +) + +var secret = []byte("My Secret Key") + +func main() { + app := iris.New() + app.ConfigureContainer(register) + + app.Listen(":8080") +} + +func register(api *iris.APIContainer) { + j := jwt.New(jwt.Config{ + // Extract by "token" url parameter. + Extractor: jwt.FromFirst(jwt.FromParameter("token"), jwt.FromAuthHeader), + ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { + return secret, nil + }, + SigningMethod: jwt.SigningMethodHS256, + }) + + api.Get("/authenticate", writeToken) + // This works as usually: + api.Get("/restricted", j.Serve, restrictedPage) + + // You can also bind the *jwt.Token (see `verifiedWithBindedTokenPage`) + // by registering a *jwt.Token dependency. + // + // api.RegisterDependency(func(ctx iris.Context) *jwt.Token { + // if err := j.CheckJWT(ctx); err != nil { + // ctx.StopWithStatus(iris.StatusUnauthorized) + // return nil + // } + // + // token := j.Get(ctx) + // return token + // }) + // ^ You can do the same with MVC too, as the container is shared and works + // the same way in both functions-as-handlers and structs-as-controllers. + // + // api.Get("/", restrictedPageWithBindedTokenPage) +} + +func writeToken() string { + token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "foo": "bar", + }) + + tokenString, _ := token.SignedString(secret) + return tokenString +} + +func restrictedPage() string { + return "This page can only be seen by verified clients" +} + +func restrictedPageWithBindedTokenPage(token *jwt.Token) string { + // Token[foo] value: bar + return "Token[foo] value: " + token.Claims.(jwt.MapClaims)["foo"].(string) +} diff --git a/dependency-injection/jwt/main.go b/dependency-injection/jwt/main.go new file mode 100644 index 00000000..ff328eb9 --- /dev/null +++ b/dependency-injection/jwt/main.go @@ -0,0 +1,70 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/jwt" +) + +func main() { + app := iris.New() + app.ConfigureContainer(register) + + // http://localhost:8080/authenticate + // http://localhost:8080/restricted (Header: Authorization = Bearer $token) + app.Listen(":8080") +} + +var secret = []byte("secret") + +func register(api *iris.APIContainer) { + api.RegisterDependency(func(ctx iris.Context) (claims userClaims) { + /* Using the middleware: + if ctx.Proceed(verify) { + // ^ the "verify" middleware will stop the execution if it's failed to verify the request. + // Map the input parameter of "restricted" function with the claims. + return jwt.Get(ctx).(*userClaims) + }*/ + token := jwt.FromHeader(ctx) + if token == "" { + ctx.StopWithError(iris.StatusUnauthorized, jwt.ErrMissing) + return + } + + verifiedToken, err := jwt.Verify(jwt.HS256, secret, []byte(token)) + if err != nil { + ctx.StopWithError(iris.StatusUnauthorized, err) + return + } + + verifiedToken.Claims(&claims) + return + }) + + api.Get("/authenticate", writeToken) + api.Get("/restricted", restrictedPage) +} + +type userClaims struct { + Username string `json:"username"` +} + +func writeToken(ctx iris.Context) { + claims := userClaims{ + Username: "kataras", + } + + token, err := jwt.Sign(jwt.HS256, secret, claims, jwt.MaxAge(1*time.Minute)) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Write(token) +} + +func restrictedPage(claims userClaims) string { + // userClaims.Username: kataras + return "userClaims.Username: " + claims.Username +} diff --git a/hero/overview/datamodels/movie.go b/dependency-injection/overview/datamodels/movie.go similarity index 89% rename from hero/overview/datamodels/movie.go rename to dependency-injection/overview/datamodels/movie.go index 7649d487..1b25d127 100644 --- a/hero/overview/datamodels/movie.go +++ b/dependency-injection/overview/datamodels/movie.go @@ -8,9 +8,9 @@ package datamodels // which could wrap by embedding the datamodels.Movie or // declare new fields instead butwe will use this datamodel // as the only one Movie model in our application, -// for the shake of simplicty. +// for the sake of simplicty. type Movie struct { - ID int64 `json:"id"` + ID uint64 `json:"id"` Name string `json:"name"` Year int `json:"year"` Genre string `json:"genre"` diff --git a/mvc/overview/datasource/movies.go b/dependency-injection/overview/datasource/movies.go similarity index 86% rename from mvc/overview/datasource/movies.go rename to dependency-injection/overview/datasource/movies.go index b7f35a74..4b5fbf31 100644 --- a/mvc/overview/datasource/movies.go +++ b/dependency-injection/overview/datasource/movies.go @@ -2,10 +2,10 @@ package datasource -import "github.com/iris-contrib/examples/mvc/overview/datamodels" +import "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datamodels" // Movies is our imaginary data source. -var Movies = map[int64]datamodels.Movie{ +var Movies = map[uint64]datamodels.Movie{ 1: { ID: 1, Name: "Casablanca", diff --git a/dependency-injection/overview/main.go b/dependency-injection/overview/main.go new file mode 100644 index 00000000..8386aaae --- /dev/null +++ b/dependency-injection/overview/main.go @@ -0,0 +1,55 @@ +// file: main.go + +package main + +import ( + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datasource" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/repositories" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/services" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/web/middleware" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/web/routes" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + // Load the template files. + app.RegisterView(iris.HTML("./web/views", ".html")) + + // Create our movie repository with some (memory) data from the datasource. + repo := repositories.NewMovieRepository(datasource.Movies) + + app.Party("/hello").ConfigureContainer(func(r *iris.APIContainer) { + r.Get("/", routes.Hello) + r.Get("/{name}", routes.HelloName) + }) + + app.Party("/movies").ConfigureContainer(func(r *iris.APIContainer) { + // Create our movie service, we will bind it to the movie app's dependencies. + movieService := services.NewMovieService(repo) + r.RegisterDependency(movieService) + + // Add the basic authentication(admin:password) middleware + // for the /movies based requests. + r.Use(middleware.BasicAuth) + + r.Get("/", routes.Movies) + r.Get("/{id:uint64}", routes.MovieByID) + r.Put("/{id:uint64}", routes.UpdateMovieByID) + r.Delete("/{id:uint64}", routes.DeleteMovieByID) + }) + + // http://localhost:8080/hello + // http://localhost:8080/hello/iris + // http://localhost:8080/movies ("admin": "password") + // http://localhost:8080/movies/1 + app.Listen( + // Start the web server at localhost:8080 + "localhost:8080", + // enables faster json serialization and more: + iris.WithOptimizations, + ) +} diff --git a/hero/overview/repositories/movie_repository.go b/dependency-injection/overview/repositories/movie_repository.go similarity index 95% rename from hero/overview/repositories/movie_repository.go rename to dependency-injection/overview/repositories/movie_repository.go index c6e57a8c..0a46cb1b 100644 --- a/hero/overview/repositories/movie_repository.go +++ b/dependency-injection/overview/repositories/movie_repository.go @@ -6,7 +6,7 @@ import ( "errors" "sync" - "github.com/iris-contrib/examples/hero/overview/datamodels" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datamodels" ) // Query represents the visitor and action queries. @@ -27,14 +27,14 @@ type MovieRepository interface { // NewMovieRepository returns a new movie memory-based repository, // the one and only repository type in our example. -func NewMovieRepository(source map[int64]datamodels.Movie) MovieRepository { +func NewMovieRepository(source map[uint64]datamodels.Movie) MovieRepository { return &movieMemoryRepository{source: source} } // movieMemoryRepository is a "MovieRepository" // which manages the movies using the memory data source (map). type movieMemoryRepository struct { - source map[int64]datamodels.Movie + source map[uint64]datamodels.Movie mu sync.RWMutex } @@ -115,7 +115,7 @@ func (r *movieMemoryRepository) InsertOrUpdate(movie datamodels.Movie) (datamode id := movie.ID if id == 0 { // Create new action - var lastID int64 + var lastID uint64 // find the biggest ID in order to not have duplications // in productions apps you can use a third-party // library to generate a UUID as string. diff --git a/mvc/overview/services/movie_service.go b/dependency-injection/overview/services/movie_service.go similarity index 72% rename from mvc/overview/services/movie_service.go rename to dependency-injection/overview/services/movie_service.go index 0abed1c4..6835a9b5 100644 --- a/mvc/overview/services/movie_service.go +++ b/dependency-injection/overview/services/movie_service.go @@ -3,8 +3,8 @@ package services import ( - "github.com/iris-contrib/examples/mvc/overview/datamodels" - "github.com/iris-contrib/examples/mvc/overview/repositories" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datamodels" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/repositories" ) // MovieService handles some of the CRUID operations of the movie datamodel. @@ -15,9 +15,9 @@ import ( // because we may need to change or try an experimental different domain logic at the future. type MovieService interface { GetAll() []datamodels.Movie - GetByID(id int64) (datamodels.Movie, bool) - DeleteByID(id int64) bool - UpdatePosterAndGenreByID(id int64, poster string, genre string) (datamodels.Movie, error) + GetByID(id uint64) (datamodels.Movie, bool) + DeleteByID(id uint64) bool + UpdatePosterAndGenreByID(id uint64, poster string, genre string) (datamodels.Movie, error) } // NewMovieService returns the default movie service. @@ -39,14 +39,14 @@ func (s *movieService) GetAll() []datamodels.Movie { } // GetByID returns a movie based on its id. -func (s *movieService) GetByID(id int64) (datamodels.Movie, bool) { +func (s *movieService) GetByID(id uint64) (datamodels.Movie, bool) { return s.repo.Select(func(m datamodels.Movie) bool { return m.ID == id }) } // UpdatePosterAndGenreByID updates a movie's poster and genre. -func (s *movieService) UpdatePosterAndGenreByID(id int64, poster string, genre string) (datamodels.Movie, error) { +func (s *movieService) UpdatePosterAndGenreByID(id uint64, poster string, genre string) (datamodels.Movie, error) { // update the movie and return it. return s.repo.InsertOrUpdate(datamodels.Movie{ ID: id, @@ -58,7 +58,7 @@ func (s *movieService) UpdatePosterAndGenreByID(id int64, poster string, genre s // DeleteByID deletes a movie by its id. // // Returns true if deleted otherwise false. -func (s *movieService) DeleteByID(id int64) bool { +func (s *movieService) DeleteByID(id uint64) bool { return s.repo.Delete(func(m datamodels.Movie) bool { return m.ID == id }, 1) diff --git a/dependency-injection/overview/web/middleware/basicauth.go b/dependency-injection/overview/web/middleware/basicauth.go new file mode 100644 index 00000000..8cda6629 --- /dev/null +++ b/dependency-injection/overview/web/middleware/basicauth.go @@ -0,0 +1,10 @@ +// file: web/middleware/basicauth.go + +package middleware + +import "github.com/kataras/iris/v12/middleware/basicauth" + +// BasicAuth middleware sample. +var BasicAuth = basicauth.Default(map[string]string{ + "admin": "password", +}) diff --git a/hero/overview/web/routes/hello.go b/dependency-injection/overview/web/routes/hello.go similarity index 92% rename from hero/overview/web/routes/hello.go rename to dependency-injection/overview/web/routes/hello.go index 8feeca14..e0c4a029 100644 --- a/hero/overview/web/routes/hello.go +++ b/dependency-injection/overview/web/routes/hello.go @@ -5,7 +5,7 @@ package routes import ( "errors" - "github.com/kataras/iris/hero" + "github.com/kataras/iris/v12/hero" ) var helloView = hero.View{ @@ -19,7 +19,7 @@ var helloView = hero.View{ // Hello will return a predefined view with bind data. // // `hero.Result` is just an interface with a `Dispatch` function. -// `hero.Response` and `hero.View` are the built'n result type dispatchers +// `hero.Response` and `hero.View` are the builtin result type dispatchers // you can even create custom response dispatchers by // implementing the `github.com/kataras/iris/hero#Result` interface. func Hello() hero.Result { diff --git a/hero/overview/web/routes/movies.go b/dependency-injection/overview/web/routes/movies.go similarity index 78% rename from hero/overview/web/routes/movies.go rename to dependency-injection/overview/web/routes/movies.go index 2998a0d4..d6b902d9 100644 --- a/hero/overview/web/routes/movies.go +++ b/dependency-injection/overview/web/routes/movies.go @@ -5,10 +5,10 @@ package routes import ( "errors" - "github.com/iris-contrib/examples/hero/overview/datamodels" - "github.com/iris-contrib/examples/hero/overview/services" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/datamodels" + "github.com/kataras/iris/v12/_examples/dependency-injection/overview/services" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // Movies returns list of the movies. @@ -21,14 +21,14 @@ func Movies(service services.MovieService) (results []datamodels.Movie) { // MovieByID returns a movie. // Demo: // curl -i http://localhost:8080/movies/1 -func MovieByID(service services.MovieService, id int64) (movie datamodels.Movie, found bool) { +func MovieByID(service services.MovieService, id uint64) (movie datamodels.Movie, found bool) { return service.GetByID(id) // it will throw 404 if not found. } // UpdateMovieByID updates a movie. // Demo: // curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1 -func UpdateMovieByID(ctx iris.Context, service services.MovieService, id int64) (datamodels.Movie, error) { +func UpdateMovieByID(ctx iris.Context, service services.MovieService, id uint64) (datamodels.Movie, error) { // get the request data for poster and genre file, info, err := ctx.FormFile("poster") if err != nil { @@ -47,7 +47,7 @@ func UpdateMovieByID(ctx iris.Context, service services.MovieService, id int64) // DeleteMovieByID deletes a movie. // Demo: // curl -i -X DELETE -u admin:password http://localhost:8080/movies/1 -func DeleteMovieByID(service services.MovieService, id int64) interface{} { +func DeleteMovieByID(service services.MovieService, id uint64) interface{} { wasDel := service.DeleteByID(id) if wasDel { // return the deleted movie's ID diff --git a/hero/overview/web/views/hello/index.html b/dependency-injection/overview/web/views/hello/index.html similarity index 100% rename from hero/overview/web/views/hello/index.html rename to dependency-injection/overview/web/views/hello/index.html diff --git a/hero/overview/web/views/hello/name.html b/dependency-injection/overview/web/views/hello/name.html similarity index 100% rename from hero/overview/web/views/hello/name.html rename to dependency-injection/overview/web/views/hello/name.html diff --git a/dependency-injection/sessions/main.go b/dependency-injection/sessions/main.go new file mode 100644 index 00000000..2172c34c --- /dev/null +++ b/dependency-injection/sessions/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12/_examples/dependency-injection/sessions/routes" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/sessions" +) + +func main() { + app := iris.New() + sessionManager := sessions.New(sessions.Config{ + Cookie: "site_session_id", + Expires: 60 * time.Minute, + AllowReclaim: true, + }) + + // Session is automatically binded through `sessions.Get(ctx)` + // if a *sessions.Session input argument is present on the handler's function, + // which `routes.Index` does. + app.Use(sessionManager.Handler()) + + // Method: GET + // Path: http://localhost:8080 + app.ConfigureContainer(registerRoutes) + + app.Listen(":8080") +} + +func registerRoutes(api *iris.APIContainer) { + api.Get("/", routes.Index) +} diff --git a/dependency-injection/sessions/routes/index.go b/dependency-injection/sessions/routes/index.go new file mode 100644 index 00000000..d1660563 --- /dev/null +++ b/dependency-injection/sessions/routes/index.go @@ -0,0 +1,17 @@ +package routes + +import ( + "fmt" + + "github.com/kataras/iris/v12/sessions" +) + +// Index will increment a simple int version based on the visits that this user/session did. +func Index(session *sessions.Session) string { + // it increments a "visits" value of integer by one, + // if the entry with key 'visits' doesn't exist it will create it for you. + visits := session.Increment("visits", 1) + + // write the current, updated visits. + return fmt.Sprintf("%d visit(s) from my current session", visits) +} diff --git a/dependency-injection/smart-contract/main.go b/dependency-injection/smart-contract/main.go new file mode 100644 index 00000000..6c6e4ca1 --- /dev/null +++ b/dependency-injection/smart-contract/main.go @@ -0,0 +1,156 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/kataras/iris/v12" + + // External package to optionally filter JSON responses before sent, + // see `sendJSON` for more. + "github.com/jmespath/go-jmespath" +) + +/* + $ go get github.com/jmespath/go-jmespath +*/ + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + + // http://localhost:8080/users?query=[?Name == 'John Doe'].Age + // <- client will receive the age of a user which his name is "John Doe". + // You can also test query=[0].Name to retrieve the first user's name. + // Or even query=[0:3].Age to print the first three ages. + // Learn more about jmespath and how to filter: + // http://jmespath.readthedocs.io/en/latest/ and + // https://github.com/jmespath/go-jmespath/tree/master/fuzz/testdata + // + // http://localhost:8080/users + // http://localhost:8080/users/William%20Woe + // http://localhost:8080/users/William%20Woe/age + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + // PartyFunc is the same as usersRouter := app.Party("/users") + // but it gives us an easy way to call router's registration functions, + // i.e functions from another package that can handle this group of routes. + app.PartyFunc("/users", registerUsersRoutes) + + return app +} + +/* + START OF USERS ROUTER +*/ + +func registerUsersRoutes(usersRouter iris.Party) { + // GET: /users + usersRouter.Get("/", getAllUsersHandler) + usersRouter.Party("/{name}").ConfigureContainer(registerUserRoutes) +} + +type user struct { + Name string `json:"name"` + Age int `json:"age"` +} + +var usersSample = []*user{ + {"William Woe", 25}, + {"Mary Moe", 15}, + {"John Doe", 17}, +} + +func getAllUsersHandler(ctx iris.Context) { + err := sendJSON(ctx, usersSample) + if err != nil { + fail(ctx, iris.StatusInternalServerError, "unable to send a list of all users: %v", err) + return + } +} + +/* + START OF USERS.USER SUB ROUTER +*/ + +func registerUserRoutes(userRouter *iris.APIContainer) { + userRouter.RegisterDependency(userDependency) + // GET: /users/{name:string} + userRouter.Get("/", getUserHandler) + // GET: /users/{name:string}/age + userRouter.Get("/age", getUserAgeHandler) +} + +var userDependency = func(ctx iris.Context) *user { + name := strings.Title(ctx.Params().Get("name")) + for _, u := range usersSample { + if u.Name == name { + return u + } + } + + // you may want or no to handle the error here, either way the main route handler + // is going to be executed, always. A dynamic dependency(per-request) is not a middleware, so things like `ctx.Next()` or `ctx.StopExecution()` + // do not apply here, look the `getUserHandler`'s first lines; we stop/exit the handler manually + // if the received user is nil but depending on your app's needs, it is possible to do other things too. + // A dynamic dependency like this can return more output values, i.e (*user, bool). + fail(ctx, iris.StatusNotFound, "user with name '%s' not found", name) + return nil +} + +func getUserHandler(ctx iris.Context, u *user) { + sendJSON(ctx, u) +} + +func getUserAgeHandler(u *user) string { + return fmt.Sprintf("%d", u.Age) +} + +/* END OF USERS.USER SUB ROUTER */ + +/* END OF USERS ROUTER */ + +// common JSON response for manual HTTP errors, optionally. +type httpError struct { + Code int `json:"code"` + Reason string `json:"reason"` +} + +func (h httpError) Error() string { + return fmt.Sprintf("Status Code: %d\nReason: %s", h.Code, h.Reason) +} + +func fail(ctx iris.Context, statusCode int, format string, a ...interface{}) { + err := httpError{ + Code: statusCode, + Reason: fmt.Sprintf(format, a...), + } + + // log all the >= 500 internal errors. + if statusCode >= 500 { + ctx.Application().Logger().Error(err) + } + + // no next handlers will run. + ctx.StopWithJSON(statusCode, err) +} + +// JSON helper to give end-user the ability to put indention chars or filtering the response, you can do that, optionally. +// If you'd like to see that function inside the Iris' Context itself raise a [Feature Request] issue and link this example. +func sendJSON(ctx iris.Context, resp interface{}) (err error) { + indent := ctx.URLParamDefault("indent", " ") + // i.e [?Name == 'John Doe'].Age # to output the [age] of a user which his name is "John Doe". + if query := ctx.URLParam("query"); query != "" && query != "[]" { + resp, err = jmespath.Search(query, resp) + if err != nil { + return + } + } + + err = ctx.JSON(resp, iris.JSON{Indent: indent, UnescapeHTML: true}) + return err +} diff --git a/desktop/blink/main.go b/desktop/blink/main.go new file mode 100644 index 00000000..866bdd7b --- /dev/null +++ b/desktop/blink/main.go @@ -0,0 +1,43 @@ +//go:build windows +// +build windows + +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/raintean/blink" +) + +const addr = "127.0.0.1:8080" + +/* +$ go build -mod=mod -ldflags -H=windowsgui -o myapp.exe +$ ./myapp.exe # run the app +*/ +func main() { + go runServer() + showAndWaitWindow() +} + +func runServer() { + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1> Hello Desktop</h1>") + }) + app.Listen(addr) +} + +func showAndWaitWindow() { + blink.SetDebugMode(true) + if err := blink.InitBlink(); err != nil { + panic(err) + } + + view := blink.NewWebView(false, 800, 600) + view.LoadURL(addr) + view.SetWindowTitle("My App") + view.MoveToCenter() + view.ShowWindow() + + <-view.Destroy +} diff --git a/desktop/lorca/main.go b/desktop/lorca/main.go new file mode 100644 index 00000000..a59b9623 --- /dev/null +++ b/desktop/lorca/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/zserge/lorca" +) + +const addr = "127.0.0.1:8080" + +/* +$ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows +$ ./myapp.exe # run +*/ +func main() { + go runServer() + showAndWaitWindow() +} + +func runServer() { + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<head><title>My App</title></head><body><h1>Hello Desktop</h1></body>") + }) + app.Listen(addr) +} + +func showAndWaitWindow() { + webview, err := lorca.New("http://"+addr, "", 800, 600) + if err != nil { + panic(err) + } + defer webview.Close() + + // webview.SetBounds(lorca.Bounds{ + // WindowState: lorca.WindowStateFullscreen, + // }) + + // Wait for the browser window to be closed + <-webview.Done() +} diff --git a/desktop/webview/go.mod b/desktop/webview/go.mod new file mode 100644 index 00000000..0653aeea --- /dev/null +++ b/desktop/webview/go.mod @@ -0,0 +1,54 @@ +module github.com/kataras/iris/_examples/desktop/webview + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/desktop/webview/go.sum b/desktop/webview/go.sum new file mode 100644 index 00000000..4384c884 --- /dev/null +++ b/desktop/webview/go.sum @@ -0,0 +1,180 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43 h1:PwbNdNumoKba+ZgrE6ZpSluJfNJfyMuqwVyUB5+iLDI= +github.com/webview/webview_go v0.0.0-20240220051247-56f456ca3a43/go.mod h1:yE65LFCeWf4kyWD5re+h4XNvOHJEXOCOuJZ4v8l5sgk= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/desktop/webview/main.go b/desktop/webview/main.go new file mode 100644 index 00000000..b377798e --- /dev/null +++ b/desktop/webview/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/webview/webview_go" +) + +const addr = "127.0.0.1:8080" + +/* +# Windows requires special linker flags for GUI apps. +# It's also recommended to use TDM-GCC-64 compiler for CGo. +# http://tdm-gcc.tdragon.net/download +# +# +$ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows +$ ./myapp.exe # run +# +# MacOS uses app bundles for GUI apps +$ mkdir -p example.app/Contents/MacOS +$ go build -o example.app/Contents/MacOS/example +$ open example.app # Or click on the app in Finder +# +# Note: if you see "use option -std=c99 or -std=gnu99 to compile your code" +# please refer to: https://github.com/webview/webview/issues/188. +# New repository: https://github.com/webview/webview_go. +*/ +func main() { + go runServer() + showAndWaitWindow() +} + +func runServer() { + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Hello Desktop</h1>") + }) + app.Listen(addr) +} + +func showAndWaitWindow() { + debug := true + + w := webview.New(debug) + defer w.Destroy() + w.SetTitle("Minimal webview example") + w.SetSize(800, 600, webview.HintNone) + w.Navigate("http://" + addr) + w.Run() +} diff --git a/tutorial/dropzonejs/README.md b/dropzonejs/README.md similarity index 96% rename from tutorial/dropzonejs/README.md rename to dropzonejs/README.md index 31912956..0e6c6ac9 100644 --- a/tutorial/dropzonejs/README.md +++ b/dropzonejs/README.md @@ -89,7 +89,7 @@ import ( "io" "strings" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) const uploadsDir = "./public/uploads/" @@ -101,12 +101,15 @@ func main() { app.RegisterView(iris.HTML("./views", ".html")) // Make the /public route path to statically serve the ./public/... contents - app.StaticWeb("/public", "./public") + app.HandleDir("/public", iris.Dir("./public")) // Render the actual form // GET: http://localhost:8080 app.Get("/", func(ctx iris.Context) { - ctx.View("upload.html") + if err := ctx.View("upload.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) // Upload the file to the server @@ -139,7 +142,7 @@ func main() { }) // Start the server at http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } ``` diff --git a/tutorial/dropzonejs/README_PART2.md b/dropzonejs/README_PART2.md similarity index 97% rename from tutorial/dropzonejs/README_PART2.md rename to dropzonejs/README_PART2.md index 599e5782..437d6955 100644 --- a/tutorial/dropzonejs/README_PART2.md +++ b/dropzonejs/README_PART2.md @@ -54,7 +54,7 @@ import ( "strings" "sync" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" "github.com/nfnt/resize" // $ go get -u github.com/nfnt/resize ) @@ -168,10 +168,13 @@ func main() { app := iris.New() app.RegisterView(iris.HTML("./views", ".html")) - app.StaticWeb("/public", "./public") + app.HandleDir("/public", iris.Dir("./public")) app.Get("/", func(ctx iris.Context) { - ctx.View("upload.html") + if err := ctx.View("upload.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) files := scanUploads(uploadsDir) @@ -212,7 +215,7 @@ func main() { }) // start the server at http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } ``` @@ -302,7 +305,7 @@ If you have done it successfully. Now go and upload some images and reload the u - http://www.dropzonejs.com/#server-side-implementation - https://www.startutorial.com/articles/view/how-to-build-a-file-upload-form-using-dropzonejs-and-php - https://docs.iris-go.com -- https://github.com/kataras/iris/tree/master/_examples/tutorial/dropzonejs +- https://github.com/kataras/iris/tree/main/_examples/dropzonejs ## The end diff --git a/tutorial/dropzonejs/folder_structure.png b/dropzonejs/folder_structure.png similarity index 100% rename from tutorial/dropzonejs/folder_structure.png rename to dropzonejs/folder_structure.png diff --git a/tutorial/dropzonejs/meta.yml b/dropzonejs/meta.yml similarity index 52% rename from tutorial/dropzonejs/meta.yml rename to dropzonejs/meta.yml index f0815494..8b23e948 100644 --- a/tutorial/dropzonejs/meta.yml +++ b/dropzonejs/meta.yml @@ -1,8 +1,8 @@ Name: DropzoneJS Articles: - Title: How to build a file upload form using DropzoneJS and Go - Source: https://hackernoon.com/how-to-build-a-file-upload-form-using-dropzonejs-and-go-8fb9f258a991 + Source: https://medium.com/hackernoon/how-to-build-a-file-upload-form-using-dropzonejs-and-go-8fb9f258a991 Author: https://twitter.com/@kataras - Title: How to display existing files on server using DropzoneJS and Go - Source: https://hackernoon.com/how-to-display-existing-files-on-server-using-dropzonejs-and-go-53e24b57ba19 + Source: https://medium.com/@kataras/how-to-display-existing-files-on-server-using-dropzonejs-and-go-53e24b57ba19 Author: https://twitter.com/@kataras \ No newline at end of file diff --git a/tutorial/dropzonejs/no_files.png b/dropzonejs/no_files.png similarity index 100% rename from tutorial/dropzonejs/no_files.png rename to dropzonejs/no_files.png diff --git a/tutorial/dropzonejs/src/main.go b/dropzonejs/src/main.go similarity index 94% rename from tutorial/dropzonejs/src/main.go rename to dropzonejs/src/main.go index 86e54982..56edf24c 100644 --- a/tutorial/dropzonejs/src/main.go +++ b/dropzonejs/src/main.go @@ -10,7 +10,7 @@ import ( "strings" "sync" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" "github.com/nfnt/resize" ) @@ -32,7 +32,6 @@ type uploadedFiles struct { } func scanUploads(dir string) *uploadedFiles { - f := new(uploadedFiles) lindex := dir[len(dir)-1] @@ -54,7 +53,6 @@ func scanUploads(dir string) *uploadedFiles { func (f *uploadedFiles) scan(dir string) { f.dir = dir filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - // if it's directory or a thumbnail we saved earlier, skip it. if info.IsDir() || strings.HasPrefix(info.Name(), "thumbnail_") { return nil @@ -117,17 +115,19 @@ func (f *uploadedFiles) createThumbnail(uf uploadedFile) { png.Encode(out, resized) } // and so on... you got the point, this code can be simplify, as a practise. - } func main() { app := iris.New() app.RegisterView(iris.HTML("./views", ".html")) - app.StaticWeb("/public", "./public") + app.HandleDir("/public", iris.Dir("./public")) app.Get("/", func(ctx iris.Context) { - ctx.View("upload.html") + if err := ctx.View("upload.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) files := scanUploads(uploadsDir) @@ -152,7 +152,6 @@ func main() { // assuming that you have a folder named 'uploads' out, err := os.OpenFile(uploadsDir+fname, os.O_WRONLY|os.O_CREATE, 0666) - if err != nil { ctx.StatusCode(iris.StatusInternalServerError) ctx.Application().Logger().Warnf("Error while preparing the new file: %v", err.Error()) @@ -168,5 +167,5 @@ func main() { }) // start the server at http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/tutorial/dropzonejs/src/public/css/dropzone.css b/dropzonejs/src/public/css/dropzone.css similarity index 100% rename from tutorial/dropzonejs/src/public/css/dropzone.css rename to dropzonejs/src/public/css/dropzone.css diff --git a/tutorial/dropzonejs/src/public/js/dropzone.js b/dropzonejs/src/public/js/dropzone.js similarity index 100% rename from tutorial/dropzonejs/src/public/js/dropzone.js rename to dropzonejs/src/public/js/dropzone.js diff --git a/tutorial/dropzonejs/src/views/upload.html b/dropzonejs/src/views/upload.html similarity index 100% rename from tutorial/dropzonejs/src/views/upload.html rename to dropzonejs/src/views/upload.html diff --git a/tutorial/dropzonejs/with_files.png b/dropzonejs/with_files.png similarity index 100% rename from tutorial/dropzonejs/with_files.png rename to dropzonejs/with_files.png diff --git a/experimental-handlers/README.md b/experimental-handlers/README.md deleted file mode 100644 index 6e21b557..00000000 --- a/experimental-handlers/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Install iris-contrib/middleware - -```sh -$ go get -u github.com/iris-contrib/middleware/... -``` \ No newline at end of file diff --git a/experimental-handlers/casbin/middleware/casbinmodel.conf b/experimental-handlers/casbin/middleware/casbinmodel.conf deleted file mode 100644 index d1b3dbd7..00000000 --- a/experimental-handlers/casbin/middleware/casbinmodel.conf +++ /dev/null @@ -1,14 +0,0 @@ -[request_definition] -r = sub, obj, act - -[policy_definition] -p = sub, obj, act - -[role_definition] -g = _, _ - -[policy_effect] -e = some(where (p.eft == allow)) - -[matchers] -m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") \ No newline at end of file diff --git a/experimental-handlers/casbin/middleware/casbinpolicy.csv b/experimental-handlers/casbin/middleware/casbinpolicy.csv deleted file mode 100644 index 52837375..00000000 --- a/experimental-handlers/casbin/middleware/casbinpolicy.csv +++ /dev/null @@ -1,5 +0,0 @@ -p, alice, /dataset1/*, GET -p, alice, /dataset1/resource1, POST -p, bob, /dataset2/resource1, * -p, bob, /dataset2/resource2, GET -p, bob, /dataset2/folder1/*, POST \ No newline at end of file diff --git a/experimental-handlers/casbin/middleware/main.go b/experimental-handlers/casbin/middleware/main.go deleted file mode 100644 index 03639675..00000000 --- a/experimental-handlers/casbin/middleware/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/casbin/casbin" - cm "github.com/iris-contrib/middleware/casbin" -) - -// $ go get github.com/casbin/casbin -// $ go run main.go - -// Enforcer maps the model and the policy for the casbin service, we use this variable on the main_test too. -var Enforcer = casbin.NewEnforcer("casbinmodel.conf", "casbinpolicy.csv") - -func newApp() *iris.Application { - casbinMiddleware := cm.New(Enforcer) - - app := iris.New() - app.Use(casbinMiddleware.ServeHTTP) - - app.Get("/", hi) - - app.Get("/dataset1/{p:path}", hi) // p, alice, /dataset1/*, GET - - app.Post("/dataset1/resource1", hi) - - app.Get("/dataset2/resource2", hi) - app.Post("/dataset2/folder1/{p:path}", hi) - - app.Any("/dataset2/resource1", hi) - - return app -} - -func main() { - app := newApp() - app.Run(iris.Addr(":8080")) -} - -func hi(ctx iris.Context) { - ctx.Writef("Hello %s", cm.Username(ctx.Request())) -} diff --git a/experimental-handlers/casbin/middleware/main_test.go b/experimental-handlers/casbin/middleware/main_test.go deleted file mode 100644 index 275f2955..00000000 --- a/experimental-handlers/casbin/middleware/main_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "testing" - - "github.com/iris-contrib/httpexpect" - "github.com/kataras/iris/httptest" -) - -func TestCasbinMiddleware(t *testing.T) { - app := newApp() - e := httptest.New(t, app, httptest.Debug(false)) - - type ttcasbin struct { - username string - path string - method string - status int - } - - tt := []ttcasbin{ - {"alice", "/dataset1/resource1", "GET", 200}, - {"alice", "/dataset1/resource1", "POST", 200}, - {"alice", "/dataset1/resource2", "GET", 200}, - {"alice", "/dataset1/resource2", "POST", 404}, - - {"bob", "/dataset2/resource1", "GET", 200}, - {"bob", "/dataset2/resource1", "POST", 200}, - {"bob", "/dataset2/resource1", "DELETE", 200}, - {"bob", "/dataset2/resource2", "GET", 200}, - {"bob", "/dataset2/resource2", "POST", 404}, - {"bob", "/dataset2/resource2", "DELETE", 404}, - - {"bob", "/dataset2/folder1/item1", "GET", 404}, - {"bob", "/dataset2/folder1/item1", "POST", 200}, - {"bob", "/dataset2/folder1/item1", "DELETE", 404}, - {"bob", "/dataset2/folder1/item2", "GET", 404}, - {"bob", "/dataset2/folder1/item2", "POST", 200}, - {"bob", "/dataset2/folder1/item2", "DELETE", 404}, - } - - for _, tt := range tt { - check(e, tt.method, tt.path, tt.username, tt.status) - } -} - -func check(e *httpexpect.Expect, method, path, username string, status int) { - e.Request(method, path).WithBasicAuth(username, "password").Expect().Status(status) -} diff --git a/experimental-handlers/casbin/wrapper/casbinmodel.conf b/experimental-handlers/casbin/wrapper/casbinmodel.conf deleted file mode 100644 index d1b3dbd7..00000000 --- a/experimental-handlers/casbin/wrapper/casbinmodel.conf +++ /dev/null @@ -1,14 +0,0 @@ -[request_definition] -r = sub, obj, act - -[policy_definition] -p = sub, obj, act - -[role_definition] -g = _, _ - -[policy_effect] -e = some(where (p.eft == allow)) - -[matchers] -m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") \ No newline at end of file diff --git a/experimental-handlers/casbin/wrapper/casbinpolicy.csv b/experimental-handlers/casbin/wrapper/casbinpolicy.csv deleted file mode 100644 index 532b7b4a..00000000 --- a/experimental-handlers/casbin/wrapper/casbinpolicy.csv +++ /dev/null @@ -1,7 +0,0 @@ -p, alice, /dataset1/*, GET -p, alice, /dataset1/resource1, POST -p, bob, /dataset2/resource1, * -p, bob, /dataset2/resource2, GET -p, bob, /dataset2/folder1/*, POST -p, dataset1_admin, /dataset1/*, * -g, cathrin, dataset1_admin \ No newline at end of file diff --git a/experimental-handlers/casbin/wrapper/main.go b/experimental-handlers/casbin/wrapper/main.go deleted file mode 100644 index ece88ab4..00000000 --- a/experimental-handlers/casbin/wrapper/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/casbin/casbin" - cm "github.com/iris-contrib/middleware/casbin" -) - -// $ go get github.com/casbin/casbin -// $ go run main.go - -// Enforcer maps the model and the policy for the casbin service, we use this variable on the main_test too. -var Enforcer = casbin.NewEnforcer("casbinmodel.conf", "casbinpolicy.csv") - -func newApp() *iris.Application { - casbinMiddleware := cm.New(Enforcer) - - app := iris.New() - app.WrapRouter(casbinMiddleware.Wrapper()) - - app.Get("/", hi) - - app.Any("/dataset1/{p:path}", hi) // p, dataset1_admin, /dataset1/*, * && p, alice, /dataset1/*, GET - - app.Post("/dataset1/resource1", hi) - - app.Get("/dataset2/resource2", hi) - app.Post("/dataset2/folder1/{p:path}", hi) - - app.Any("/dataset2/resource1", hi) - - return app -} - -func main() { - app := newApp() - app.Run(iris.Addr(":8080")) -} - -func hi(ctx iris.Context) { - ctx.Writef("Hello %s", cm.Username(ctx.Request())) -} diff --git a/experimental-handlers/casbin/wrapper/main_test.go b/experimental-handlers/casbin/wrapper/main_test.go deleted file mode 100644 index 152a8108..00000000 --- a/experimental-handlers/casbin/wrapper/main_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "testing" - - "github.com/iris-contrib/httpexpect" - "github.com/kataras/iris/httptest" -) - -func TestCasbinWrapper(t *testing.T) { - app := newApp() - e := httptest.New(t, app) - - type ttcasbin struct { - username string - path string - method string - status int - } - - tt := []ttcasbin{ - {"alice", "/dataset1/resource1", "GET", 200}, - {"alice", "/dataset1/resource1", "POST", 200}, - {"alice", "/dataset1/resource2", "GET", 200}, - {"alice", "/dataset1/resource2", "POST", 403}, - - {"bob", "/dataset2/resource1", "GET", 200}, - {"bob", "/dataset2/resource1", "POST", 200}, - {"bob", "/dataset2/resource1", "DELETE", 200}, - {"bob", "/dataset2/resource2", "GET", 200}, - {"bob", "/dataset2/resource2", "POST", 403}, - {"bob", "/dataset2/resource2", "DELETE", 403}, - - {"bob", "/dataset2/folder1/item1", "GET", 403}, - {"bob", "/dataset2/folder1/item1", "POST", 200}, - {"bob", "/dataset2/folder1/item1", "DELETE", 403}, - {"bob", "/dataset2/folder1/item2", "GET", 403}, - {"bob", "/dataset2/folder1/item2", "POST", 200}, - {"bob", "/dataset2/folder1/item2", "DELETE", 403}, - } - - for _, tt := range tt { - check(e, tt.method, tt.path, tt.username, tt.status) - } - - ttAdmin := []ttcasbin{ - {"cathrin", "/dataset1/item", "GET", 200}, - {"cathrin", "/dataset1/item", "POST", 200}, - {"cathrin", "/dataset1/item", "DELETE", 200}, - {"cathrin", "/dataset2/item", "GET", 403}, - {"cathrin", "/dataset2/item", "POST", 403}, - {"cathrin", "/dataset2/item", "DELETE", 403}, - } - - for _, tt := range ttAdmin { - check(e, tt.method, tt.path, tt.username, tt.status) - } - - Enforcer.DeleteRolesForUser("cathrin") - - ttAdminDeleted := []ttcasbin{ - {"cathrin", "/dataset1/item", "GET", 403}, - {"cathrin", "/dataset1/item", "POST", 403}, - {"cathrin", "/dataset1/item", "DELETE", 403}, - {"cathrin", "/dataset2/item", "GET", 403}, - {"cathrin", "/dataset2/item", "POST", 403}, - {"cathrin", "/dataset2/item", "DELETE", 403}, - } - - for _, tt := range ttAdminDeleted { - check(e, tt.method, tt.path, tt.username, tt.status) - } - -} - -func check(e *httpexpect.Expect, method, path, username string, status int) { - e.Request(method, path).WithBasicAuth(username, "password").Expect().Status(status) -} diff --git a/experimental-handlers/cloudwatch/simple/main.go b/experimental-handlers/cloudwatch/simple/main.go deleted file mode 100644 index dbe440be..00000000 --- a/experimental-handlers/cloudwatch/simple/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "time" - - "github.com/kataras/iris" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/cloudwatch" - cw "github.com/iris-contrib/middleware/cloudwatch" -) - -// $ go get github.com/aws/aws-sdk-go/... -// $ go run main.go - -func main() { - app := iris.New() - app.Use(cw.New("us-east-1", "test").ServeHTTP) - - app.Get("/", func(ctx iris.Context) { - put := cw.GetPutFunc(ctx) - - put([]*cloudwatch.MetricDatum{ - { - MetricName: aws.String("MyMetric"), - Dimensions: []*cloudwatch.Dimension{ - { - Name: aws.String("ThingOne"), - Value: aws.String("something"), - }, - { - Name: aws.String("ThingTwo"), - Value: aws.String("other"), - }, - }, - Timestamp: aws.Time(time.Now()), - Unit: aws.String("Count"), - Value: aws.Float64(42), - }, - }) - - ctx.StatusCode(iris.StatusOK) - ctx.Text("success!\n") - }) - - // http://localhost:8080 - // should give: NoCredentialProviders - // which is correct, you have to authorize your aws, we asumme that you know how to. - app.Run(iris.Addr(":8080")) -} diff --git a/experimental-handlers/cors/simple/main.go b/experimental-handlers/cors/simple/main.go deleted file mode 100644 index ea8f4e70..00000000 --- a/experimental-handlers/cors/simple/main.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -// go get -u github.com/iris-contrib/middleware/... - -import ( - "github.com/kataras/iris" - - "github.com/iris-contrib/middleware/cors" -) - -func main() { - app := iris.New() - - crs := cors.New(cors.Options{ - AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts. - AllowCredentials: true, - }) - - v1 := app.Party("/api/v1", crs).AllowMethods(iris.MethodOptions) // <- important for the preflight. - { - v1.Get("/home", func(ctx iris.Context) { - ctx.WriteString("Hello from /home") - }) - v1.Get("/about", func(ctx iris.Context) { - ctx.WriteString("Hello from /about") - }) - v1.Post("/send", func(ctx iris.Context) { - ctx.WriteString("sent") - }) - v1.Put("/send", func(ctx iris.Context) { - ctx.WriteString("updated") - }) - v1.Delete("/send", func(ctx iris.Context) { - ctx.WriteString("deleted") - }) - } - - app.Run(iris.Addr("localhost:8080")) -} diff --git a/experimental-handlers/csrf/main.go b/experimental-handlers/csrf/main.go deleted file mode 100644 index 20964ac0..00000000 --- a/experimental-handlers/csrf/main.go +++ /dev/null @@ -1,55 +0,0 @@ -// This middleware provides Cross-Site Request Forgery -// protection. -// -// It securely generates a masked (unique-per-request) token that -// can be embedded in the HTTP response (e.g. form field or HTTP header). -// The original (unmasked) token is stored in the session, which is inaccessible -// by an attacker (provided you are using HTTPS). Subsequent requests are -// expected to include this token, which is compared against the session token. -// Requests that do not provide a matching token are served with a HTTP 403 -// 'Forbidden' error response. -package main - -// $ go get -u github.com/iris-contrib/middleware/... - -import ( - "github.com/kataras/iris" - - "github.com/iris-contrib/middleware/csrf" -) - -func main() { - app := iris.New() - app.RegisterView(iris.HTML("./views", ".html")) - // Note that the authentication key provided should be 32 bytes - // long and persist across application restarts. - protect := csrf.Protect([]byte("9AB0F421E53A477C084477AEA06096F5"), - csrf.Secure(false)) // Defaults to true, but pass `false` while no https (devmode). - - users := app.Party("/user", protect) - { - users.Get("/signup", getSignupForm) - // // POST requests without a valid token will return a HTTP 403 Forbidden. - users.Post("/signup", postSignupForm) - } - - // GET: http://localhost:8080/user/signup - // POST: http://localhost:8080/user/signup - app.Run(iris.Addr(":8080")) -} - -func getSignupForm(ctx iris.Context) { - // views/user/signup.html just needs a {{ .csrfField }} template tag for - // csrf.TemplateField to inject the CSRF token into. Easy! - ctx.ViewData(csrf.TemplateTag, csrf.TemplateField(ctx)) - ctx.View("user/signup.html") - - // We could also retrieve the token directly from csrf.Token(ctx) and - // set it in the request header - ctx.GetHeader("X-CSRF-Token", token) - // This is useful if you're sending JSON to clients or a front-end JavaScript - // framework. -} - -func postSignupForm(ctx iris.Context) { - ctx.Writef("You're welcome mate!") -} diff --git a/experimental-handlers/csrf/views/user/signup.html b/experimental-handlers/csrf/views/user/signup.html deleted file mode 100644 index eea693d6..00000000 --- a/experimental-handlers/csrf/views/user/signup.html +++ /dev/null @@ -1,4 +0,0 @@ -<form method="POST" action="/user/signup"> - {{ .csrfField }} -<button type="submit">Proceed</button> -</form> diff --git a/experimental-handlers/jwt/main.go b/experimental-handlers/jwt/main.go deleted file mode 100644 index 41e5dfee..00000000 --- a/experimental-handlers/jwt/main.go +++ /dev/null @@ -1,46 +0,0 @@ -// iris provides some basic middleware, most for your learning courve. -// You can use any net/http compatible middleware with iris.FromStd wrapper. -// -// JWT net/http video tutorial for golang newcomers: https://www.youtube.com/watch?v=dgJFeqeXVKw -// -// This middleware is the only one cloned from external source: https://github.com/auth0/go-jwt-middleware -// (because it used "context" to define the user but we don't need that so a simple iris.FromStd wouldn't work as expected.) -package main - -// $ go get -u github.com/dgrijalva/jwt-go -// $ go run main.go - -import ( - "github.com/kataras/iris" - - "github.com/dgrijalva/jwt-go" - jwtmiddleware "github.com/iris-contrib/middleware/jwt" -) - -func myHandler(ctx iris.Context) { - user := ctx.Values().Get("jwt").(*jwt.Token) - - ctx.Writef("This is an authenticated request\n") - ctx.Writef("Claim content:\n") - - ctx.Writef("%s", user.Signature) -} - -func main() { - app := iris.New() - - jwtHandler := jwtmiddleware.New(jwtmiddleware.Config{ - ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { - return []byte("My Secret"), nil - }, - // When set, the middleware verifies that tokens are signed with the specific signing algorithm - // If the signing method is not constant the ValidationKeyGetter callback can be used to implement additional checks - // Important to avoid security issues described here: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ - SigningMethod: jwt.SigningMethodHS256, - }) - - app.Use(jwtHandler.Serve) - - app.Get("/ping", myHandler) - app.Run(iris.Addr("localhost:3001")) -} // don't forget to look ../jwt_test.go to seee how to set your own custom claims diff --git a/experimental-handlers/newrelic/simple/main.go b/experimental-handlers/newrelic/simple/main.go deleted file mode 100644 index a4e762a3..00000000 --- a/experimental-handlers/newrelic/simple/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/iris-contrib/middleware/newrelic" -) - -func main() { - app := iris.New() - config := newrelic.Config("APP_SERVER_NAME", "NEWRELIC_LICENSE_KEY") - config.Enabled = true - m, err := newrelic.New(config) - if err != nil { - app.Logger().Fatal(err) - } - app.Use(m.ServeHTTP) - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("success!\n") - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/experimental-handlers/prometheus/simple/main.go b/experimental-handlers/prometheus/simple/main.go deleted file mode 100644 index ff624b14..00000000 --- a/experimental-handlers/prometheus/simple/main.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - "math/rand" - "time" - - "github.com/kataras/iris" - - prometheusMiddleware "github.com/iris-contrib/middleware/prometheus" - - "github.com/prometheus/client_golang/prometheus" -) - -func main() { - app := iris.New() - m := prometheusMiddleware.New("serviceName", 300, 1200, 5000) - - app.Use(m.ServeHTTP) - - app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) { - // error code handlers are not sharing the same middleware as other routes, so we have - // to call them inside their body. - m.ServeHTTP(ctx) - - ctx.Writef("Not Found") - }) - - app.Get("/", func(ctx iris.Context) { - sleep := rand.Intn(4999) + 1 - time.Sleep(time.Duration(sleep) * time.Millisecond) - ctx.Writef("Slept for %d milliseconds", sleep) - }) - - app.Get("/metrics", iris.FromStd(prometheus.Handler())) - - // http://localhost:8080/ - // http://localhost:8080/anotfound - // http://localhost:8080/metrics - app.Run(iris.Addr(":8080")) -} diff --git a/experimental-handlers/secure/simple/main.go b/experimental-handlers/secure/simple/main.go deleted file mode 100644 index 8f021e79..00000000 --- a/experimental-handlers/secure/simple/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/iris-contrib/middleware/secure" -) - -func main() { - s := secure.New(secure.Options{ - AllowedHosts: []string{"ssl.example.com"}, // AllowedHosts is a list of fully qualified domain names that are allowed. Default is empty list, which allows any and all host names. - SSLRedirect: true, // If SSLRedirect is set to true, then only allow HTTPS requests. Default is false. - SSLTemporaryRedirect: false, // If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301). - SSLHost: "ssl.example.com", // SSLHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host. - SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, // SSLProxyHeaders is set of header keys with associated values that would indicate a valid HTTPS request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map. - STSSeconds: 315360000, // STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header. - STSIncludeSubdomains: true, // If STSIncludeSubdomains is set to true, the `includeSubdomains` will be appended to the Strict-Transport-Security header. Default is false. - STSPreload: true, // If STSPreload is set to true, the `preload` flag will be appended to the Strict-Transport-Security header. Default is false. - ForceSTSHeader: false, // STS header is only included when the connection is HTTPS. If you want to force it to always be added, set to true. `IsDevelopment` still overrides this. Default is false. - FrameDeny: true, // If FrameDeny is set to true, adds the X-Frame-Options header with the value of `DENY`. Default is false. - CustomFrameOptionsValue: "SAMEORIGIN", // CustomFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value. This overrides the FrameDeny option. - ContentTypeNosniff: true, // If ContentTypeNosniff is true, adds the X-Content-Type-Options header with the value `nosniff`. Default is false. - BrowserXSSFilter: true, // If BrowserXssFilter is true, adds the X-XSS-Protection header with the value `1; mode=block`. Default is false. - ContentSecurityPolicy: "default-src 'self'", // ContentSecurityPolicy allows the Content-Security-Policy header value to be set with a custom value. Default is "". - PublicKey: `pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubdomains; report-uri="https://www.example.com/hpkp-report"`, // PublicKey implements HPKP to prevent MITM attacks with forged certificates. Default is "". - - IsDevelopment: true, // This will cause the AllowedHosts, SSLRedirect, and STSSeconds/STSIncludeSubdomains options to be ignored during development. When deploying to production, be sure to set this to false. - }) - - app := iris.New() - app.Use(s.Serve) - - app.Get("/home", func(ctx iris.Context) { - ctx.Writef("Hello from /home") - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/experimental-handlers/tollboothic/limit-handler/main.go b/experimental-handlers/tollboothic/limit-handler/main.go deleted file mode 100644 index a7a255b4..00000000 --- a/experimental-handlers/tollboothic/limit-handler/main.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/didip/tollbooth" - "github.com/iris-contrib/middleware/tollboothic" -) - -// $ go get github.com/didip/tollbooth -// $ go run main.go - -func main() { - app := iris.New() - - limiter := tollbooth.NewLimiter(1, nil) - // - // or create a limiter with expirable token buckets - // This setting means: - // create a 1 request/second limiter and - // every token bucket in it will expire 1 hour after it was initially set. - // limiter := tollbooth.NewLimiter(1, &limiter.ExpirableOptions{DefaultExpirationTTL: time.Hour}) - - app.Get("/", tollboothic.LimitHandler(limiter), func(ctx iris.Context) { - ctx.HTML("<b>Hello, world!</b>") - }) - - app.Run(iris.Addr(":8080")) -} - -// Read more at: https://github.com/didip/tollbooth diff --git a/file-server/single-page-application/basic/public/css/main.css b/file-server/basic/assets.system/css/main.css similarity index 100% rename from file-server/single-page-application/basic/public/css/main.css rename to file-server/basic/assets.system/css/main.css diff --git a/file-server/basic/assets.system/test.txt b/file-server/basic/assets.system/test.txt new file mode 100644 index 00000000..1ce52e76 --- /dev/null +++ b/file-server/basic/assets.system/test.txt @@ -0,0 +1 @@ +main_test.go#TestHandleDirDot \ No newline at end of file diff --git a/file-server/basic/assets/app2/app22/just_a_text_no_index.txt b/file-server/basic/assets/app2/app22/just_a_text_no_index.txt new file mode 100644 index 00000000..f1cc1278 --- /dev/null +++ b/file-server/basic/assets/app2/app22/just_a_text_no_index.txt @@ -0,0 +1 @@ +just a text. \ No newline at end of file diff --git a/file-server/basic/assets/app2/app2app3/index.html b/file-server/basic/assets/app2/app2app3/index.html new file mode 100644 index 00000000..750f10ba --- /dev/null +++ b/file-server/basic/assets/app2/app2app3/index.html @@ -0,0 +1 @@ +<h1>Hello App2App3 index</h1> \ No newline at end of file diff --git a/file-server/basic/assets/app2/index.html b/file-server/basic/assets/app2/index.html new file mode 100644 index 00000000..8193d822 --- /dev/null +++ b/file-server/basic/assets/app2/index.html @@ -0,0 +1 @@ +<h1>Hello App2 index</h1> \ No newline at end of file diff --git a/file-server/basic/assets/js/jquery-2.1.1.js b/file-server/basic/assets/js/jquery-2.1.1.js deleted file mode 100644 index 9f7b3d38..00000000 --- a/file-server/basic/assets/js/jquery-2.1.1.js +++ /dev/null @@ -1,9190 +0,0 @@ -/*! - * jQuery JavaScript Library v2.1.1 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-05-01T17:11Z - */ - -(function( global, factory ) { - - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Can't do this because several apps including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// Support: Firefox 18+ -// - -var arr = []; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var support = {}; - - - -var - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - version = "2.1.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android<4.1 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; - }, - - isPlainObject: function( obj ) { - // Not plain objects: - // - Any object or value whose internal [[Class]] property is not "[object Object]" - // - DOM nodes - // - window - if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.constructor && - !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { - return false; - } - - // If the function hasn't returned already, we're confident that - // |obj| is a plain object, created by {} or constructed with new Object - return true; - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - // Support: Android < 4.0, iOS < 6 (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call(obj) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - var script, - indirect = eval; - - code = jQuery.trim( code ); - - if ( code ) { - // If the code includes a valid, prologue position - // strict mode pragma, execute code by injecting a - // script tag into the document. - if ( code.indexOf("use strict") === 1 ) { - script = document.createElement("script"); - script.text = code; - document.head.appendChild( script ).parentNode.removeChild( script ); - } else { - // Otherwise, avoid the DOM node creation, insertion - // and removal by using an indirect global eval - indirect( code ); - } - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); - - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -function isArraylike( obj ) { - var length = obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.nodeType === 1 && length ) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v1.10.19 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-04-18 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }; - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - - context = context || document; - results = results || []; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; - } - - if ( documentIsHTML && !seed ) { - - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== strundefined && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent !== parent.top ) { - // IE11 does not have attachEvent, so all must suffer - if ( parent.addEventListener ) { - parent.addEventListener( "unload", function() { - setDocument(); - }, false ); - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", function() { - setDocument(); - }); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowclip^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome<14 -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = "<a href='#'></a>"; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = "<input/>"; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - - -var rneedsContext = jQuery.expr.match.needsContext; - -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - -var risSimple = /^.[^:#\[\.,]*$/; - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); -}; - -jQuery.fn.extend({ - find: function( selector ) { - var i, - len = this.length, - ret = [], - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -}); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.extend({ - dir: function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }, - - sibling: function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - } -}); - -jQuery.fn.extend({ - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter(function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.unique( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return elem.contentDocument || jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.unique( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -}); -var rnotwhite = (/\S+/g); - - - -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); - - -// The deferred used on DOM ready -var readyList; - -jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; -}; - -jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } -}); - -/** - * The ready event handler and self cleanup method - */ -function completed() { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - jQuery.ready(); -} - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); - - } else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); - } - } - return readyList.promise( obj ); -}; - -// Kick off the DOM ready check even if the user does not -jQuery.ready.promise(); - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - len ? fn( elems[0], key ) : emptyGet; -}; - - -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( owner ) { - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - /* jshint -W018 */ - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - -function Data() { - // Support: Android < 4, - // Old WebKit does not have Object.preventExtensions/freeze method, - // return new empty object instead with no [[set]] accessor - Object.defineProperty( this.cache = {}, 0, { - get: function() { - return {}; - } - }); - - this.expando = jQuery.expando + Math.random(); -} - -Data.uid = 1; -Data.accepts = jQuery.acceptData; - -Data.prototype = { - key: function( owner ) { - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return the key for a frozen object. - if ( !Data.accepts( owner ) ) { - return 0; - } - - var descriptor = {}, - // Check if the owner object already has a cache key - unlock = owner[ this.expando ]; - - // If not, create one - if ( !unlock ) { - unlock = Data.uid++; - - // Secure it in a non-enumerable, non-writable property - try { - descriptor[ this.expando ] = { value: unlock }; - Object.defineProperties( owner, descriptor ); - - // Support: Android < 4 - // Fallback to a less secure definition - } catch ( e ) { - descriptor[ this.expando ] = unlock; - jQuery.extend( owner, descriptor ); - } - } - - // Ensure the cache object - if ( !this.cache[ unlock ] ) { - this.cache[ unlock ] = {}; - } - - return unlock; - }, - set: function( owner, data, value ) { - var prop, - // There may be an unlock assigned to this node, - // if there is no entry for this "owner", create one inline - // and set the unlock as though an owner entry had always existed - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - // Handle: [ owner, key, value ] args - if ( typeof data === "string" ) { - cache[ data ] = value; - - // Handle: [ owner, { properties } ] args - } else { - // Fresh assignments by object are shallow copied - if ( jQuery.isEmptyObject( cache ) ) { - jQuery.extend( this.cache[ unlock ], data ); - // Otherwise, copy the properties one-by-one to the cache object - } else { - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } - } - } - return cache; - }, - get: function( owner, key ) { - // Either a valid cache is found, or will be created. - // New caches will be created and the unlock returned, - // allowing direct access to the newly created - // empty data object. A valid owner object must be provided. - var cache = this.cache[ this.key( owner ) ]; - - return key === undefined ? - cache : cache[ key ]; - }, - access: function( owner, key, value ) { - var stored; - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ((key && typeof key === "string") && value === undefined) ) { - - stored = this.get( owner, key ); - - return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase(key) ); - } - - // [*]When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, name, camel, - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - if ( key === undefined ) { - this.cache[ unlock ] = {}; - - } else { - // Support array or space separated string of keys - if ( jQuery.isArray( key ) ) { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = key.concat( key.map( jQuery.camelCase ) ); - } else { - camel = jQuery.camelCase( key ); - // Try the string as a key before any manipulation - if ( key in cache ) { - name = [ key, camel ]; - } else { - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - name = camel; - name = name in cache ? - [ name ] : ( name.match( rnotwhite ) || [] ); - } - } - - i = name.length; - while ( i-- ) { - delete cache[ name[ i ] ]; - } - } - }, - hasData: function( owner ) { - return !jQuery.isEmptyObject( - this.cache[ owner[ this.expando ] ] || {} - ); - }, - discard: function( owner ) { - if ( owner[ this.expando ] ) { - delete this.cache[ owner[ this.expando ] ]; - } - } -}; -var data_priv = new Data(); - -var data_user = new Data(); - - - -/* - Implementation Summary - - 1. Enforce API surface and semantic compatibility with 1.9.x branch - 2. Improve the module's maintainability by reducing the storage - paths to a single mechanism. - 3. Use the same single mechanism to support "private" and "user" data. - 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) - 5. Avoid exposing implementation details on user objects (eg. expando properties) - 6. Provide a clear path for implementation upgrade to WeakMap in 2014 -*/ -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - data_user.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend({ - hasData: function( elem ) { - return data_user.hasData( elem ) || data_priv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return data_user.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - data_user.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to data_priv methods, these can be deprecated. - _data: function( elem, name, data ) { - return data_priv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - data_priv.remove( elem, name ); - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = data_user.get( elem ); - - if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - data_priv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - data_user.set( this, key ); - }); - } - - return access( this, function( value ) { - var data, - camelKey = jQuery.camelCase( key ); - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - // Attempt to get data from the cache - // with the key as-is - data = data_user.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to get data from the cache - // with the key camelized - data = data_user.get( elem, camelKey ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, camelKey, undefined ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each(function() { - // First, attempt to store a copy or reference of any - // data that might've been store with a camelCased key. - var data = data_user.get( this, camelKey ); - - // For HTML5 data-* attribute interop, we have to - // store property names with dashes in a camelCase form. - // This might not apply to all properties...* - data_user.set( this, camelKey, value ); - - // *... In the case of properties that might _actually_ - // have dashes, we need to also store a copy of that - // unchanged property. - if ( key.indexOf("-") !== -1 && data !== undefined ) { - data_user.set( this, key, value ); - } - }); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each(function() { - data_user.remove( this, key ); - }); - } -}); - - -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = data_priv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = data_priv.access( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return data_priv.get( elem, key ) || data_priv.access( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - data_priv.remove( elem, [ type + "queue", key ] ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = data_priv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); - }; - -var rcheckableType = (/^(?:checkbox|radio)$/i); - - - -(function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // #11217 - WebKit loses check when the name is after the checked attribute - // Support: Windows Web Apps (WWA) - // `name` and `type` need .setAttribute for WWA - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE9-IE11+ - div.innerHTML = "<textarea>x</textarea>"; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -})(); -var strundefined = typeof undefined; - - - -support.focusinBubbles = "onfocusin" in window; - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.hasData( elem ) && data_priv.get( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - data_priv.remove( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG <use> instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } - - return handlerQueue; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: Cordova 2.5 (WebKit) (#13255) - // All events should have a target; Cordova deviceready doesn't - if ( !event.target ) { - event.target = document; - } - - // Support: Safari 6.0+, Chrome < 28 - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } -}; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && e.preventDefault ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && e.stopPropagation ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -// Support: Chrome 15+ -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// Create "bubbling" focus and blur events -// Support: Firefox, Chrome, Safari -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - data_priv.remove( doc, fix ); - - } else { - data_priv.access( doc, fix, attaches ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -}); - - -var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /^$|\/(?:java|ecma)script/i, - rscriptTypeMasked = /^true\/(.*)/, - rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - - // Support: IE 9 - option: [ 1, "<select multiple='multiple'>", "</select>" ], - - thead: [ 1, "<table>", "</table>" ], - col: [ 2, "<table><colgroup>", "</colgroup></table>" ], - tr: [ 2, "<table><tbody>", "</tbody></table>" ], - td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], - - _default: [ 0, "", "" ] - }; - -// Support: IE 9 -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: 1.x compatibility -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute("type"); - } - - return elem; -} - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - data_priv.set( - elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) - ); - } -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( data_priv.hasData( src ) ) { - pdataOld = data_priv.access( src ); - pdataCur = data_priv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( data_user.hasData( src ) ) { - udataOld = data_user.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - data_user.set( dest, udataCur ); - } -} - -function getAll( context, tag ) { - var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : - context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; -} - -// Support: IE >= 9 -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Support: IE >= 9 - // Fix Cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - buildFragment: function( elems, context, scripts, selection ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Fixes #12346 - // Support: Webkit, IE - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - }, - - cleanData: function( elems ) { - var data, elem, type, key, - special = jQuery.event.special, - i = 0; - - for ( ; (elem = elems[ i ]) !== undefined; i++ ) { - if ( jQuery.acceptData( elem ) ) { - key = elem[ data_priv.expando ]; - - if ( key && (data = data_priv.cache[ key ]) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - if ( data_priv.cache[ key ] ) { - // Discard any remaining `private` data - delete data_priv.cache[ key ]; - } - } - } - // Discard any remaining `user` data - delete data_user.cache[ elem[ data_user.expando ] ]; - } - } -}); - -jQuery.fn.extend({ - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each(function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - }); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1></$2>" ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var arg = arguments[ 0 ]; - - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; - - jQuery.cleanData( getAll( this ) ); - - if ( arg ) { - arg.replaceChild( elem, this ); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - self.domManip( args, callback ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } - } - } - } - - return this; - } -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: QtWebKit - // .get() because push.apply(_, arraylike) throws - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - - -var iframe, - elemdisplay = {}; - -/** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ -// Called only from within defaultDisplay -function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? - - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; -} - -/** - * Try to determine the default display value of an element - * @param {String} nodeName - */ -function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); - - // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse - doc = iframe[ 0 ].contentDocument; - - // Support: IE - doc.write(); - doc.close(); - - display = actualDisplay( nodeName, doc ); - iframe.detach(); - } - - // Store the correct default display - elemdisplay[ nodeName ] = display; - } - - return display; -} -var rmargin = (/^margin/); - -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); - }; - - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - style = elem.style; - - computed = computed || getStyles( elem ); - - // Support: IE9 - // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - } - - if ( computed ) { - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // Support: iOS < 6 - // A tribute to the "awesome hack by Dean Edwards" - // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - // Support: IE - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - // Hook not needed (or it's not possible to use it due to missing dependency), - // remove it. - // Since there are no other hooks for marginRight, remove the whole object. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - - return (this.get = hookFn).apply( this, arguments ); - } - }; -} - - -(function() { - var pixelPositionVal, boxSizingReliableVal, - docElem = document.documentElement, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - if ( !div.style ) { - return; - } - - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" + - "position:absolute"; - container.appendChild( div ); - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computePixelPositionAndBoxSizingReliable() { - div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + - "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + - "border:1px;padding:1px;width:4px;position:absolute"; - div.innerHTML = ""; - docElem.appendChild( container ); - - var divStyle = window.getComputedStyle( div, null ); - pixelPositionVal = divStyle.top !== "1%"; - boxSizingReliableVal = divStyle.width === "4px"; - - docElem.removeChild( container ); - } - - // Support: node.js jsdom - // Don't assume that getComputedStyle is a property of the global object - if ( window.getComputedStyle ) { - jQuery.extend( support, { - pixelPosition: function() { - // This test is executed only once but we still do memoizing - // since we can use the boxSizingReliable pre-computing. - // No need to check if the test was already performed, though. - computePixelPositionAndBoxSizingReliable(); - return pixelPositionVal; - }, - boxSizingReliable: function() { - if ( boxSizingReliableVal == null ) { - computePixelPositionAndBoxSizingReliable(); - } - return boxSizingReliableVal; - }, - reliableMarginRight: function() { - // Support: Android 2.3 - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. (#3333) - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // This support function is only executed once so no memoizing is needed. - var ret, - marginDiv = div.appendChild( document.createElement( "div" ) ); - - // Reset CSS: box-sizing; display; margin; border; padding - marginDiv.style.cssText = div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - docElem.appendChild( container ); - - ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight ); - - docElem.removeChild( container ); - - return ret; - } - }); - } -})(); - - -// A method for quickly swapping in/out CSS properties to get correct calculations. -jQuery.swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), - rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name[0].toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); - } - - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } else { - // at this point, extra isn't content, so add padding - val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var valueIsBorderBox = true, - val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name, styles ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && - ( support.boxSizingReliable() || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles - ) - ) + "px"; -} - -function showHide( elements, show ) { - var display, elem, hidden, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - values[ index ] = data_priv.get( elem, "olddisplay" ); - display = elem.style.display; - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) ); - } - } else { - hidden = isHidden( elem ); - - if ( display !== "none" || !hidden ) { - data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": "cssFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set. See: #7116 - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, - // but it would mean to define eight (for every problematic property) identical functions - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - style[ name ] = value; - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - } -}); - -jQuery.each([ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? - jQuery.swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - }) : - getWidthOrHeight( elem, name, extra ); - } - }, - - set: function( elem, value, extra ) { - var styles = extra && getStyles( elem ); - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - styles - ) : 0 - ); - } - }; -}); - -// Support: Android 2.3 -jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, - function( elem, computed ) { - if ( computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, - curCSS, [ elem, "marginRight" ] ); - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each({ - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -}); - -jQuery.fn.extend({ - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( jQuery.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each(function() { - if ( isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - if ( tween.elem[ tween.prop ] != null && - (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { - return tween.elem[ tween.prop ]; - } - - // passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE9 -// Panic based approach to setting things on disconnected nodes - -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - } -}; - -jQuery.fx = Tween.prototype.init; - -// Back Compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), - rrun = /queueHooks$/, - animationPrefilters = [ defaultPrefilter ], - tweeners = { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ), - target = tween.cur(), - parts = rfxnum.exec( value ), - unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && - rfxnum.exec( jQuery.css( tween.elem, prop ) ), - scale = 1, - maxIterations = 20; - - if ( start && start[ 3 ] !== unit ) { - // Trust units reported by jQuery.css - unit = unit || start[ 3 ]; - - // Make sure we update the tween properties later on - parts = parts || []; - - // Iteratively approximate from a nonzero starting point - start = +target || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } - - // Update tween properties - if ( parts ) { - start = tween.start = +start || +target || 0; - tween.unit = unit; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[ 1 ] ? - start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : - +parts[ 2 ]; - } - - return tween; - } ] - }; - -// Animations created synchronously will run synchronously -function createFxNow() { - setTimeout(function() { - fxNow = undefined; - }); - return ( fxNow = jQuery.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4 ; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( (tween = collection[ index ].call( animation, prop, value )) ) { - - // we're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - /* jshint validthis: true */ - var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHidden( elem ), - dataShow = data_priv.get( elem, "fxshow" ); - - // handle queue: false promises - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function() { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE9-10 do not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - display = jQuery.css( elem, "display" ); - - // Test default display if display is currently "none" - checkDisplay = display === "none" ? - data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; - - if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { - style.display = "inline-block"; - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always(function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - }); - } - - // show/hide pass - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.exec( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - - // Any non-fx value stops us from restoring the original display value - } else { - display = undefined; - } - } - - if ( !jQuery.isEmptyObject( orig ) ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = data_priv.access( elem, "fxshow", {} ); - } - - // store state if its toggle - enables .stop().toggle() to "reverse" - if ( toggle ) { - dataShow.hidden = !hidden; - } - if ( hidden ) { - jQuery( elem ).show(); - } else { - anim.done(function() { - jQuery( elem ).hide(); - }); - } - anim.done(function() { - var prop; - - data_priv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( prop in orig ) { - tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - - // If this is a noop like .hide().hide(), restore an overwritten display value - } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { - style.display = display; - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( jQuery.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always( function() { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ]); - - if ( percent < 1 && length ) { - return remaining; - } else { - deferred.resolveWith( elem, [ animation ] ); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { specialEasing: {} }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // resolve when we played the last frame - // otherwise, reject - if ( gotoEnd ) { - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - }), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length ; index++ ) { - result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( jQuery.isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - }) - ); - - // attach callbacks from options - return animation.progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweener: function( props, callback ) { - if ( jQuery.isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length ; index++ ) { - prop = props[ index ]; - tweeners[ prop ] = tweeners[ prop ] || []; - tweeners[ prop ].unshift( callback ); - } - }, - - prefilter: function( callback, prepend ) { - if ( prepend ) { - animationPrefilters.unshift( callback ); - } else { - animationPrefilters.push( callback ); - } - } -}); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - jQuery.isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( jQuery.isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend({ - fadeTo: function( speed, to, easing, callback ) { - - // show any hidden elements after setting opacity to 0 - return this.filter( isHidden ).css( "opacity", 0 ).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || data_priv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each(function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = data_priv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - }); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each(function() { - var index, - data = data_priv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // enable finishing flag on private data - data.finish = true; - - // empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // turn off finishing flag - delete data.finish; - }); - } -}); - -jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -}); - -// Generate shortcuts for custom animations -jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -}); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = jQuery.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - // Checks the timer has not already been removed - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - if ( timer() ) { - jQuery.fx.start(); - } else { - jQuery.timers.pop(); - } -}; - -jQuery.fx.interval = 13; - -jQuery.fx.start = function() { - if ( !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } -}; - -jQuery.fx.stop = function() { - clearInterval( timerId ); - timerId = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); -}; - - -(function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: iOS 5.1, Android 4.x, Android 2.3 - // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) - support.checkOn = input.value !== ""; - - // Must access the parent to make an option select properly - // Support: IE9, IE10 - support.optSelected = opt.selected; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Check if an input maintains its value after becoming a radio - // Support: IE9, IE10 - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -})(); - - -var nodeHook, boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend({ - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - } -}); - -jQuery.extend({ - attr: function( elem, name, value ) { - var hooks, ret, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === strundefined ) { - return jQuery.prop( elem, name, value ); - } - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - - } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var name, propName, - i = 0, - attrNames = value && value.match( rnotwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { - propName = jQuery.propFix[ name ] || name; - - // Boolean attributes get special treatment (#10870) - if ( jQuery.expr.match.bool.test( name ) ) { - // Set corresponding property to false - elem[ propName ] = false; - } - - elem.removeAttribute( name ); - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - jQuery.nodeName( elem, "input" ) ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - } -}); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle; - if ( !isXML ) { - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ name ]; - attrHandle[ name ] = ret; - ret = getter( elem, name, isXML ) != null ? - name.toLowerCase() : - null; - attrHandle[ name ] = handle; - } - return ret; - }; -}); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i; - -jQuery.fn.extend({ - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each(function() { - delete this[ jQuery.propFix[ name ] || name ]; - }); - } -}); - -jQuery.extend({ - propFix: { - "for": "htmlFor", - "class": "className" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? - ret : - ( elem[ name ] = value ); - - } else { - return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? - ret : - elem[ name ]; - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? - elem.tabIndex : - -1; - } - } - } -}); - -// Support: IE9+ -// Selectedness for an option in an optgroup can be inaccurate -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - } - }; -} - -jQuery.each([ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -}); - - - - -var rclass = /[\t\r\n\f]/g; - -jQuery.fn.extend({ - addClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call( this, j, this.className ) ); - }); - } - - if ( proceed ) { - // The disjunction here is for better compressibility (see removeClass) - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - " " - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = jQuery.trim( cur ); - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = arguments.length === 0 || typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call( this, j, this.className ) ); - }); - } - if ( proceed ) { - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - "" - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = value ? jQuery.trim( cur ) : ""; - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value; - - if ( typeof stateVal === "boolean" && type === "string" ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - classNames = value.match( rnotwhite ) || []; - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( type === strundefined || type === "boolean" ) { - if ( this.className ) { - // store className if set - data_priv.set( this, "__className__", this.className ); - } - - // If the element has a class name or if we're passed "false", - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - } -}); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend({ - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - // Support: IE10-11+ - // option.text throws exceptions (#14686, #14858) - jQuery.trim( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one" || index < 0, - values = one ? null : [], - max = one ? index + 1 : options.length, - i = index < 0 ? - max : - one ? index : 0; - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // IE6-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - // Don't return options that are disabled or in a disabled optgroup - ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && - ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) { - optionSet = true; - } - } - - // force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -}); - -// Radios and checkboxes getter/setter -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - // Support: Webkit - // "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - }; - } -}); - - - - -// Return jQuery for attributes-only inclusion - - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; -}); - -jQuery.fn.extend({ - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - } -}); - - -var nonce = jQuery.now(); - -var rquery = (/\?/); - - - -// Support: Android 2.3 -// Workaround failure to string-cast null input -jQuery.parseJSON = function( data ) { - return JSON.parse( data + "" ); -}; - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE9 - try { - tmp = new DOMParser(); - xml = tmp.parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rts = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat("*"); - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set -try { - ajaxLocation = location.href; -} catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; -} - -// Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - while ( (dataType = dataTypes[i++]) ) { - // Prepend if requested - if ( dataType[0] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); - - // Otherwise append - } else { - (structure[ dataType ] = structure[ dataType ] || []).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - }); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s[ "throws" ] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend({ - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: ajaxLocation, - type: "GET", - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - // URL without anti-cache param - cacheURL, - // Response headers - responseHeadersString, - responseHeaders, - // timeout handle - timeoutTimer, - // Cross-domain detection vars - parts, - // To know if global events are to be dispatched - fireGlobals, - // Loop variable - i, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks("once memory"), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( (match = rheaders.exec( responseHeadersString )) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - var lname = name.toLowerCase(); - if ( !state ) { - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( state < 2 ) { - for ( code in map ) { - // Lazy-add the new callback in a way that preserves old ones - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } else { - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ).complete = completeDeferred.add; - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) - .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ); - s.crossDomain = !!( parts && - ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || - ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== - ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) - ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger("ajaxStart"); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - cacheURL = s.url; - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add anti-cache in url if needed - if ( s.cache === false ) { - s.url = rts.test( cacheURL ) ? - - // If there is already a '_' parameter, set its value - cacheURL.replace( rts, "$1_=" + nonce++ ) : - - // Otherwise add one to the end - cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; - } - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout(function() { - jqXHR.abort("timeout"); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch ( e ) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader("etag"); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger("ajaxStop"); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - url: url, - type: method, - dataType: type, - data: data, - success: callback - }); - }; -}); - -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -}); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax({ - url: url, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); -}; - - -jQuery.fn.extend({ - wrapAll: function( html ) { - var wrap; - - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapAll( html.call(this, i) ); - }); - } - - if ( this[ 0 ] ) { - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function( i ) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - } -}); - - -jQuery.expr.filters.hidden = function( elem ) { - // Support: Opera <= 12.12 - // Opera reports offsetWidths and offsetHeights less than zero on some elements - return elem.offsetWidth <= 0 && elem.offsetHeight <= 0; -}; -jQuery.expr.filters.visible = function( elem ) { - return !jQuery.expr.filters.hidden( elem ); -}; - - - - -var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( jQuery.isArray( obj ) ) { - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - // Item is non-scalar (array or object), encode its numeric index. - buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); - } - }); - - } else if ( !traditional && jQuery.type( obj ) === "object" ) { - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, value ) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); - s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if ( traditional === undefined ) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ).replace( r20, "+" ); -}; - -jQuery.fn.extend({ - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map(function() { - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - }) - .filter(function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - }) - .map(function( i, elem ) { - var val = jQuery( this ).val(); - - return val == null ? - null : - jQuery.isArray( val ) ? - jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }) : - { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }).get(); - } -}); - - -jQuery.ajaxSettings.xhr = function() { - try { - return new XMLHttpRequest(); - } catch( e ) {} -}; - -var xhrId = 0, - xhrCallbacks = {}, - xhrSuccessStatus = { - // file protocol always yields status code 0, assume 200 - 0: 200, - // Support: IE9 - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -// Support: IE9 -// Open requests must be manually aborted on unload (#5280) -if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ](); - } - }); -} - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport(function( options ) { - var callback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(), - id = ++xhrId; - - xhr.open( options.type, options.url, options.async, options.username, options.password ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers["X-Requested-With"] ) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - delete xhrCallbacks[ id ]; - callback = xhr.onload = xhr.onerror = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - complete( - // file: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - // Support: IE9 - // Accessing binary-data responseText throws an exception - // (#11426) - typeof xhr.responseText === "string" ? { - text: xhr.responseText - } : undefined, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - xhr.onerror = callback("error"); - - // Create the abort callback - callback = xhrCallbacks[ id ] = callback("abort"); - - try { - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -// Install script dataType -jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /(?:java|ecma)script/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -}); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -}); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery("<script>").prop({ - async: true, - charset: s.scriptCharset, - src: s.url - }).on( - "load error", - callback = function( evt ) { - script.remove(); - callback = null; - if ( evt ) { - complete( evt.type === "error" ? 404 : 200, evt.type ); - } - } - ); - document.head.appendChild( script[ 0 ] ); - }, - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -var oldCallbacks = [], - rjsonp = /(=)\?(?=&|$)|\?\?/; - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? - "url" : - typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if ( jsonProp ) { - s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); - } else if ( s.jsonp !== false ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - overwritten = window[ callbackName ]; - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); - - - - -// data: string of html -// context (optional): If specified, the fragment will be created in this context, defaults to document -// keepScripts (optional): If true, will include scripts passed in the html string -jQuery.parseHTML = function( data, context, keepScripts ) { - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec( data ), - scripts = !keepScripts && []; - - // Single tag - if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ); - - if ( scripts && scripts.length ) { - jQuery( scripts ).remove(); - } - - return jQuery.merge( [], parsed.childNodes ); -}; - - -// Keep a copy of the old load method -var _load = jQuery.fn.load; - -/** - * Load a url into a page - */ -jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - var selector, type, response, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = jQuery.trim( url.slice( off ) ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // If we have elements to modify, make the request - if ( self.length > 0 ) { - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - self.html( selector ? - - // If a selector was specified, locate the right elements in a dummy div - // Exclude scripts to avoid IE 'Permission Denied' errors - jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : - - // Otherwise use the full result - responseText ); - - }).complete( callback && function( jqXHR, status ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - }); - } - - return this; -}; - - - - -jQuery.expr.filters.animated = function( elem ) { - return jQuery.grep(jQuery.timers, function( fn ) { - return elem === fn.elem; - }).length; -}; - - - - -var docElem = window.document.documentElement; - -/** - * Gets a window from an element - */ -function getWindow( elem ) { - return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; -} - -jQuery.offset = { - setOffset: function( elem, options, i ) { - var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, - position = jQuery.css( elem, "position" ), - curElem = jQuery( elem ), - props = {}; - - // Set position first, in-case top/left are set even on static elem - if ( position === "static" ) { - elem.style.position = "relative"; - } - - curOffset = curElem.offset(); - curCSSTop = jQuery.css( elem, "top" ); - curCSSLeft = jQuery.css( elem, "left" ); - calculatePosition = ( position === "absolute" || position === "fixed" ) && - ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; - - // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if ( calculatePosition ) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - - } else { - curTop = parseFloat( curCSSTop ) || 0; - curLeft = parseFloat( curCSSLeft ) || 0; - } - - if ( jQuery.isFunction( options ) ) { - options = options.call( elem, i, curOffset ); - } - - if ( options.top != null ) { - props.top = ( options.top - curOffset.top ) + curTop; - } - if ( options.left != null ) { - props.left = ( options.left - curOffset.left ) + curLeft; - } - - if ( "using" in options ) { - options.using.call( elem, props ); - - } else { - curElem.css( props ); - } - } -}; - -jQuery.fn.extend({ - offset: function( options ) { - if ( arguments.length ) { - return options === undefined ? - this : - this.each(function( i ) { - jQuery.offset.setOffset( this, options, i ); - }); - } - - var docElem, win, - elem = this[ 0 ], - box = { top: 0, left: 0 }, - doc = elem && elem.ownerDocument; - - if ( !doc ) { - return; - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if ( !jQuery.contains( docElem, elem ) ) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== strundefined ) { - box = elem.getBoundingClientRect(); - } - win = getWindow( doc ); - return { - top: box.top + win.pageYOffset - docElem.clientTop, - left: box.left + win.pageXOffset - docElem.clientLeft - }; - }, - - position: function() { - if ( !this[ 0 ] ) { - return; - } - - var offsetParent, offset, - elem = this[ 0 ], - parentOffset = { top: 0, left: 0 }; - - // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent - if ( jQuery.css( elem, "position" ) === "fixed" ) { - // We assume that getBoundingClientRect is available when computed position is fixed - offset = elem.getBoundingClientRect(); - - } else { - // Get *real* offsetParent - offsetParent = this.offsetParent(); - - // Get correct offsets - offset = this.offset(); - if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { - parentOffset = offsetParent.offset(); - } - - // Add offsetParent borders - parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); - parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); - } - - // Subtract parent offsets and element margins - return { - top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), - left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) - }; - }, - - offsetParent: function() { - return this.map(function() { - var offsetParent = this.offsetParent || docElem; - - while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { - offsetParent = offsetParent.offsetParent; - } - - return offsetParent || docElem; - }); - } -}); - -// Create scrollLeft and scrollTop methods -jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { - var top = "pageYOffset" === prop; - - jQuery.fn[ method ] = function( val ) { - return access( this, function( elem, method, val ) { - var win = getWindow( elem ); - - if ( val === undefined ) { - return win ? win[ prop ] : elem[ method ]; - } - - if ( win ) { - win.scrollTo( - !top ? val : window.pageXOffset, - top ? val : window.pageYOffset - ); - - } else { - elem[ method ] = val; - } - }, method, val, arguments.length, null ); - }; -}); - -// Add the top/left cssHooks using jQuery.fn.position -// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 -// getComputedStyle returns percent when specified for top/left/bottom/right -// rather than make the css module depend on the offset module, we just check for it here -jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, - function( elem, computed ) { - if ( computed ) { - computed = curCSS( elem, prop ); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( computed ) ? - jQuery( elem ).position()[ prop ] + "px" : - computed; - } - } - ); -}); - - -// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods -jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { - // margin is only for outerHeight, outerWidth - jQuery.fn[ funcName ] = function( margin, value ) { - var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), - extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); - - return access( this, function( elem, type, value ) { - var doc; - - if ( jQuery.isWindow( elem ) ) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement[ "client" + name ]; - } - - // Get document width or height - if ( elem.nodeType === 9 ) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], - // whichever is greatest - return Math.max( - elem.body[ "scroll" + name ], doc[ "scroll" + name ], - elem.body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, extra ) : - - // Set width or height on the element - jQuery.style( elem, type, value, extra ); - }, type, chainable ? margin : undefined, chainable, null ); - }; - }); -}); - - -// The number of elements contained in the matched element set -jQuery.fn.size = function() { - return this.length; -}; - -jQuery.fn.andSelf = jQuery.fn.addBack; - - - - -// Register as a named AMD module, since jQuery can be concatenated with other -// files that may use define, but not via a proper concatenation script that -// understands anonymous AMD modules. A named AMD is safest and most robust -// way to register. Lowercase jquery is used because AMD module names are -// derived from file names, and jQuery is normally delivered in a lowercase -// file name. Do this after creating the global so that if an AMD module wants -// to call noConflict to hide this version of jQuery, it will work. - -// Note that for maximum portability, libraries that are not jQuery should -// declare themselves as anonymous modules, and avoid setting a global if an -// AMD loader is present. jQuery is a special case. For more information, see -// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon - -if ( typeof define === "function" && define.amd ) { - define( "jquery", [], function() { - return jQuery; - }); -} - - - - -var - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$; - -jQuery.noConflict = function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; -}; - -// Expose jQuery and $ identifiers, even in -// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) -// and CommonJS for browser emulators (#13566) -if ( typeof noGlobal === strundefined ) { - window.jQuery = window.$ = jQuery; -} - - - - -return jQuery; - -})); diff --git a/file-server/basic/assets/js/main.js b/file-server/basic/assets/js/main.js new file mode 100644 index 00000000..07f93514 --- /dev/null +++ b/file-server/basic/assets/js/main.js @@ -0,0 +1 @@ +console.log("example"); \ No newline at end of file diff --git a/file-server/basic/main.go b/file-server/basic/main.go index 09b4faf8..032538e1 100644 --- a/file-server/basic/main.go +++ b/file-server/basic/main.go @@ -1,41 +1,68 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) -func main() { +func newApp() *iris.Application { app := iris.New() app.Favicon("./assets/favicon.ico") - // enable gzip, optionally: - // if used before the `StaticXXX` handlers then - // the content byte range feature is gone. - // recommend: turn off for large files especially - // when server has low memory, - // turn on for medium-sized files - // or for large-sized files if they are zipped already, - // i.e "zippedDir/file.gz" - // - // app.Use(iris.Gzip) - // first parameter is the request path // second is the system directory // - // app.StaticWeb("/css", "./assets/css") - // app.StaticWeb("/js", "./assets/js") - // - app.StaticWeb("/static", "./assets") + // app.HandleDir("/css", iris.Dir("./assets/css")) + // app.HandleDir("/js", iris.Dir("./assets/js")) - // http://localhost:8080/static/css/main.css - // http://localhost:8080/static/js/jquery-2.1.1.js - // http://localhost:8080/static/favicon.ico - app.Run(iris.Addr(":8080")) + v1 := app.Party("/v1") + v1.HandleDir("/static", iris.Dir("./assets"), iris.DirOptions{ + // Defaults to "/index.html", if request path is ending with **/*/$IndexName + // then it redirects to **/*(/) which another handler is handling it, + // that another handler, called index handler, is auto-registered by the framework + // if end developer does not managed to handle it by hand. + IndexName: "/index.html", + // When files should served under compression. + Compress: false, + // List the files inside the current requested directory if `IndexName` not found. + ShowList: false, + // When ShowList is true you can configure if you want to show or hide hidden files. + ShowHidden: false, + Cache: iris.DirCacheOptions{ + // enable in-memory cache and pre-compress the files. + Enable: true, + // ignore image types (and pdf). + CompressIgnore: iris.MatchImagesAssets, + // do not compress files smaller than size. + CompressMinSize: 300, + // available encodings that will be negotiated with client's needs. + Encodings: []string{"gzip", "br" /* you can also add: deflate, snappy */}, + }, + DirList: iris.DirListRich(), + // If `ShowList` is true then this function will be used instead of the default + // one to show the list of files of a current requested directory(dir). + // DirList: func(ctx iris.Context, dirName string, dir http.File) error { ... } + // + // Optional validator that loops through each requested resource. + // AssetValidator: func(ctx iris.Context, name string) bool { ... } + }) - // Note: - // Routing doesn't allows something .StaticWeb("/", "./assets") - // - // To see how you can wrap the router in order to achieve - // wildcard on root path, see "single-page-application". + // You can also register any index handler manually, order of registration does not matter: + // v1.Get("/static", [...custom middleware...], func(ctx iris.Context) { + // [...custom code...] + // ctx.ServeFile("./assets/index.html") + // }) + + // http://localhost:8080/v1/static + // http://localhost:8080/v1/static/css/main.css + // http://localhost:8080/v1/static/js/jquery-2.1.1.js + // http://localhost:8080/v1/static/favicon.ico + return app +} + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + + app.Listen(":8080") } diff --git a/file-server/basic/main_test.go b/file-server/basic/main_test.go new file mode 100644 index 00000000..cdd6b46b --- /dev/null +++ b/file-server/basic/main_test.go @@ -0,0 +1,114 @@ +package main + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +type resource string + +func (r resource) contentType() string { + switch filepath.Ext(r.String()) { + case ".js": + return "text/javascript" + case ".css": + return "text/css" + case ".ico": + return "image/x-icon" + case ".html", "": + return "text/html" + default: + return "text/plain" + } +} + +func (r resource) String() string { + return string(r) +} + +func (r resource) strip(strip string) string { + s := r.String() + return strings.TrimPrefix(s, strip) +} + +func (r resource) loadFromBase(dir string, strip string) string { + filename := r.String() + + filename = r.strip(strip) + if filepath.Ext(filename) == "" { + // root /. + filename = filename + "/index.html" + } + + fullpath := filepath.Join(dir, filename) + + b, err := os.ReadFile(fullpath) + if err != nil { + panic(fullpath + " failed with error: " + err.Error()) + } + + result := string(b) + + return result +} + +func TestFileServerBasic(t *testing.T) { + urls := []resource{ + "/v1/static/css/main.css", + "/v1/static/js/main.js", + "/v1/static/favicon.ico", + "/v1/static/app2", + "/v1/static/app2/app2app3", + "/v1/static", + } + + app := newApp() + // route := app.GetRouteReadOnly("GET/{file:path}") + // if route == nil { + // app.Logger().Fatalf("expected a route to serve files") + // } + + // if expected, got := "./assets", route.StaticDir(); expected != got { + // app.Logger().Fatalf("expected route's static directory to be: '%s' but got: '%s'", expected, got) + // } + + // if !route.StaticDirContainsIndex() { + // app.Logger().Fatalf("epxected ./assets to contain an %s file", "/index.html") + // } + + e := httptest.New(t, app) + for _, u := range urls { + url := u.String() + contents := u.loadFromBase("./assets", "/v1/static") + + e.GET(url).Expect(). + Status(httptest.StatusOK). + ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). + Body().IsEqual(contents) + } +} + +// Tests subdomain + request path and system directory with a name that contains a dot(.) +func TestHandleDirDot(t *testing.T) { + urls := []resource{ + "/v1/assets.system/css/main.css", + } + app := newApp() + app.Subdomain("test").Party("/v1").HandleDir("/assets.system", iris.Dir("./assets.system")) + + e := httptest.New(t, app, httptest.URL("http://test.example.com")) + for _, u := range urls { + url := u.String() + contents := u.loadFromBase("./assets.system", "/v1/assets.system") + + e.GET(url).Expect(). + Status(httptest.StatusOK). + ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). + Body().IsEqual(contents) + } +} diff --git a/file-server/embedding-files-into-app-bindata/assets/css/main.css b/file-server/embedding-files-into-app-bindata/assets/css/main.css new file mode 100644 index 00000000..9749e5ad --- /dev/null +++ b/file-server/embedding-files-into-app-bindata/assets/css/main.css @@ -0,0 +1,5 @@ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} \ No newline at end of file diff --git a/structuring/bootstrap/public/favicon.ico b/file-server/embedding-files-into-app-bindata/assets/favicon.ico similarity index 100% rename from structuring/bootstrap/public/favicon.ico rename to file-server/embedding-files-into-app-bindata/assets/favicon.ico diff --git a/file-server/embedding-files-into-app-bindata/assets/js/main.js b/file-server/embedding-files-into-app-bindata/assets/js/main.js new file mode 100644 index 00000000..07f93514 --- /dev/null +++ b/file-server/embedding-files-into-app-bindata/assets/js/main.js @@ -0,0 +1 @@ +console.log("example"); \ No newline at end of file diff --git a/file-server/embedding-files-into-app-bindata/bindata.go b/file-server/embedding-files-into-app-bindata/bindata.go new file mode 100644 index 00000000..80b96bf4 --- /dev/null +++ b/file-server/embedding-files-into-app-bindata/bindata.go @@ -0,0 +1,383 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// assets/css/main.css +// assets/favicon.ico +// assets/js/main.js +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _cssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x28\xc9\xcd\x51\xa8\xe6\xe5\xe2\x4c\xcb\xcf\x2b\xd1\x4d\x4b\xcc\xcd\xcc\xa9\xb4\x52\x28\x4e\xcc\x2b\xd6\x2d\x4e\x2d\xca\x4c\xb3\xe6\xe5\xe2\xd4\x2d\x4f\x4d\xca\xce\x2c\xd1\x2d\x49\xad\x28\xd1\x2d\xce\xac\x4a\xd5\x4d\x4c\xc9\x2a\x2d\x2e\xb1\x52\x30\x34\x30\x50\x05\xab\xc8\x2d\xc6\x21\xcb\xcb\x55\x0b\x08\x00\x00\xff\xff\x32\x4c\x06\xc6\x63\x00\x00\x00") + +func cssMainCssBytes() ([]byte, error) { + return bindataRead( + _cssMainCss, + "css/main.css", + ) +} + +func cssMainCss() (*asset, error) { + bytes, err := cssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "css/main.css", size: 99, mode: os.FileMode(438), modTime: time.Unix(1613718750, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _faviconIco = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00") + +func faviconIcoBytes() ([]byte, error) { + return bindataRead( + _faviconIco, + "favicon.ico", + ) +} + +func faviconIco() (*asset, error) { + bytes, err := faviconIcoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "favicon.ico", size: 15086, mode: os.FileMode(438), modTime: time.Unix(1612640817, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _jsMainJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xce\xcf\x2b\xce\xcf\x49\xd5\xcb\xc9\x4f\xd7\x50\x4a\xad\x48\xcc\x2d\xc8\x49\x55\xd2\xb4\x06\x04\x00\x00\xff\xff\xc8\x9f\xbd\x5f\x17\x00\x00\x00") + +func jsMainJsBytes() ([]byte, error) { + return bindataRead( + _jsMainJs, + "js/main.js", + ) +} + +func jsMainJs() (*asset, error) { + bytes, err := jsMainJsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "js/main.js", size: 23, mode: os.FileMode(438), modTime: time.Unix(1613718745, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "css/main.css": cssMainCss, + "favicon.ico": faviconIco, + "js/main.js": jsMainJs, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "css": {nil, map[string]*bintree{ + "main.css": {cssMainCss, map[string]*bintree{}}, + }}, + "favicon.ico": {faviconIco, map[string]*bintree{}}, + "js": {nil, map[string]*bintree{ + "main.js": {jsMainJs, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/file-server/embedding-files-into-app-bindata/main.go b/file-server/embedding-files-into-app-bindata/main.go new file mode 100644 index 00000000..f14b9b93 --- /dev/null +++ b/file-server/embedding-files-into-app-bindata/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +// Follow these steps first: +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// $ go-bindata -prefix "assets" -fs ./assets/... +// $ go run . +// "physical" files are not used, you can delete the "assets" folder and run the example. +// +// See `file-server/embedding-gzipped-files-into-app-bindata` and +// 'file-server/embedding-files-into-app` examples as well. +func newApp() *iris.Application { + app := iris.New() + app.Logger().SetLevel("debug") + + app.HandleDir("/static", AssetFile()) + + /* + Or if you need to cache them inside the memory (requires the assets folder + to be located near the executable program): + app.HandleDir("/static", iris.Dir("./assets"), iris.DirOptions{ + IndexName: "index.html", + Cache: iris.DirCacheOptions{ + Enable: true, + Encodings: []string{"gzip"}, + CompressIgnore: iris.MatchImagesAssets, + CompressMinSize: 30 * iris.B, + }, + }) + */ + return app +} + +func main() { + app := newApp() + + // http://localhost:8080/static/css/main.css + // http://localhost:8080/static/js/main.js + // http://localhost:8080/static/favicon.ico + app.Listen(":8080") +} diff --git a/file-server/embedding-files-into-app-bindata/main_test.go b/file-server/embedding-files-into-app-bindata/main_test.go new file mode 100644 index 00000000..03e32d33 --- /dev/null +++ b/file-server/embedding-files-into-app-bindata/main_test.go @@ -0,0 +1,94 @@ +package main + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +type resource string + +// content types that are used in the ./assets, +// we could use the detectContentType that iris do but it's better +// to do it manually so we can test if that returns the correct result on embedding files. +func (r resource) contentType() string { + switch filepath.Ext(r.String()) { + case ".js": + return "text/javascript" + case ".css": + return "text/css" + case ".ico": + return "image/x-icon" + case ".html": + return "text/html" + default: + return "text/plain" + } +} + +func (r resource) String() string { + return string(r) +} + +func (r resource) strip(strip string) string { + s := r.String() + return strings.TrimPrefix(s, strip) +} + +func (r resource) loadFromBase(dir string) string { + filename := r.strip("/static") + + fullpath := filepath.Join(dir, filename) + + b, err := os.ReadFile(fullpath) + if err != nil { + panic(fullpath + " failed with error: " + err.Error()) + } + + result := string(b) + if runtime.GOOS != "windows" { + result = strings.ReplaceAll(result, "\n", "\r\n") + result = strings.ReplaceAll(result, "\r\r", "") + } + + return result +} + +var urls = []resource{ + "/static/css/main.css", + "/static/js/main.js", + "/static/favicon.ico", +} + +// if bindata's values matches with the assets/... contents +// and secondly if the HandleDir had successfully registered +// the routes and gave the correct response. +func TestEmbeddingFilesIntoApp(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + route := app.GetRouteReadOnly("GET/static/{file:path}") + if route == nil { + t.Fatalf("expected a route to serve embedded files") + } + + if runtime.GOOS != "windows" { + // remove the embedded static favicon for !windows, + // it should be built for unix-specific in order to be work + urls = urls[0 : len(urls)-1] + } + + for _, u := range urls { + url := u.String() + contents := u.loadFromBase("./assets") + + e.GET(url).Expect(). + Status(httptest.StatusOK). + ContentType(u.contentType()). + Body().IsEqual(contents) + } +} diff --git a/file-server/embedding-files-into-app/assets/css/bootstrap.min.css b/file-server/embedding-files-into-app/assets/css/bootstrap.min.css deleted file mode 100644 index b578f18d..00000000 --- a/file-server/embedding-files-into-app/assets/css/bootstrap.min.css +++ /dev/null @@ -1,7225 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100% -} - -body { - margin: 0 -} - -article, aside, details, figcaption, figure, footer, header, hgroup, - main, menu, nav, section, summary { - display: block -} - -audio, canvas, progress, video { - display: inline-block; - vertical-align: baseline -} - -audio:not ([controls] ){ - display: none; - height: 0 -} - -[hidden], template { - display: none -} - -a { - background-color: transparent -} - -a:active, a:hover { - outline: 0 -} - -abbr[title] { - border-bottom: 1px dotted -} - -b, strong { - font-weight: 700 -} - -dfn { - font-style: italic -} - -h1 { - margin: .67em 0; - font-size: 2em -} - -mark { - color: #000; - background: #ff0 -} - -small { - font-size: 80% -} - -sub, sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline -} - -sup { - top: -.5em -} - -sub { - bottom: -.25em -} - -img { - border: 0 -} - -svg:not (:root ){ - overflow: hidden -} - -figure { - margin: 1em 40px -} - -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box -} - -pre { - overflow: auto -} - -code, kbd, pre, samp { - font-family: monospace, monospace; - font-size: 1em -} - -button, input, optgroup, select, textarea { - margin: 0; - font: inherit; - color: inherit -} - -button { - overflow: visible -} - -button, select { - text-transform: none -} - -button, html input[type=button], input[type=reset], input[type=submit] { - -webkit-appearance: button; - cursor: pointer -} - -button[disabled], html input[disabled] { - cursor: default -} - -button::-moz-focus-inner, input::-moz-focus-inner { - padding: 0; - border: 0 -} - -input { - line-height: normal -} - -input[type=checkbox], input[type=radio] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0 -} - -input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button - { - height: auto -} - -input[type=search] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield -} - -input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration - { - -webkit-appearance: none -} - -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid silver -} - -legend { - padding: 0; - border: 0 -} - -textarea { - overflow: auto -} - -optgroup { - font-weight: 700 -} - -table { - border-spacing: 0; - border-collapse: collapse -} - -td, th { - padding: 0 -} - /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, :after, :before { - color: #000 !important; - text-shadow: none !important; - background: 0 0 !important; - -webkit-box-shadow: none !important; - box-shadow: none !important - } - a, a:visited { - text-decoration: underline - } - a[href]:after { - content: " (" attr(href) ")" - } - abbr[title]:after { - content: " (" attr(title) ")" - } - a[href^="javascript:"]:after, a[href^="#"]:after { - content: "" - } - blockquote, pre { - border: 1px solid #999; - page-break-inside: avoid - } - thead { - display: table-header-group - } - img, tr { - page-break-inside: avoid - } - img { - max-width: 100% !important - } - h2, h3, p { - orphans: 3; - widows: 3 - } - h2, h3 { - page-break-after: avoid - } - select { - background: #fff !important - } - .navbar { - display: none - } - .btn>.caret, .dropup>.btn>.caret { - border-top-color: #000 !important - } - .label { - border: 1px solid #000 - } - .table { - border-collapse: collapse !important - } - .table td, .table th { - background-color: #fff !important - } - .table-bordered td, .table-bordered th { - border: 1px solid #ddd !important - } -} - -@font-face { - font-family: 'Glyphicons Halflings'; - src: url(../fonts/glyphicons-halflings-regular.eot); - src: url(../fonts/glyphicons-halflings-regular.eot?#iefix) - format('embedded-opentype'), - url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'), - url(../fonts/glyphicons-halflings-regular.woff) format('woff'), - url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'), - url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) - format('svg') -} - -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: 400; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale -} - -.glyphicon-asterisk:before { - content: "\2a" -} - -.glyphicon-plus:before { - content: "\2b" -} - -.glyphicon-eur:before, .glyphicon-euro:before { - content: "\20ac" -} - -.glyphicon-minus:before { - content: "\2212" -} - -.glyphicon-cloud:before { - content: "\2601" -} - -.glyphicon-envelope:before { - content: "\2709" -} - -.glyphicon-pencil:before { - content: "\270f" -} - -.glyphicon-glass:before { - content: "\e001" -} - -.glyphicon-music:before { - content: "\e002" -} - -.glyphicon-search:before { - content: "\e003" -} - -.glyphicon-heart:before { - content: "\e005" -} - -.glyphicon-star:before { - content: "\e006" -} - -.glyphicon-star-empty:before { - content: "\e007" -} - -.glyphicon-user:before { - content: "\e008" -} - -.glyphicon-film:before { - content: "\e009" -} - -.glyphicon-th-large:before { - content: "\e010" -} - -.glyphicon-th:before { - content: "\e011" -} - -.glyphicon-th-list:before { - content: "\e012" -} - -.glyphicon-ok:before { - content: "\e013" -} - -.glyphicon-remove:before { - content: "\e014" -} - -.glyphicon-zoom-in:before { - content: "\e015" -} - -.glyphicon-zoom-out:before { - content: "\e016" -} - -.glyphicon-off:before { - content: "\e017" -} - -.glyphicon-signal:before { - content: "\e018" -} - -.glyphicon-cog:before { - content: "\e019" -} - -.glyphicon-trash:before { - content: "\e020" -} - -.glyphicon-home:before { - content: "\e021" -} - -.glyphicon-file:before { - content: "\e022" -} - -.glyphicon-time:before { - content: "\e023" -} - -.glyphicon-road:before { - content: "\e024" -} - -.glyphicon-download-alt:before { - content: "\e025" -} - -.glyphicon-download:before { - content: "\e026" -} - -.glyphicon-upload:before { - content: "\e027" -} - -.glyphicon-inbox:before { - content: "\e028" -} - -.glyphicon-play-circle:before { - content: "\e029" -} - -.glyphicon-repeat:before { - content: "\e030" -} - -.glyphicon-refresh:before { - content: "\e031" -} - -.glyphicon-list-alt:before { - content: "\e032" -} - -.glyphicon-lock:before { - content: "\e033" -} - -.glyphicon-flag:before { - content: "\e034" -} - -.glyphicon-headphones:before { - content: "\e035" -} - -.glyphicon-volume-off:before { - content: "\e036" -} - -.glyphicon-volume-down:before { - content: "\e037" -} - -.glyphicon-volume-up:before { - content: "\e038" -} - -.glyphicon-qrcode:before { - content: "\e039" -} - -.glyphicon-barcode:before { - content: "\e040" -} - -.glyphicon-tag:before { - content: "\e041" -} - -.glyphicon-tags:before { - content: "\e042" -} - -.glyphicon-book:before { - content: "\e043" -} - -.glyphicon-bookmark:before { - content: "\e044" -} - -.glyphicon-print:before { - content: "\e045" -} - -.glyphicon-camera:before { - content: "\e046" -} - -.glyphicon-font:before { - content: "\e047" -} - -.glyphicon-bold:before { - content: "\e048" -} - -.glyphicon-italic:before { - content: "\e049" -} - -.glyphicon-text-height:before { - content: "\e050" -} - -.glyphicon-text-width:before { - content: "\e051" -} - -.glyphicon-align-left:before { - content: "\e052" -} - -.glyphicon-align-center:before { - content: "\e053" -} - -.glyphicon-align-right:before { - content: "\e054" -} - -.glyphicon-align-justify:before { - content: "\e055" -} - -.glyphicon-list:before { - content: "\e056" -} - -.glyphicon-indent-left:before { - content: "\e057" -} - -.glyphicon-indent-right:before { - content: "\e058" -} - -.glyphicon-facetime-video:before { - content: "\e059" -} - -.glyphicon-picture:before { - content: "\e060" -} - -.glyphicon-map-marker:before { - content: "\e062" -} - -.glyphicon-adjust:before { - content: "\e063" -} - -.glyphicon-tint:before { - content: "\e064" -} - -.glyphicon-edit:before { - content: "\e065" -} - -.glyphicon-share:before { - content: "\e066" -} - -.glyphicon-check:before { - content: "\e067" -} - -.glyphicon-move:before { - content: "\e068" -} - -.glyphicon-step-backward:before { - content: "\e069" -} - -.glyphicon-fast-backward:before { - content: "\e070" -} - -.glyphicon-backward:before { - content: "\e071" -} - -.glyphicon-play:before { - content: "\e072" -} - -.glyphicon-pause:before { - content: "\e073" -} - -.glyphicon-stop:before { - content: "\e074" -} - -.glyphicon-forward:before { - content: "\e075" -} - -.glyphicon-fast-forward:before { - content: "\e076" -} - -.glyphicon-step-forward:before { - content: "\e077" -} - -.glyphicon-eject:before { - content: "\e078" -} - -.glyphicon-chevron-left:before { - content: "\e079" -} - -.glyphicon-chevron-right:before { - content: "\e080" -} - -.glyphicon-plus-sign:before { - content: "\e081" -} - -.glyphicon-minus-sign:before { - content: "\e082" -} - -.glyphicon-remove-sign:before { - content: "\e083" -} - -.glyphicon-ok-sign:before { - content: "\e084" -} - -.glyphicon-question-sign:before { - content: "\e085" -} - -.glyphicon-info-sign:before { - content: "\e086" -} - -.glyphicon-screenshot:before { - content: "\e087" -} - -.glyphicon-remove-circle:before { - content: "\e088" -} - -.glyphicon-ok-circle:before { - content: "\e089" -} - -.glyphicon-ban-circle:before { - content: "\e090" -} - -.glyphicon-arrow-left:before { - content: "\e091" -} - -.glyphicon-arrow-right:before { - content: "\e092" -} - -.glyphicon-arrow-up:before { - content: "\e093" -} - -.glyphicon-arrow-down:before { - content: "\e094" -} - -.glyphicon-share-alt:before { - content: "\e095" -} - -.glyphicon-resize-full:before { - content: "\e096" -} - -.glyphicon-resize-small:before { - content: "\e097" -} - -.glyphicon-exclamation-sign:before { - content: "\e101" -} - -.glyphicon-gift:before { - content: "\e102" -} - -.glyphicon-leaf:before { - content: "\e103" -} - -.glyphicon-fire:before { - content: "\e104" -} - -.glyphicon-eye-open:before { - content: "\e105" -} - -.glyphicon-eye-close:before { - content: "\e106" -} - -.glyphicon-warning-sign:before { - content: "\e107" -} - -.glyphicon-plane:before { - content: "\e108" -} - -.glyphicon-calendar:before { - content: "\e109" -} - -.glyphicon-random:before { - content: "\e110" -} - -.glyphicon-comment:before { - content: "\e111" -} - -.glyphicon-magnet:before { - content: "\e112" -} - -.glyphicon-chevron-up:before { - content: "\e113" -} - -.glyphicon-chevron-down:before { - content: "\e114" -} - -.glyphicon-retweet:before { - content: "\e115" -} - -.glyphicon-shopping-cart:before { - content: "\e116" -} - -.glyphicon-folder-close:before { - content: "\e117" -} - -.glyphicon-folder-open:before { - content: "\e118" -} - -.glyphicon-resize-vertical:before { - content: "\e119" -} - -.glyphicon-resize-horizontal:before { - content: "\e120" -} - -.glyphicon-hdd:before { - content: "\e121" -} - -.glyphicon-bullhorn:before { - content: "\e122" -} - -.glyphicon-bell:before { - content: "\e123" -} - -.glyphicon-certificate:before { - content: "\e124" -} - -.glyphicon-thumbs-up:before { - content: "\e125" -} - -.glyphicon-thumbs-down:before { - content: "\e126" -} - -.glyphicon-hand-right:before { - content: "\e127" -} - -.glyphicon-hand-left:before { - content: "\e128" -} - -.glyphicon-hand-up:before { - content: "\e129" -} - -.glyphicon-hand-down:before { - content: "\e130" -} - -.glyphicon-circle-arrow-right:before { - content: "\e131" -} - -.glyphicon-circle-arrow-left:before { - content: "\e132" -} - -.glyphicon-circle-arrow-up:before { - content: "\e133" -} - -.glyphicon-circle-arrow-down:before { - content: "\e134" -} - -.glyphicon-globe:before { - content: "\e135" -} - -.glyphicon-wrench:before { - content: "\e136" -} - -.glyphicon-tasks:before { - content: "\e137" -} - -.glyphicon-filter:before { - content: "\e138" -} - -.glyphicon-briefcase:before { - content: "\e139" -} - -.glyphicon-fullscreen:before { - content: "\e140" -} - -.glyphicon-dashboard:before { - content: "\e141" -} - -.glyphicon-paperclip:before { - content: "\e142" -} - -.glyphicon-heart-empty:before { - content: "\e143" -} - -.glyphicon-link:before { - content: "\e144" -} - -.glyphicon-phone:before { - content: "\e145" -} - -.glyphicon-pushpin:before { - content: "\e146" -} - -.glyphicon-usd:before { - content: "\e148" -} - -.glyphicon-gbp:before { - content: "\e149" -} - -.glyphicon-sort:before { - content: "\e150" -} - -.glyphicon-sort-by-alphabet:before { - content: "\e151" -} - -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152" -} - -.glyphicon-sort-by-order:before { - content: "\e153" -} - -.glyphicon-sort-by-order-alt:before { - content: "\e154" -} - -.glyphicon-sort-by-attributes:before { - content: "\e155" -} - -.glyphicon-sort-by-attributes-alt:before { - content: "\e156" -} - -.glyphicon-unchecked:before { - content: "\e157" -} - -.glyphicon-expand:before { - content: "\e158" -} - -.glyphicon-collapse-down:before { - content: "\e159" -} - -.glyphicon-collapse-up:before { - content: "\e160" -} - -.glyphicon-log-in:before { - content: "\e161" -} - -.glyphicon-flash:before { - content: "\e162" -} - -.glyphicon-log-out:before { - content: "\e163" -} - -.glyphicon-new-window:before { - content: "\e164" -} - -.glyphicon-record:before { - content: "\e165" -} - -.glyphicon-save:before { - content: "\e166" -} - -.glyphicon-open:before { - content: "\e167" -} - -.glyphicon-saved:before { - content: "\e168" -} - -.glyphicon-import:before { - content: "\e169" -} - -.glyphicon-export:before { - content: "\e170" -} - -.glyphicon-send:before { - content: "\e171" -} - -.glyphicon-floppy-disk:before { - content: "\e172" -} - -.glyphicon-floppy-saved:before { - content: "\e173" -} - -.glyphicon-floppy-remove:before { - content: "\e174" -} - -.glyphicon-floppy-save:before { - content: "\e175" -} - -.glyphicon-floppy-open:before { - content: "\e176" -} - -.glyphicon-credit-card:before { - content: "\e177" -} - -.glyphicon-transfer:before { - content: "\e178" -} - -.glyphicon-cutlery:before { - content: "\e179" -} - -.glyphicon-header:before { - content: "\e180" -} - -.glyphicon-compressed:before { - content: "\e181" -} - -.glyphicon-earphone:before { - content: "\e182" -} - -.glyphicon-phone-alt:before { - content: "\e183" -} - -.glyphicon-tower:before { - content: "\e184" -} - -.glyphicon-stats:before { - content: "\e185" -} - -.glyphicon-sd-video:before { - content: "\e186" -} - -.glyphicon-hd-video:before { - content: "\e187" -} - -.glyphicon-subtitles:before { - content: "\e188" -} - -.glyphicon-sound-stereo:before { - content: "\e189" -} - -.glyphicon-sound-dolby:before { - content: "\e190" -} - -.glyphicon-sound-5-1:before { - content: "\e191" -} - -.glyphicon-sound-6-1:before { - content: "\e192" -} - -.glyphicon-sound-7-1:before { - content: "\e193" -} - -.glyphicon-copyright-mark:before { - content: "\e194" -} - -.glyphicon-registration-mark:before { - content: "\e195" -} - -.glyphicon-cloud-download:before { - content: "\e197" -} - -.glyphicon-cloud-upload:before { - content: "\e198" -} - -.glyphicon-tree-conifer:before { - content: "\e199" -} - -.glyphicon-tree-deciduous:before { - content: "\e200" -} - -.glyphicon-cd:before { - content: "\e201" -} - -.glyphicon-save-file:before { - content: "\e202" -} - -.glyphicon-open-file:before { - content: "\e203" -} - -.glyphicon-level-up:before { - content: "\e204" -} - -.glyphicon-copy:before { - content: "\e205" -} - -.glyphicon-paste:before { - content: "\e206" -} - -.glyphicon-alert:before { - content: "\e209" -} - -.glyphicon-equalizer:before { - content: "\e210" -} - -.glyphicon-king:before { - content: "\e211" -} - -.glyphicon-queen:before { - content: "\e212" -} - -.glyphicon-pawn:before { - content: "\e213" -} - -.glyphicon-bishop:before { - content: "\e214" -} - -.glyphicon-knight:before { - content: "\e215" -} - -.glyphicon-baby-formula:before { - content: "\e216" -} - -.glyphicon-tent:before { - content: "\26fa" -} - -.glyphicon-blackboard:before { - content: "\e218" -} - -.glyphicon-bed:before { - content: "\e219" -} - -.glyphicon-apple:before { - content: "\f8ff" -} - -.glyphicon-erase:before { - content: "\e221" -} - -.glyphicon-hourglass:before { - content: "\231b" -} - -.glyphicon-lamp:before { - content: "\e223" -} - -.glyphicon-duplicate:before { - content: "\e224" -} - -.glyphicon-piggy-bank:before { - content: "\e225" -} - -.glyphicon-scissors:before { - content: "\e226" -} - -.glyphicon-bitcoin:before { - content: "\e227" -} - -.glyphicon-btc:before { - content: "\e227" -} - -.glyphicon-xbt:before { - content: "\e227" -} - -.glyphicon-yen:before { - content: "\00a5" -} - -.glyphicon-jpy:before { - content: "\00a5" -} - -.glyphicon-ruble:before { - content: "\20bd" -} - -.glyphicon-rub:before { - content: "\20bd" -} - -.glyphicon-scale:before { - content: "\e230" -} - -.glyphicon-ice-lolly:before { - content: "\e231" -} - -.glyphicon-ice-lolly-tasted:before { - content: "\e232" -} - -.glyphicon-education:before { - content: "\e233" -} - -.glyphicon-option-horizontal:before { - content: "\e234" -} - -.glyphicon-option-vertical:before { - content: "\e235" -} - -.glyphicon-menu-hamburger:before { - content: "\e236" -} - -.glyphicon-modal-window:before { - content: "\e237" -} - -.glyphicon-oil:before { - content: "\e238" -} - -.glyphicon-grain:before { - content: "\e239" -} - -.glyphicon-sunglasses:before { - content: "\e240" -} - -.glyphicon-text-size:before { - content: "\e241" -} - -.glyphicon-text-color:before { - content: "\e242" -} - -.glyphicon-text-background:before { - content: "\e243" -} - -.glyphicon-object-align-top:before { - content: "\e244" -} - -.glyphicon-object-align-bottom:before { - content: "\e245" -} - -.glyphicon-object-align-horizontal:before { - content: "\e246" -} - -.glyphicon-object-align-left:before { - content: "\e247" -} - -.glyphicon-object-align-vertical:before { - content: "\e248" -} - -.glyphicon-object-align-right:before { - content: "\e249" -} - -.glyphicon-triangle-right:before { - content: "\e250" -} - -.glyphicon-triangle-left:before { - content: "\e251" -} - -.glyphicon-triangle-bottom:before { - content: "\e252" -} - -.glyphicon-triangle-top:before { - content: "\e253" -} - -.glyphicon-console:before { - content: "\e254" -} - -.glyphicon-superscript:before { - content: "\e255" -} - -.glyphicon-subscript:before { - content: "\e256" -} - -.glyphicon-menu-left:before { - content: "\e257" -} - -.glyphicon-menu-right:before { - content: "\e258" -} - -.glyphicon-menu-down:before { - content: "\e259" -} - -.glyphicon-menu-up:before { - content: "\e260" -} - -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -:after, :before { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -html { - font-size: 10px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0) -} - -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff -} - -button, input, select, textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit -} - -a { - color: #337ab7; - text-decoration: none -} - -a:focus, a:hover { - color: #23527c; - text-decoration: underline -} - -a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -figure { - margin: 0 -} - -img { - vertical-align: middle -} - -.carousel-inner>.item>a>img, .carousel-inner>.item>img, .img-responsive, - .thumbnail a>img, .thumbnail>img { - display: block; - max-width: 100%; - height: auto -} - -.img-rounded { - border-radius: 6px -} - -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out -} - -.img-circle { - border-radius: 50% -} - -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0 -} - -.sr-only-focusable:active, .sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto -} - -[role=button] { - cursor: pointer -} - -.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit -} - -.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, .h4 .small, - .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h1 .small, h1 small, - h2 .small, h2 small, h3 .small, h3 small, h4 .small, h4 small, h5 .small, - h5 small, h6 .small, h6 small { - font-weight: 400; - line-height: 1; - color: #777 -} - -.h1, .h2, .h3, h1, h2, h3 { - margin-top: 20px; - margin-bottom: 10px -} - -.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, h1 .small, - h1 small, h2 .small, h2 small, h3 .small, h3 small { - font-size: 65% -} - -.h4, .h5, .h6, h4, h5, h6 { - margin-top: 10px; - margin-bottom: 10px -} - -.h4 .small, .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h4 .small, - h4 small, h5 .small, h5 small, h6 .small, h6 small { - font-size: 75% -} - -.h1, h1 { - font-size: 36px -} - -.h2, h2 { - font-size: 30px -} - -.h3, h3 { - font-size: 24px -} - -.h4, h4 { - font-size: 18px -} - -.h5, h5 { - font-size: 14px -} - -.h6, h6 { - font-size: 12px -} - -p { - margin: 0 0 10px -} - -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4 -} - -@media ( min-width :768px) { - .lead { - font-size: 21px - } -} - -.small, small { - font-size: 85% -} - -.mark, mark { - padding: .2em; - background-color: #fcf8e3 -} - -.text-left { - text-align: left -} - -.text-right { - text-align: right -} - -.text-center { - text-align: center -} - -.text-justify { - text-align: justify -} - -.text-nowrap { - white-space: nowrap -} - -.text-lowercase { - text-transform: lowercase -} - -.text-uppercase { - text-transform: uppercase -} - -.text-capitalize { - text-transform: capitalize -} - -.text-muted { - color: #777 -} - -.text-primary { - color: #337ab7 -} - -a.text-primary:hover { - color: #286090 -} - -.text-success { - color: #3c763d -} - -a.text-success:hover { - color: #2b542c -} - -.text-info { - color: #31708f -} - -a.text-info:hover { - color: #245269 -} - -.text-warning { - color: #8a6d3b -} - -a.text-warning:hover { - color: #66512c -} - -.text-danger { - color: #a94442 -} - -a.text-danger:hover { - color: #843534 -} - -.bg-primary { - color: #fff; - background-color: #337ab7 -} - -a.bg-primary:hover { - background-color: #286090 -} - -.bg-success { - background-color: #dff0d8 -} - -a.bg-success:hover { - background-color: #c1e2b3 -} - -.bg-info { - background-color: #d9edf7 -} - -a.bg-info:hover { - background-color: #afd9ee -} - -.bg-warning { - background-color: #fcf8e3 -} - -a.bg-warning:hover { - background-color: #f7ecb5 -} - -.bg-danger { - background-color: #f2dede -} - -a.bg-danger:hover { - background-color: #e4b9b9 -} - -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee -} - -ol, ul { - margin-top: 0; - margin-bottom: 10px -} - -ol ol, ol ul, ul ol, ul ul { - margin-bottom: 0 -} - -.list-unstyled { - padding-left: 0; - list-style: none -} - -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none -} - -.list-inline>li { - display: inline-block; - padding-right: 5px; - padding-left: 5px -} - -dl { - margin-top: 0; - margin-bottom: 20px -} - -dd, dt { - line-height: 1.42857143 -} - -dt { - font-weight: 700 -} - -dd { - margin-left: 0 -} - -@media ( min-width :768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap - } - .dl-horizontal dd { - margin-left: 180px - } -} - -abbr[data-original-title], abbr[title] { - cursor: help; - border-bottom: 1px dotted #777 -} - -.initialism { - font-size: 90%; - text-transform: uppercase -} - -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee -} - -blockquote ol:last-child, blockquote p:last-child, blockquote ul:last-child - { - margin-bottom: 0 -} - -blockquote .small, blockquote footer, blockquote small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777 -} - -blockquote .small:before, blockquote footer:before, blockquote small:before - { - content: '\2014 \00A0' -} - -.blockquote-reverse, blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0 -} - -.blockquote-reverse .small:before, .blockquote-reverse footer:before, - .blockquote-reverse small:before, blockquote.pull-right .small:before, - blockquote.pull-right footer:before, blockquote.pull-right small:before - { - content: '' -} - -.blockquote-reverse .small:after, .blockquote-reverse footer:after, - .blockquote-reverse small:after, blockquote.pull-right .small:after, - blockquote.pull-right footer:after, blockquote.pull-right small:after { - content: '\00A0 \2014' -} - -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143 -} - -code, kbd, pre, samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace -} - -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px -} - -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25) -} - -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: 700; - -webkit-box-shadow: none; - box-shadow: none -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px -} - -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0 -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll -} - -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto -} - -@media ( min-width :768px) { - .container { - width: 750px - } -} - -@media ( min-width :992px) { - .container { - width: 970px - } -} - -@media ( min-width :1200px) { - .container { - width: 1170px - } -} - -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto -} - -.row { - margin-right: -15px; - margin-left: -15px -} - -.col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, - .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, - .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, - .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, - .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, - .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, - .col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, - .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px -} - -.col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, - .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 { - float: left -} - -.col-xs-12 { - width: 100% -} - -.col-xs-11 { - width: 91.66666667% -} - -.col-xs-10 { - width: 83.33333333% -} - -.col-xs-9 { - width: 75% -} - -.col-xs-8 { - width: 66.66666667% -} - -.col-xs-7 { - width: 58.33333333% -} - -.col-xs-6 { - width: 50% -} - -.col-xs-5 { - width: 41.66666667% -} - -.col-xs-4 { - width: 33.33333333% -} - -.col-xs-3 { - width: 25% -} - -.col-xs-2 { - width: 16.66666667% -} - -.col-xs-1 { - width: 8.33333333% -} - -.col-xs-pull-12 { - right: 100% -} - -.col-xs-pull-11 { - right: 91.66666667% -} - -.col-xs-pull-10 { - right: 83.33333333% -} - -.col-xs-pull-9 { - right: 75% -} - -.col-xs-pull-8 { - right: 66.66666667% -} - -.col-xs-pull-7 { - right: 58.33333333% -} - -.col-xs-pull-6 { - right: 50% -} - -.col-xs-pull-5 { - right: 41.66666667% -} - -.col-xs-pull-4 { - right: 33.33333333% -} - -.col-xs-pull-3 { - right: 25% -} - -.col-xs-pull-2 { - right: 16.66666667% -} - -.col-xs-pull-1 { - right: 8.33333333% -} - -.col-xs-pull-0 { - right: auto -} - -.col-xs-push-12 { - left: 100% -} - -.col-xs-push-11 { - left: 91.66666667% -} - -.col-xs-push-10 { - left: 83.33333333% -} - -.col-xs-push-9 { - left: 75% -} - -.col-xs-push-8 { - left: 66.66666667% -} - -.col-xs-push-7 { - left: 58.33333333% -} - -.col-xs-push-6 { - left: 50% -} - -.col-xs-push-5 { - left: 41.66666667% -} - -.col-xs-push-4 { - left: 33.33333333% -} - -.col-xs-push-3 { - left: 25% -} - -.col-xs-push-2 { - left: 16.66666667% -} - -.col-xs-push-1 { - left: 8.33333333% -} - -.col-xs-push-0 { - left: auto -} - -.col-xs-offset-12 { - margin-left: 100% -} - -.col-xs-offset-11 { - margin-left: 91.66666667% -} - -.col-xs-offset-10 { - margin-left: 83.33333333% -} - -.col-xs-offset-9 { - margin-left: 75% -} - -.col-xs-offset-8 { - margin-left: 66.66666667% -} - -.col-xs-offset-7 { - margin-left: 58.33333333% -} - -.col-xs-offset-6 { - margin-left: 50% -} - -.col-xs-offset-5 { - margin-left: 41.66666667% -} - -.col-xs-offset-4 { - margin-left: 33.33333333% -} - -.col-xs-offset-3 { - margin-left: 25% -} - -.col-xs-offset-2 { - margin-left: 16.66666667% -} - -.col-xs-offset-1 { - margin-left: 8.33333333% -} - -.col-xs-offset-0 { - margin-left: 0 -} - -@media ( min-width :768px) { - .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, - .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9 { - float: left - } - .col-sm-12 { - width: 100% - } - .col-sm-11 { - width: 91.66666667% - } - .col-sm-10 { - width: 83.33333333% - } - .col-sm-9 { - width: 75% - } - .col-sm-8 { - width: 66.66666667% - } - .col-sm-7 { - width: 58.33333333% - } - .col-sm-6 { - width: 50% - } - .col-sm-5 { - width: 41.66666667% - } - .col-sm-4 { - width: 33.33333333% - } - .col-sm-3 { - width: 25% - } - .col-sm-2 { - width: 16.66666667% - } - .col-sm-1 { - width: 8.33333333% - } - .col-sm-pull-12 { - right: 100% - } - .col-sm-pull-11 { - right: 91.66666667% - } - .col-sm-pull-10 { - right: 83.33333333% - } - .col-sm-pull-9 { - right: 75% - } - .col-sm-pull-8 { - right: 66.66666667% - } - .col-sm-pull-7 { - right: 58.33333333% - } - .col-sm-pull-6 { - right: 50% - } - .col-sm-pull-5 { - right: 41.66666667% - } - .col-sm-pull-4 { - right: 33.33333333% - } - .col-sm-pull-3 { - right: 25% - } - .col-sm-pull-2 { - right: 16.66666667% - } - .col-sm-pull-1 { - right: 8.33333333% - } - .col-sm-pull-0 { - right: auto - } - .col-sm-push-12 { - left: 100% - } - .col-sm-push-11 { - left: 91.66666667% - } - .col-sm-push-10 { - left: 83.33333333% - } - .col-sm-push-9 { - left: 75% - } - .col-sm-push-8 { - left: 66.66666667% - } - .col-sm-push-7 { - left: 58.33333333% - } - .col-sm-push-6 { - left: 50% - } - .col-sm-push-5 { - left: 41.66666667% - } - .col-sm-push-4 { - left: 33.33333333% - } - .col-sm-push-3 { - left: 25% - } - .col-sm-push-2 { - left: 16.66666667% - } - .col-sm-push-1 { - left: 8.33333333% - } - .col-sm-push-0 { - left: auto - } - .col-sm-offset-12 { - margin-left: 100% - } - .col-sm-offset-11 { - margin-left: 91.66666667% - } - .col-sm-offset-10 { - margin-left: 83.33333333% - } - .col-sm-offset-9 { - margin-left: 75% - } - .col-sm-offset-8 { - margin-left: 66.66666667% - } - .col-sm-offset-7 { - margin-left: 58.33333333% - } - .col-sm-offset-6 { - margin-left: 50% - } - .col-sm-offset-5 { - margin-left: 41.66666667% - } - .col-sm-offset-4 { - margin-left: 33.33333333% - } - .col-sm-offset-3 { - margin-left: 25% - } - .col-sm-offset-2 { - margin-left: 16.66666667% - } - .col-sm-offset-1 { - margin-left: 8.33333333% - } - .col-sm-offset-0 { - margin-left: 0 - } -} - -@media ( min-width :992px) { - .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, - .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9 { - float: left - } - .col-md-12 { - width: 100% - } - .col-md-11 { - width: 91.66666667% - } - .col-md-10 { - width: 83.33333333% - } - .col-md-9 { - width: 75% - } - .col-md-8 { - width: 66.66666667% - } - .col-md-7 { - width: 58.33333333% - } - .col-md-6 { - width: 50% - } - .col-md-5 { - width: 41.66666667% - } - .col-md-4 { - width: 33.33333333% - } - .col-md-3 { - width: 25% - } - .col-md-2 { - width: 16.66666667% - } - .col-md-1 { - width: 8.33333333% - } - .col-md-pull-12 { - right: 100% - } - .col-md-pull-11 { - right: 91.66666667% - } - .col-md-pull-10 { - right: 83.33333333% - } - .col-md-pull-9 { - right: 75% - } - .col-md-pull-8 { - right: 66.66666667% - } - .col-md-pull-7 { - right: 58.33333333% - } - .col-md-pull-6 { - right: 50% - } - .col-md-pull-5 { - right: 41.66666667% - } - .col-md-pull-4 { - right: 33.33333333% - } - .col-md-pull-3 { - right: 25% - } - .col-md-pull-2 { - right: 16.66666667% - } - .col-md-pull-1 { - right: 8.33333333% - } - .col-md-pull-0 { - right: auto - } - .col-md-push-12 { - left: 100% - } - .col-md-push-11 { - left: 91.66666667% - } - .col-md-push-10 { - left: 83.33333333% - } - .col-md-push-9 { - left: 75% - } - .col-md-push-8 { - left: 66.66666667% - } - .col-md-push-7 { - left: 58.33333333% - } - .col-md-push-6 { - left: 50% - } - .col-md-push-5 { - left: 41.66666667% - } - .col-md-push-4 { - left: 33.33333333% - } - .col-md-push-3 { - left: 25% - } - .col-md-push-2 { - left: 16.66666667% - } - .col-md-push-1 { - left: 8.33333333% - } - .col-md-push-0 { - left: auto - } - .col-md-offset-12 { - margin-left: 100% - } - .col-md-offset-11 { - margin-left: 91.66666667% - } - .col-md-offset-10 { - margin-left: 83.33333333% - } - .col-md-offset-9 { - margin-left: 75% - } - .col-md-offset-8 { - margin-left: 66.66666667% - } - .col-md-offset-7 { - margin-left: 58.33333333% - } - .col-md-offset-6 { - margin-left: 50% - } - .col-md-offset-5 { - margin-left: 41.66666667% - } - .col-md-offset-4 { - margin-left: 33.33333333% - } - .col-md-offset-3 { - margin-left: 25% - } - .col-md-offset-2 { - margin-left: 16.66666667% - } - .col-md-offset-1 { - margin-left: 8.33333333% - } - .col-md-offset-0 { - margin-left: 0 - } -} - -@media ( min-width :1200px) { - .col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, - .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9 { - float: left - } - .col-lg-12 { - width: 100% - } - .col-lg-11 { - width: 91.66666667% - } - .col-lg-10 { - width: 83.33333333% - } - .col-lg-9 { - width: 75% - } - .col-lg-8 { - width: 66.66666667% - } - .col-lg-7 { - width: 58.33333333% - } - .col-lg-6 { - width: 50% - } - .col-lg-5 { - width: 41.66666667% - } - .col-lg-4 { - width: 33.33333333% - } - .col-lg-3 { - width: 25% - } - .col-lg-2 { - width: 16.66666667% - } - .col-lg-1 { - width: 8.33333333% - } - .col-lg-pull-12 { - right: 100% - } - .col-lg-pull-11 { - right: 91.66666667% - } - .col-lg-pull-10 { - right: 83.33333333% - } - .col-lg-pull-9 { - right: 75% - } - .col-lg-pull-8 { - right: 66.66666667% - } - .col-lg-pull-7 { - right: 58.33333333% - } - .col-lg-pull-6 { - right: 50% - } - .col-lg-pull-5 { - right: 41.66666667% - } - .col-lg-pull-4 { - right: 33.33333333% - } - .col-lg-pull-3 { - right: 25% - } - .col-lg-pull-2 { - right: 16.66666667% - } - .col-lg-pull-1 { - right: 8.33333333% - } - .col-lg-pull-0 { - right: auto - } - .col-lg-push-12 { - left: 100% - } - .col-lg-push-11 { - left: 91.66666667% - } - .col-lg-push-10 { - left: 83.33333333% - } - .col-lg-push-9 { - left: 75% - } - .col-lg-push-8 { - left: 66.66666667% - } - .col-lg-push-7 { - left: 58.33333333% - } - .col-lg-push-6 { - left: 50% - } - .col-lg-push-5 { - left: 41.66666667% - } - .col-lg-push-4 { - left: 33.33333333% - } - .col-lg-push-3 { - left: 25% - } - .col-lg-push-2 { - left: 16.66666667% - } - .col-lg-push-1 { - left: 8.33333333% - } - .col-lg-push-0 { - left: auto - } - .col-lg-offset-12 { - margin-left: 100% - } - .col-lg-offset-11 { - margin-left: 91.66666667% - } - .col-lg-offset-10 { - margin-left: 83.33333333% - } - .col-lg-offset-9 { - margin-left: 75% - } - .col-lg-offset-8 { - margin-left: 66.66666667% - } - .col-lg-offset-7 { - margin-left: 58.33333333% - } - .col-lg-offset-6 { - margin-left: 50% - } - .col-lg-offset-5 { - margin-left: 41.66666667% - } - .col-lg-offset-4 { - margin-left: 33.33333333% - } - .col-lg-offset-3 { - margin-left: 25% - } - .col-lg-offset-2 { - margin-left: 16.66666667% - } - .col-lg-offset-1 { - margin-left: 8.33333333% - } - .col-lg-offset-0 { - margin-left: 0 - } -} - -table { - background-color: transparent -} - -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left -} - -th { - text-align: left -} - -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px -} - -.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, - .table>thead>tr>td, .table>thead>tr>th { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd -} - -.table>thead>tr>th { - vertical-align: bottom; - border-bottom: 2px solid #ddd -} - -.table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, - .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, - .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th - { - border-top: 0 -} - -.table>tbody+tbody { - border-top: 2px solid #ddd -} - -.table .table { - background-color: #fff -} - -.table-condensed>tbody>tr>td, .table-condensed>tbody>tr>th, - .table-condensed>tfoot>tr>td, .table-condensed>tfoot>tr>th, - .table-condensed>thead>tr>td, .table-condensed>thead>tr>th { - padding: 5px -} - -.table-bordered { - border: 1px solid #ddd -} - -.table-bordered>tbody>tr>td, .table-bordered>tbody>tr>th, - .table-bordered>tfoot>tr>td, .table-bordered>tfoot>tr>th, - .table-bordered>thead>tr>td, .table-bordered>thead>tr>th { - border: 1px solid #ddd -} - -.table-bordered>thead>tr>td, .table-bordered>thead>tr>th { - border-bottom-width: 2px -} - -.table-striped>tbody>tr:nth-of-type(odd) { - background-color: #f9f9f9 -} - -.table-hover>tbody>tr:hover { - background-color: #f5f5f5 -} - -table col[class*=col-] { - position: static; - display: table-column; - float: none -} - -table td[class*=col-], table th[class*=col-] { - position: static; - display: table-cell; - float: none -} - -.table>tbody>tr.active>td, .table>tbody>tr.active>th, .table>tbody>tr>td.active, - .table>tbody>tr>th.active, .table>tfoot>tr.active>td, .table>tfoot>tr.active>th, - .table>tfoot>tr>td.active, .table>tfoot>tr>th.active, .table>thead>tr.active>td, - .table>thead>tr.active>th, .table>thead>tr>td.active, .table>thead>tr>th.active - { - background-color: #f5f5f5 -} - -.table-hover>tbody>tr.active:hover>td, .table-hover>tbody>tr.active:hover>th, - .table-hover>tbody>tr:hover>.active, .table-hover>tbody>tr>td.active:hover, - .table-hover>tbody>tr>th.active:hover { - background-color: #e8e8e8 -} - -.table>tbody>tr.success>td, .table>tbody>tr.success>th, .table>tbody>tr>td.success, - .table>tbody>tr>th.success, .table>tfoot>tr.success>td, .table>tfoot>tr.success>th, - .table>tfoot>tr>td.success, .table>tfoot>tr>th.success, .table>thead>tr.success>td, - .table>thead>tr.success>th, .table>thead>tr>td.success, .table>thead>tr>th.success - { - background-color: #dff0d8 -} - -.table-hover>tbody>tr.success:hover>td, .table-hover>tbody>tr.success:hover>th, - .table-hover>tbody>tr:hover>.success, .table-hover>tbody>tr>td.success:hover, - .table-hover>tbody>tr>th.success:hover { - background-color: #d0e9c6 -} - -.table>tbody>tr.info>td, .table>tbody>tr.info>th, .table>tbody>tr>td.info, - .table>tbody>tr>th.info, .table>tfoot>tr.info>td, .table>tfoot>tr.info>th, - .table>tfoot>tr>td.info, .table>tfoot>tr>th.info, .table>thead>tr.info>td, - .table>thead>tr.info>th, .table>thead>tr>td.info, .table>thead>tr>th.info - { - background-color: #d9edf7 -} - -.table-hover>tbody>tr.info:hover>td, .table-hover>tbody>tr.info:hover>th, - .table-hover>tbody>tr:hover>.info, .table-hover>tbody>tr>td.info:hover, - .table-hover>tbody>tr>th.info:hover { - background-color: #c4e3f3 -} - -.table>tbody>tr.warning>td, .table>tbody>tr.warning>th, .table>tbody>tr>td.warning, - .table>tbody>tr>th.warning, .table>tfoot>tr.warning>td, .table>tfoot>tr.warning>th, - .table>tfoot>tr>td.warning, .table>tfoot>tr>th.warning, .table>thead>tr.warning>td, - .table>thead>tr.warning>th, .table>thead>tr>td.warning, .table>thead>tr>th.warning - { - background-color: #fcf8e3 -} - -.table-hover>tbody>tr.warning:hover>td, .table-hover>tbody>tr.warning:hover>th, - .table-hover>tbody>tr:hover>.warning, .table-hover>tbody>tr>td.warning:hover, - .table-hover>tbody>tr>th.warning:hover { - background-color: #faf2cc -} - -.table>tbody>tr.danger>td, .table>tbody>tr.danger>th, .table>tbody>tr>td.danger, - .table>tbody>tr>th.danger, .table>tfoot>tr.danger>td, .table>tfoot>tr.danger>th, - .table>tfoot>tr>td.danger, .table>tfoot>tr>th.danger, .table>thead>tr.danger>td, - .table>thead>tr.danger>th, .table>thead>tr>td.danger, .table>thead>tr>th.danger - { - background-color: #f2dede -} - -.table-hover>tbody>tr.danger:hover>td, .table-hover>tbody>tr.danger:hover>th, - .table-hover>tbody>tr:hover>.danger, .table-hover>tbody>tr>td.danger:hover, - .table-hover>tbody>tr>th.danger:hover { - background-color: #ebcccc -} - -.table-responsive { - min-height: .01%; - overflow-x: auto -} - -@media screen and (max-width:767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd - } - .table-responsive>.table { - margin-bottom: 0 - } - .table-responsive>.table>tbody>tr>td, .table-responsive>.table>tbody>tr>th, - .table-responsive>.table>tfoot>tr>td, .table-responsive>.table>tfoot>tr>th, - .table-responsive>.table>thead>tr>td, .table-responsive>.table>thead>tr>th - { - white-space: nowrap - } - .table-responsive>.table-bordered { - border: 0 - } - .table-responsive>.table-bordered>tbody>tr>td:first-child, - .table-responsive>.table-bordered>tbody>tr>th:first-child, - .table-responsive>.table-bordered>tfoot>tr>td:first-child, - .table-responsive>.table-bordered>tfoot>tr>th:first-child, - .table-responsive>.table-bordered>thead>tr>td:first-child, - .table-responsive>.table-bordered>thead>tr>th:first-child { - border-left: 0 - } - .table-responsive>.table-bordered>tbody>tr>td:last-child, - .table-responsive>.table-bordered>tbody>tr>th:last-child, - .table-responsive>.table-bordered>tfoot>tr>td:last-child, - .table-responsive>.table-bordered>tfoot>tr>th:last-child, - .table-responsive>.table-bordered>thead>tr>td:last-child, - .table-responsive>.table-bordered>thead>tr>th:last-child { - border-right: 0 - } - .table-responsive>.table-bordered>tbody>tr:last-child>td, - .table-responsive>.table-bordered>tbody>tr:last-child>th, - .table-responsive>.table-bordered>tfoot>tr:last-child>td, - .table-responsive>.table-bordered>tfoot>tr:last-child>th { - border-bottom: 0 - } -} - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0 -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5 -} - -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: 700 -} - -input[type=search] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -input[type=checkbox], input[type=radio] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal -} - -input[type=file] { - display: block -} - -input[type=range] { - display: block; - width: 100% -} - -select[multiple], select[size] { - height: auto -} - -input[type=file]:focus, input[type=checkbox]:focus, input[type=radio]:focus - { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555 -} - -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow - ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out - .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s -} - -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px - rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px - rgba(102, 175, 233, .6) -} - -.form-control::-moz-placeholder { - color: #999; - opacity: 1 -} - -.form-control:-ms-input-placeholder { - color: #999 -} - -.form-control::-webkit-input-placeholder { - color: #999 -} - -.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control - { - background-color: #eee; - opacity: 1 -} - -.form-control[disabled], fieldset[disabled] .form-control { - cursor: not-allowed -} - -textarea.form-control { - height: auto -} - -input[type=search] { - -webkit-appearance: none -} - -@media screen and (-webkit-min-device-pixel-ratio:0) { - input[type=date], input[type=time], input[type=datetime-local], input[type=month] - { - line-height: 34px - } - .input-group-sm input[type=date], .input-group-sm input[type=time], - .input-group-sm input[type=datetime-local], .input-group-sm input[type=month], - input[type=date].input-sm, input[type=time].input-sm, input[type=datetime-local].input-sm, - input[type=month].input-sm { - line-height: 30px - } - .input-group-lg input[type=date], .input-group-lg input[type=time], - .input-group-lg input[type=datetime-local], .input-group-lg input[type=month], - input[type=date].input-lg, input[type=time].input-lg, input[type=datetime-local].input-lg, - input[type=month].input-lg { - line-height: 46px - } -} - -.form-group { - margin-bottom: 15px -} - -.checkbox, .radio { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px -} - -.checkbox label, .radio label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - cursor: pointer -} - -.checkbox input[type=checkbox], .checkbox-inline input[type=checkbox], - .radio input[type=radio], .radio-inline input[type=radio] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px -} - -.checkbox+.checkbox, .radio+.radio { - margin-top: -5px -} - -.checkbox-inline, .radio-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - vertical-align: middle; - cursor: pointer -} - -.checkbox-inline+.checkbox-inline, .radio-inline+.radio-inline { - margin-top: 0; - margin-left: 10px -} - -fieldset[disabled] input[type=checkbox], fieldset[disabled] input[type=radio], - input[type=checkbox].disabled, input[type=checkbox][disabled], input[type=radio].disabled, - input[type=radio][disabled] { - cursor: not-allowed -} - -.checkbox-inline.disabled, .radio-inline.disabled, fieldset[disabled] .checkbox-inline, - fieldset[disabled] .radio-inline { - cursor: not-allowed -} - -.checkbox.disabled label, .radio.disabled label, fieldset[disabled] .checkbox label, - fieldset[disabled] .radio label { - cursor: not-allowed -} - -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0 -} - -.form-control-static.input-lg, .form-control-static.input-sm { - padding-right: 0; - padding-left: 0 -} - -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.input-sm { - height: 30px; - line-height: 30px -} - -select[multiple].input-sm, textarea.input-sm { - height: auto -} - -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.form-group-sm .form-control { - height: 30px; - line-height: 30px -} - -select[multiple].form-group-sm .form-control, textarea.form-group-sm .form-control - { - height: auto -} - -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5 -} - -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.input-lg { - height: 46px; - line-height: 46px -} - -select[multiple].input-lg, textarea.input-lg { - height: auto -} - -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.form-group-lg .form-control { - height: 46px; - line-height: 46px -} - -select[multiple].form-group-lg .form-control, textarea.form-group-lg .form-control - { - height: auto -} - -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333 -} - -.has-feedback { - position: relative -} - -.has-feedback .form-control { - padding-right: 42.5px -} - -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none -} - -.input-lg+.form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px -} - -.input-sm+.form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px -} - -.has-success .checkbox, .has-success .checkbox-inline, .has-success .control-label, - .has-success .help-block, .has-success .radio, .has-success .radio-inline, - .has-success.checkbox label, .has-success.checkbox-inline label, - .has-success.radio label, .has-success.radio-inline label { - color: #3c763d -} - -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168 -} - -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d -} - -.has-success .form-control-feedback { - color: #3c763d -} - -.has-warning .checkbox, .has-warning .checkbox-inline, .has-warning .control-label, - .has-warning .help-block, .has-warning .radio, .has-warning .radio-inline, - .has-warning.checkbox label, .has-warning.checkbox-inline label, - .has-warning.radio label, .has-warning.radio-inline label { - color: #8a6d3b -} - -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b -} - -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b -} - -.has-warning .form-control-feedback { - color: #8a6d3b -} - -.has-error .checkbox, .has-error .checkbox-inline, .has-error .control-label, - .has-error .help-block, .has-error .radio, .has-error .radio-inline, - .has-error.checkbox label, .has-error.checkbox-inline label, .has-error.radio label, - .has-error.radio-inline label { - color: #a94442 -} - -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483 -} - -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442 -} - -.has-error .form-control-feedback { - color: #a94442 -} - -.has-feedback label ~.form-control-feedback { - top: 25px -} - -.has-feedback label.sr-only ~.form-control-feedback { - top: 0 -} - -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373 -} - -@media ( min-width :768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle - } - .form-inline .form-control-static { - display: inline-block - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle - } - .form-inline .input-group .form-control, .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn { - width: auto - } - .form-inline .input-group>.form-control { - width: 100% - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle - } - .form-inline .checkbox, .form-inline .radio { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle - } - .form-inline .checkbox label, .form-inline .radio label { - padding-left: 0 - } - .form-inline .checkbox input[type=checkbox], .form-inline .radio input[type=radio] - { - position: relative; - margin-left: 0 - } - .form-inline .has-feedback .form-control-feedback { - top: 0 - } -} - -.form-horizontal .checkbox, .form-horizontal .checkbox-inline, - .form-horizontal .radio, .form-horizontal .radio-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0 -} - -.form-horizontal .checkbox, .form-horizontal .radio { - min-height: 27px -} - -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px -} - -@media ( min-width :768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right - } -} - -.form-horizontal .has-feedback .form-control-feedback { - right: 15px -} - -@media ( min-width :768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 14.33px - } -} - -@media ( min-width :768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px - } -} - -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px -} - -.btn.active.focus, .btn.active:focus, .btn.focus, .btn:active.focus, - .btn:active:focus, .btn:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -.btn.focus, .btn:focus, .btn:hover { - color: #333; - text-decoration: none -} - -.btn.active, .btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) -} - -.btn.disabled, .btn[disabled], fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity = 65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65 -} - -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc -} - -.btn-default.active, .btn-default.focus, .btn-default:active, - .btn-default:focus, .btn-default:hover, .open>.dropdown-toggle.btn-default - { - color: #333; - background-color: #e6e6e6; - border-color: #adadad -} - -.btn-default.active, .btn-default:active, .open>.dropdown-toggle.btn-default - { - background-image: none -} - -.btn-default.disabled, .btn-default.disabled.active, .btn-default.disabled.focus, - .btn-default.disabled:active, .btn-default.disabled:focus, .btn-default.disabled:hover, - .btn-default[disabled], .btn-default[disabled].active, .btn-default[disabled].focus, - .btn-default[disabled]:active, .btn-default[disabled]:focus, - .btn-default[disabled]:hover, fieldset[disabled] .btn-default, fieldset[disabled] .btn-default.active, - fieldset[disabled] .btn-default.focus, fieldset[disabled] .btn-default:active, - fieldset[disabled] .btn-default:focus, fieldset[disabled] .btn-default:hover - { - background-color: #fff; - border-color: #ccc -} - -.btn-default .badge { - color: #fff; - background-color: #333 -} - -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4 -} - -.btn-primary.active, .btn-primary.focus, .btn-primary:active, - .btn-primary:focus, .btn-primary:hover, .open>.dropdown-toggle.btn-primary - { - color: #fff; - background-color: #286090; - border-color: #204d74 -} - -.btn-primary.active, .btn-primary:active, .open>.dropdown-toggle.btn-primary - { - background-image: none -} - -.btn-primary.disabled, .btn-primary.disabled.active, .btn-primary.disabled.focus, - .btn-primary.disabled:active, .btn-primary.disabled:focus, .btn-primary.disabled:hover, - .btn-primary[disabled], .btn-primary[disabled].active, .btn-primary[disabled].focus, - .btn-primary[disabled]:active, .btn-primary[disabled]:focus, - .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary, fieldset[disabled] .btn-primary.active, - fieldset[disabled] .btn-primary.focus, fieldset[disabled] .btn-primary:active, - fieldset[disabled] .btn-primary:focus, fieldset[disabled] .btn-primary:hover - { - background-color: #337ab7; - border-color: #2e6da4 -} - -.btn-primary .badge { - color: #337ab7; - background-color: #fff -} - -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c -} - -.btn-success.active, .btn-success.focus, .btn-success:active, - .btn-success:focus, .btn-success:hover, .open>.dropdown-toggle.btn-success - { - color: #fff; - background-color: #449d44; - border-color: #398439 -} - -.btn-success.active, .btn-success:active, .open>.dropdown-toggle.btn-success - { - background-image: none -} - -.btn-success.disabled, .btn-success.disabled.active, .btn-success.disabled.focus, - .btn-success.disabled:active, .btn-success.disabled:focus, .btn-success.disabled:hover, - .btn-success[disabled], .btn-success[disabled].active, .btn-success[disabled].focus, - .btn-success[disabled]:active, .btn-success[disabled]:focus, - .btn-success[disabled]:hover, fieldset[disabled] .btn-success, fieldset[disabled] .btn-success.active, - fieldset[disabled] .btn-success.focus, fieldset[disabled] .btn-success:active, - fieldset[disabled] .btn-success:focus, fieldset[disabled] .btn-success:hover - { - background-color: #5cb85c; - border-color: #4cae4c -} - -.btn-success .badge { - color: #5cb85c; - background-color: #fff -} - -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da -} - -.btn-info.active, .btn-info.focus, .btn-info:active, .btn-info:focus, - .btn-info:hover, .open>.dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc -} - -.btn-info.active, .btn-info:active, .open>.dropdown-toggle.btn-info { - background-image: none -} - -.btn-info.disabled, .btn-info.disabled.active, .btn-info.disabled.focus, - .btn-info.disabled:active, .btn-info.disabled:focus, .btn-info.disabled:hover, - .btn-info[disabled], .btn-info[disabled].active, .btn-info[disabled].focus, - .btn-info[disabled]:active, .btn-info[disabled]:focus, .btn-info[disabled]:hover, - fieldset[disabled] .btn-info, fieldset[disabled] .btn-info.active, - fieldset[disabled] .btn-info.focus, fieldset[disabled] .btn-info:active, - fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:hover - { - background-color: #5bc0de; - border-color: #46b8da -} - -.btn-info .badge { - color: #5bc0de; - background-color: #fff -} - -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236 -} - -.btn-warning.active, .btn-warning.focus, .btn-warning:active, - .btn-warning:focus, .btn-warning:hover, .open>.dropdown-toggle.btn-warning - { - color: #fff; - background-color: #ec971f; - border-color: #d58512 -} - -.btn-warning.active, .btn-warning:active, .open>.dropdown-toggle.btn-warning - { - background-image: none -} - -.btn-warning.disabled, .btn-warning.disabled.active, .btn-warning.disabled.focus, - .btn-warning.disabled:active, .btn-warning.disabled:focus, .btn-warning.disabled:hover, - .btn-warning[disabled], .btn-warning[disabled].active, .btn-warning[disabled].focus, - .btn-warning[disabled]:active, .btn-warning[disabled]:focus, - .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning, fieldset[disabled] .btn-warning.active, - fieldset[disabled] .btn-warning.focus, fieldset[disabled] .btn-warning:active, - fieldset[disabled] .btn-warning:focus, fieldset[disabled] .btn-warning:hover - { - background-color: #f0ad4e; - border-color: #eea236 -} - -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff -} - -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a -} - -.btn-danger.active, .btn-danger.focus, .btn-danger:active, .btn-danger:focus, - .btn-danger:hover, .open>.dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925 -} - -.btn-danger.active, .btn-danger:active, .open>.dropdown-toggle.btn-danger - { - background-image: none -} - -.btn-danger.disabled, .btn-danger.disabled.active, .btn-danger.disabled.focus, - .btn-danger.disabled:active, .btn-danger.disabled:focus, .btn-danger.disabled:hover, - .btn-danger[disabled], .btn-danger[disabled].active, .btn-danger[disabled].focus, - .btn-danger[disabled]:active, .btn-danger[disabled]:focus, .btn-danger[disabled]:hover, - fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger.active, - fieldset[disabled] .btn-danger.focus, fieldset[disabled] .btn-danger:active, - fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:hover - { - background-color: #d9534f; - border-color: #d43f3a -} - -.btn-danger .badge { - color: #d9534f; - background-color: #fff -} - -.btn-link { - font-weight: 400; - color: #337ab7; - border-radius: 0 -} - -.btn-link, .btn-link.active, .btn-link:active, .btn-link[disabled], - fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none -} - -.btn-link, .btn-link:active, .btn-link:focus, .btn-link:hover { - border-color: transparent -} - -.btn-link:focus, .btn-link:hover { - color: #23527c; - text-decoration: underline; - background-color: transparent -} - -.btn-link[disabled]:focus, .btn-link[disabled]:hover, fieldset[disabled] .btn-link:focus, - fieldset[disabled] .btn-link:hover { - color: #777; - text-decoration: none -} - -.btn-group-lg>.btn, .btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -.btn-group-sm>.btn, .btn-sm { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -.btn-group-xs>.btn, .btn-xs { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -.btn-block { - display: block; - width: 100% -} - -.btn-block+.btn-block { - margin-top: 5px -} - -input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].btn-block - { - width: 100% -} - -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear -} - -.fade.in { - opacity: 1 -} - -.collapse { - display: none -} - -.collapse.in { - display: block -} - -tr.collapse.in { - display: table-row -} - -tbody.collapse.in { - display: table-row-group -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility -} - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-right: 4px solid transparent; - border-left: 4px solid transparent -} - -.dropdown, .dropup { - position: relative -} - -.dropdown-toggle:focus { - outline: 0 -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175) -} - -.dropdown-menu.pull-right { - right: 0; - left: auto -} - -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5 -} - -.dropdown-menu>li>a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: 400; - line-height: 1.42857143; - color: #333; - white-space: nowrap -} - -.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover { - color: #262626; - text-decoration: none; - background-color: #f5f5f5 -} - -.dropdown-menu>.active>a, .dropdown-menu>.active>a:focus, .dropdown-menu>.active>a:hover - { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0 -} - -.dropdown-menu>.disabled>a, .dropdown-menu>.disabled>a:focus, - .dropdown-menu>.disabled>a:hover { - color: #777 -} - -.dropdown-menu>.disabled>a:focus, .dropdown-menu>.disabled>a:hover { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) -} - -.open>.dropdown-menu { - display: block -} - -.open>a { - outline: 0 -} - -.dropdown-menu-right { - right: 0; - left: auto -} - -.dropdown-menu-left { - right: auto; - left: 0 -} - -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990 -} - -.pull-right>.dropdown-menu { - right: 0; - left: auto -} - -.dropup .caret, .navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px solid -} - -.dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px -} - -@media ( min-width :768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0 - } -} - -.btn-group, .btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle -} - -.btn-group-vertical>.btn, .btn-group>.btn { - position: relative; - float: left -} - -.btn-group-vertical>.btn.active, .btn-group-vertical>.btn:active, - .btn-group-vertical>.btn:focus, .btn-group-vertical>.btn:hover, - .btn-group>.btn.active, .btn-group>.btn:active, .btn-group>.btn:focus, - .btn-group>.btn:hover { - z-index: 2 -} - -.btn-group .btn+.btn, .btn-group .btn+.btn-group, .btn-group .btn-group+.btn, - .btn-group .btn-group+.btn-group { - margin-left: -1px -} - -.btn-toolbar { - margin-left: -5px -} - -.btn-toolbar .btn-group, .btn-toolbar .input-group { - float: left -} - -.btn-toolbar>.btn, .btn-toolbar>.btn-group, .btn-toolbar>.input-group { - margin-left: 5px -} - -.btn-group>.btn:not (:first-child ):not (:last-child ):not (.dropdown-toggle - ){ - border-radius: 0 -} - -.btn-group>.btn:first-child { - margin-left: 0 -} - -.btn-group>.btn:first-child:not (:last-child ):not (.dropdown-toggle ){ - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.btn-group>.btn:last-child:not (:first-child ), .btn-group>.dropdown-toggle:not - (:first-child ){ - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group>.btn-group { - float: left -} - -.btn-group>.btn-group:not (:first-child ):not (:last-child )>.btn { - border-radius: 0 -} - -.btn-group>.btn-group:first-child:not (:last-child )>.btn:last-child, - .btn-group>.btn-group:first-child:not (:last-child )>.dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.btn-group>.btn-group:last-child:not (:first-child )>.btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { - outline: 0 -} - -.btn-group>.btn+.dropdown-toggle { - padding-right: 8px; - padding-left: 8px -} - -.btn-group>.btn-lg+.dropdown-toggle { - padding-right: 12px; - padding-left: 12px -} - -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) -} - -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none -} - -.btn .caret { - margin-left: 0 -} - -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0 -} - -.dropup .btn-lg .caret { - border-width: 0 5px 5px -} - -.btn-group-vertical>.btn, .btn-group-vertical>.btn-group, - .btn-group-vertical>.btn-group>.btn { - display: block; - float: none; - width: 100%; - max-width: 100% -} - -.btn-group-vertical>.btn-group>.btn { - float: none -} - -.btn-group-vertical>.btn+.btn, .btn-group-vertical>.btn+.btn-group, - .btn-group-vertical>.btn-group+.btn, .btn-group-vertical>.btn-group+.btn-group - { - margin-top: -1px; - margin-left: 0 -} - -.btn-group-vertical>.btn:not (:first-child ):not (:last-child ){ - border-radius: 0 -} - -.btn-group-vertical>.btn:first-child:not (:last-child ){ - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group-vertical>.btn:last-child:not (:first-child ){ - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px -} - -.btn-group-vertical>.btn-group:not (:first-child ):not (:last-child )>.btn - { - border-radius: 0 -} - -.btn-group-vertical>.btn-group:first-child:not (:last-child )>.btn:last-child, - .btn-group-vertical>.btn-group:first-child:not (:last-child )>.dropdown-toggle - { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group-vertical>.btn-group:last-child:not (:first-child )>.btn:first-child - { - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate -} - -.btn-group-justified>.btn, .btn-group-justified>.btn-group { - display: table-cell; - float: none; - width: 1% -} - -.btn-group-justified>.btn-group .btn { - width: 100% -} - -.btn-group-justified>.btn-group .dropdown-menu { - left: auto -} - -[data-toggle=buttons]>.btn input[type=checkbox], [data-toggle=buttons]>.btn input[type=radio], - [data-toggle=buttons]>.btn-group>.btn input[type=checkbox], [data-toggle=buttons]>.btn-group>.btn input[type=radio] - { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none -} - -.input-group { - position: relative; - display: table; - border-collapse: separate -} - -.input-group[class*=col-] { - float: none; - padding-right: 0; - padding-left: 0 -} - -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0 -} - -.input-group-lg>.form-control, .input-group-lg>.input-group-addon, - .input-group-lg>.input-group-btn>.btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.input-group-lg>.form-control, select.input-group-lg>.input-group-addon, - select.input-group-lg>.input-group-btn>.btn { - height: 46px; - line-height: 46px -} - -select[multiple].input-group-lg>.form-control, select[multiple].input-group-lg>.input-group-addon, - select[multiple].input-group-lg>.input-group-btn>.btn, textarea.input-group-lg>.form-control, - textarea.input-group-lg>.input-group-addon, textarea.input-group-lg>.input-group-btn>.btn - { - height: auto -} - -.input-group-sm>.form-control, .input-group-sm>.input-group-addon, - .input-group-sm>.input-group-btn>.btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.input-group-sm>.form-control, select.input-group-sm>.input-group-addon, - select.input-group-sm>.input-group-btn>.btn { - height: 30px; - line-height: 30px -} - -select[multiple].input-group-sm>.form-control, select[multiple].input-group-sm>.input-group-addon, - select[multiple].input-group-sm>.input-group-btn>.btn, textarea.input-group-sm>.form-control, - textarea.input-group-sm>.input-group-addon, textarea.input-group-sm>.input-group-btn>.btn - { - height: auto -} - -.input-group .form-control, .input-group-addon, .input-group-btn { - display: table-cell -} - -.input-group .form-control:not (:first-child ):not (:last-child ), - .input-group-addon:not (:first-child ):not (:last-child ), - .input-group-btn:not (:first-child ):not (:last-child ){ - border-radius: 0 -} - -.input-group-addon, .input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle -} - -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: 400; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px -} - -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px -} - -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px -} - -.input-group-addon input[type=checkbox], .input-group-addon input[type=radio] - { - margin-top: 0 -} - -.input-group .form-control:first-child, .input-group-addon:first-child, - .input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group>.btn, - .input-group-btn:first-child>.dropdown-toggle, .input-group-btn:last-child>.btn-group:not - (:last-child )>.btn, .input-group-btn:last-child>.btn:not (:last-child - ):not (.dropdown-toggle ){ - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.input-group-addon:first-child { - border-right: 0 -} - -.input-group .form-control:last-child, .input-group-addon:last-child, - .input-group-btn:first-child>.btn-group:not (:first-child )>.btn, - .input-group-btn:first-child>.btn:not (:first-child ), .input-group-btn:last-child>.btn, - .input-group-btn:last-child>.btn-group>.btn, .input-group-btn:last-child>.dropdown-toggle - { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.input-group-addon:last-child { - border-left: 0 -} - -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap -} - -.input-group-btn>.btn { - position: relative -} - -.input-group-btn>.btn+.btn { - margin-left: -1px -} - -.input-group-btn>.btn:active, .input-group-btn>.btn:focus, - .input-group-btn>.btn:hover { - z-index: 2 -} - -.input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group - { - margin-right: -1px -} - -.input-group-btn:last-child>.btn, .input-group-btn:last-child>.btn-group - { - margin-left: -1px -} - -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none -} - -.nav>li { - position: relative; - display: block -} - -.nav>li>a { - position: relative; - display: block; - padding: 10px 15px -} - -.nav>li>a:focus, .nav>li>a:hover { - text-decoration: none; - background-color: #eee -} - -.nav>li.disabled>a { - color: #777 -} - -.nav>li.disabled>a:focus, .nav>li.disabled>a:hover { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent -} - -.nav .open>a, .nav .open>a:focus, .nav .open>a:hover { - background-color: #eee; - border-color: #337ab7 -} - -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5 -} - -.nav>li>a>img { - max-width: none -} - -.nav-tabs { - border-bottom: 1px solid #ddd -} - -.nav-tabs>li { - float: left; - margin-bottom: -1px -} - -.nav-tabs>li>a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0 -} - -.nav-tabs>li>a:hover { - border-color: #eee #eee #ddd -} - -.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover - { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent -} - -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0 -} - -.nav-tabs.nav-justified>li { - float: none -} - -.nav-tabs.nav-justified>li>a { - margin-bottom: 5px; - text-align: center -} - -.nav-tabs.nav-justified>.dropdown .dropdown-menu { - top: auto; - left: auto -} - -@media ( min-width :768px) { - .nav-tabs.nav-justified>li { - display: table-cell; - width: 1% - } - .nav-tabs.nav-justified>li>a { - margin-bottom: 0 - } -} - -.nav-tabs.nav-justified>li>a { - margin-right: 0; - border-radius: 4px -} - -.nav-tabs.nav-justified>.active>a, .nav-tabs.nav-justified>.active>a:focus, - .nav-tabs.nav-justified>.active>a:hover { - border: 1px solid #ddd -} - -@media ( min-width :768px) { - .nav-tabs.nav-justified>li>a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0 - } - .nav-tabs.nav-justified>.active>a, .nav-tabs.nav-justified>.active>a:focus, - .nav-tabs.nav-justified>.active>a:hover { - border-bottom-color: #fff - } -} - -.nav-pills>li { - float: left -} - -.nav-pills>li>a { - border-radius: 4px -} - -.nav-pills>li+li { - margin-left: 2px -} - -.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover - { - color: #fff; - background-color: #337ab7 -} - -.nav-stacked>li { - float: none -} - -.nav-stacked>li+li { - margin-top: 2px; - margin-left: 0 -} - -.nav-justified { - width: 100% -} - -.nav-justified>li { - float: none -} - -.nav-justified>li>a { - margin-bottom: 5px; - text-align: center -} - -.nav-justified>.dropdown .dropdown-menu { - top: auto; - left: auto -} - -@media ( min-width :768px) { - .nav-justified>li { - display: table-cell; - width: 1% - } - .nav-justified>li>a { - margin-bottom: 0 - } -} - -.nav-tabs-justified { - border-bottom: 0 -} - -.nav-tabs-justified>li>a { - margin-right: 0; - border-radius: 4px -} - -.nav-tabs-justified>.active>a, .nav-tabs-justified>.active>a:focus, - .nav-tabs-justified>.active>a:hover { - border: 1px solid #ddd -} - -@media ( min-width :768px) { - .nav-tabs-justified>li>a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0 - } - .nav-tabs-justified>.active>a, .nav-tabs-justified>.active>a:focus, - .nav-tabs-justified>.active>a:hover { - border-bottom-color: #fff - } -} - -.tab-content>.tab-pane { - display: none -} - -.tab-content>.active { - display: block -} - -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent -} - -@media ( min-width :768px) { - .navbar { - border-radius: 4px - } -} - -@media ( min-width :768px) { - .navbar-header { - float: left - } -} - -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1) -} - -.navbar-collapse.in { - overflow-y: auto -} - -@media ( min-width :768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important - } - .navbar-collapse.in { - overflow-y: visible - } - .navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse { - padding-right: 0; - padding-left: 0 - } -} - -.navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse - { - max-height: 340px -} - -@media ( max-device-width :480px)and (orientation:landscape) { - .navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse - { - max-height: 200px - } -} - -.container-fluid>.navbar-collapse, .container-fluid>.navbar-header, - .container>.navbar-collapse, .container>.navbar-header { - margin-right: -15px; - margin-left: -15px -} - -@media ( min-width :768px) { - .container-fluid>.navbar-collapse, .container-fluid>.navbar-header, - .container>.navbar-collapse, .container>.navbar-header { - margin-right: 0; - margin-left: 0 - } -} - -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px -} - -@media ( min-width :768px) { - .navbar-static-top { - border-radius: 0 - } -} - -.navbar-fixed-bottom, .navbar-fixed-top { - position: fixed; - right: 0; - left: 0; - z-index: 1030 -} - -@media ( min-width :768px) { - .navbar-fixed-bottom, .navbar-fixed-top { - border-radius: 0 - } -} - -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px -} - -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0 -} - -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px -} - -.navbar-brand:focus, .navbar-brand:hover { - text-decoration: none -} - -.navbar-brand>img { - display: block -} - -@media ( min-width :768px) { - .navbar>.container .navbar-brand, .navbar>.container-fluid .navbar-brand - { - margin-left: -15px - } -} - -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px -} - -.navbar-toggle:focus { - outline: 0 -} - -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px -} - -.navbar-toggle .icon-bar+.icon-bar { - margin-top: 4px -} - -@media ( min-width :768px) { - .navbar-toggle { - display: none - } -} - -.navbar-nav { - margin: 7.5px -15px -} - -.navbar-nav>li>a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px -} - -@media ( max-width :767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none - } - .navbar-nav .open .dropdown-menu .dropdown-header, .navbar-nav .open .dropdown-menu>li>a - { - padding: 5px 15px 5px 25px - } - .navbar-nav .open .dropdown-menu>li>a { - line-height: 20px - } - .navbar-nav .open .dropdown-menu>li>a:focus, .navbar-nav .open .dropdown-menu>li>a:hover - { - background-image: none - } -} - -@media ( min-width :768px) { - .navbar-nav { - float: left; - margin: 0 - } - .navbar-nav>li { - float: left - } - .navbar-nav>li>a { - padding-top: 15px; - padding-bottom: 15px - } -} - -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 - rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 - rgba(255, 255, 255, .1) -} - -@media ( min-width :768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle - } - .navbar-form .form-control-static { - display: inline-block - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle - } - .navbar-form .input-group .form-control, .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn { - width: auto - } - .navbar-form .input-group>.form-control { - width: 100% - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .checkbox, .navbar-form .radio { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .checkbox label, .navbar-form .radio label { - padding-left: 0 - } - .navbar-form .checkbox input[type=checkbox], .navbar-form .radio input[type=radio] - { - position: relative; - margin-left: 0 - } - .navbar-form .has-feedback .form-control-feedback { - top: 0 - } -} - -@media ( max-width :767px) { - .navbar-form .form-group { - margin-bottom: 5px - } - .navbar-form .form-group:last-child { - margin-bottom: 0 - } -} - -@media ( min-width :768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none - } -} - -.navbar-nav>li>.dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px -} - -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px -} - -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px -} - -.navbar-text { - margin-top: 15px; - margin-bottom: 15px -} - -@media ( min-width :768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px - } -} - -@media ( min-width :768px) { - .navbar-left { - float: left !important - } - .navbar-right { - float: right !important; - margin-right: -15px - } - .navbar-right ~.navbar-right { - margin-right: 0 - } -} - -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7 -} - -.navbar-default .navbar-brand { - color: #777 -} - -.navbar-default .navbar-brand:focus, .navbar-default .navbar-brand:hover - { - color: #5e5e5e; - background-color: transparent -} - -.navbar-default .navbar-text { - color: #777 -} - -.navbar-default .navbar-nav>li>a { - color: #777 -} - -.navbar-default .navbar-nav>li>a:focus, .navbar-default .navbar-nav>li>a:hover - { - color: #333; - background-color: transparent -} - -.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, - .navbar-default .navbar-nav>.active>a:hover { - color: #555; - background-color: #e7e7e7 -} - -.navbar-default .navbar-nav>.disabled>a, .navbar-default .navbar-nav>.disabled>a:focus, - .navbar-default .navbar-nav>.disabled>a:hover { - color: #ccc; - background-color: transparent -} - -.navbar-default .navbar-toggle { - border-color: #ddd -} - -.navbar-default .navbar-toggle:focus, .navbar-default .navbar-toggle:hover - { - background-color: #ddd -} - -.navbar-default .navbar-toggle .icon-bar { - background-color: #888 -} - -.navbar-default .navbar-collapse, .navbar-default .navbar-form { - border-color: #e7e7e7 -} - -.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, - .navbar-default .navbar-nav>.open>a:hover { - color: #555; - background-color: #e7e7e7 -} - -@media ( max-width :767px) { - .navbar-default .navbar-nav .open .dropdown-menu>li>a { - color: #777 - } - .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>li>a:hover { - color: #333; - background-color: transparent - } - .navbar-default .navbar-nav .open .dropdown-menu>.active>a, - .navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover { - color: #555; - background-color: #e7e7e7 - } - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a, - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover { - color: #ccc; - background-color: transparent - } -} - -.navbar-default .navbar-link { - color: #777 -} - -.navbar-default .navbar-link:hover { - color: #333 -} - -.navbar-default .btn-link { - color: #777 -} - -.navbar-default .btn-link:focus, .navbar-default .btn-link:hover { - color: #333 -} - -.navbar-default .btn-link[disabled]:focus, .navbar-default .btn-link[disabled]:hover, - fieldset[disabled] .navbar-default .btn-link:focus, fieldset[disabled] .navbar-default .btn-link:hover - { - color: #ccc -} - -.navbar-inverse { - background-color: #222; - border-color: #080808 -} - -.navbar-inverse .navbar-brand { - color: #9d9d9d -} - -.navbar-inverse .navbar-brand:focus, .navbar-inverse .navbar-brand:hover - { - color: #fff; - background-color: transparent -} - -.navbar-inverse .navbar-text { - color: #9d9d9d -} - -.navbar-inverse .navbar-nav>li>a { - color: #9d9d9d -} - -.navbar-inverse .navbar-nav>li>a:focus, .navbar-inverse .navbar-nav>li>a:hover - { - color: #fff; - background-color: transparent -} - -.navbar-inverse .navbar-nav>.active>a, .navbar-inverse .navbar-nav>.active>a:focus, - .navbar-inverse .navbar-nav>.active>a:hover { - color: #fff; - background-color: #080808 -} - -.navbar-inverse .navbar-nav>.disabled>a, .navbar-inverse .navbar-nav>.disabled>a:focus, - .navbar-inverse .navbar-nav>.disabled>a:hover { - color: #444; - background-color: transparent -} - -.navbar-inverse .navbar-toggle { - border-color: #333 -} - -.navbar-inverse .navbar-toggle:focus, .navbar-inverse .navbar-toggle:hover - { - background-color: #333 -} - -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff -} - -.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { - border-color: #101010 -} - -.navbar-inverse .navbar-nav>.open>a, .navbar-inverse .navbar-nav>.open>a:focus, - .navbar-inverse .navbar-nav>.open>a:hover { - color: #fff; - background-color: #080808 -} - -@media ( max-width :767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header { - border-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a { - color: #9d9d9d - } - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover { - color: #fff; - background-color: transparent - } - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a, - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover { - color: #fff; - background-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a, - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover { - color: #444; - background-color: transparent - } -} - -.navbar-inverse .navbar-link { - color: #9d9d9d -} - -.navbar-inverse .navbar-link:hover { - color: #fff -} - -.navbar-inverse .btn-link { - color: #9d9d9d -} - -.navbar-inverse .btn-link:focus, .navbar-inverse .btn-link:hover { - color: #fff -} - -.navbar-inverse .btn-link[disabled]:focus, .navbar-inverse .btn-link[disabled]:hover, - fieldset[disabled] .navbar-inverse .btn-link:focus, fieldset[disabled] .navbar-inverse .btn-link:hover - { - color: #444 -} - -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px -} - -.breadcrumb>li { - display: inline-block -} - -.breadcrumb>li+li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0" -} - -.breadcrumb>.active { - color: #777 -} - -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px -} - -.pagination>li { - display: inline -} - -.pagination>li>a, .pagination>li>span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd -} - -.pagination>li:first-child>a, .pagination>li:first-child>span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px -} - -.pagination>li:last-child>a, .pagination>li:last-child>span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px -} - -.pagination>li>a:focus, .pagination>li>a:hover, .pagination>li>span:focus, - .pagination>li>span:hover { - color: #23527c; - background-color: #eee; - border-color: #ddd -} - -.pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, - .pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover - { - z-index: 2; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7 -} - -.pagination>.disabled>a, .pagination>.disabled>a:focus, .pagination>.disabled>a:hover, - .pagination>.disabled>span, .pagination>.disabled>span:focus, - .pagination>.disabled>span:hover { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd -} - -.pagination-lg>li>a, .pagination-lg>li>span { - padding: 10px 16px; - font-size: 18px -} - -.pagination-lg>li:first-child>a, .pagination-lg>li:first-child>span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px -} - -.pagination-lg>li:last-child>a, .pagination-lg>li:last-child>span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px -} - -.pagination-sm>li>a, .pagination-sm>li>span { - padding: 5px 10px; - font-size: 12px -} - -.pagination-sm>li:first-child>a, .pagination-sm>li:first-child>span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px -} - -.pagination-sm>li:last-child>a, .pagination-sm>li:last-child>span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px -} - -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none -} - -.pager li { - display: inline -} - -.pager li>a, .pager li>span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px -} - -.pager li>a:focus, .pager li>a:hover { - text-decoration: none; - background-color: #eee -} - -.pager .next>a, .pager .next>span { - float: right -} - -.pager .previous>a, .pager .previous>span { - float: left -} - -.pager .disabled>a, .pager .disabled>a:focus, .pager .disabled>a:hover, - .pager .disabled>span { - color: #777; - cursor: not-allowed; - background-color: #fff -} - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em -} - -a.label:focus, a.label:hover { - color: #fff; - text-decoration: none; - cursor: pointer -} - -.label:empty { - display: none -} - -.btn .label { - position: relative; - top: -1px -} - -.label-default { - background-color: #777 -} - -.label-default[href]:focus, .label-default[href]:hover { - background-color: #5e5e5e -} - -.label-primary { - background-color: #337ab7 -} - -.label-primary[href]:focus, .label-primary[href]:hover { - background-color: #286090 -} - -.label-success { - background-color: #5cb85c -} - -.label-success[href]:focus, .label-success[href]:hover { - background-color: #449d44 -} - -.label-info { - background-color: #5bc0de -} - -.label-info[href]:focus, .label-info[href]:hover { - background-color: #31b0d5 -} - -.label-warning { - background-color: #f0ad4e -} - -.label-warning[href]:focus, .label-warning[href]:hover { - background-color: #ec971f -} - -.label-danger { - background-color: #d9534f -} - -.label-danger[href]:focus, .label-danger[href]:hover { - background-color: #c9302c -} - -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #777; - border-radius: 10px -} - -.badge:empty { - display: none -} - -.btn .badge { - position: relative; - top: -1px -} - -.btn-group-xs>.btn .badge, .btn-xs .badge { - top: 0; - padding: 1px 5px -} - -a.badge:focus, a.badge:hover { - color: #fff; - text-decoration: none; - cursor: pointer -} - -.list-group-item.active>.badge, .nav-pills>.active>a>.badge { - color: #337ab7; - background-color: #fff -} - -.list-group-item>.badge { - float: right -} - -.list-group-item>.badge+.badge { - margin-right: 5px -} - -.nav-pills>li>a>.badge { - margin-left: 3px -} - -.jumbotron { - padding: 30px 15px; - margin-bottom: 30px; - color: inherit; - background-color: #eee -} - -.jumbotron .h1, .jumbotron h1 { - color: inherit -} - -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200 -} - -.jumbotron>hr { - border-top-color: #d5d5d5 -} - -.container .jumbotron, .container-fluid .jumbotron { - border-radius: 6px -} - -.jumbotron .container { - max-width: 100% -} - -@media screen and (min-width:768px) { - .jumbotron { - padding: 48px 0 - } - .container .jumbotron, .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px - } - .jumbotron .h1, .jumbotron h1 { - font-size: 63px - } -} - -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out -} - -.thumbnail a>img, .thumbnail>img { - margin-right: auto; - margin-left: auto -} - -a.thumbnail.active, a.thumbnail:focus, a.thumbnail:hover { - border-color: #337ab7 -} - -.thumbnail .caption { - padding: 9px; - color: #333 -} - -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px -} - -.alert h4 { - margin-top: 0; - color: inherit -} - -.alert .alert-link { - font-weight: 700 -} - -.alert>p, .alert>ul { - margin-bottom: 0 -} - -.alert>p+p { - margin-top: 5px -} - -.alert-dismissable, .alert-dismissible { - padding-right: 35px -} - -.alert-dismissable .close, .alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit -} - -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6 -} - -.alert-success hr { - border-top-color: #c9e2b3 -} - -.alert-success .alert-link { - color: #2b542c -} - -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1 -} - -.alert-info hr { - border-top-color: #a6e1ec -} - -.alert-info .alert-link { - color: #245269 -} - -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc -} - -.alert-warning hr { - border-top-color: #f7e1b5 -} - -.alert-warning .alert-link { - color: #66512c -} - -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1 -} - -.alert-danger hr { - border-top-color: #e4b9c0 -} - -.alert-danger .alert-link { - color: #843534 -} - -@ --webkit-keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -@ --o-keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -@ -keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1) -} - -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease -} - -.progress-bar-striped, .progress-striped .progress-bar { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px -} - -.progress-bar.active, .progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite -} - -.progress-bar-success { - background-color: #5cb85c -} - -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-info { - background-color: #5bc0de -} - -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-warning { - background-color: #f0ad4e -} - -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-danger { - background-color: #d9534f -} - -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.media { - margin-top: 15px -} - -.media:first-child { - margin-top: 0 -} - -.media, .media-body { - overflow: hidden; - zoom: 1 -} - -.media-body { - width: 10000px -} - -.media-object { - display: block -} - -.media-right, .media>.pull-right { - padding-left: 10px -} - -.media-left, .media>.pull-left { - padding-right: 10px -} - -.media-body, .media-left, .media-right { - display: table-cell; - vertical-align: top -} - -.media-middle { - vertical-align: middle -} - -.media-bottom { - vertical-align: bottom -} - -.media-heading { - margin-top: 0; - margin-bottom: 5px -} - -.media-list { - padding-left: 0; - list-style: none -} - -.list-group { - padding-left: 0; - margin-bottom: 20px -} - -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd -} - -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px -} - -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px -} - -a.list-group-item { - color: #555 -} - -a.list-group-item .list-group-item-heading { - color: #333 -} - -a.list-group-item:focus, a.list-group-item:hover { - color: #555; - text-decoration: none; - background-color: #f5f5f5 -} - -.list-group-item.disabled, .list-group-item.disabled:focus, - .list-group-item.disabled:hover { - color: #777; - cursor: not-allowed; - background-color: #eee -} - -.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, - .list-group-item.disabled:hover .list-group-item-heading { - color: inherit -} - -.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, - .list-group-item.disabled:hover .list-group-item-text { - color: #777 -} - -.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover - { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7 -} - -.list-group-item.active .list-group-item-heading, .list-group-item.active .list-group-item-heading>.small, - .list-group-item.active .list-group-item-heading>small, - .list-group-item.active:focus .list-group-item-heading, - .list-group-item.active:focus .list-group-item-heading>.small, - .list-group-item.active:focus .list-group-item-heading>small, - .list-group-item.active:hover .list-group-item-heading, - .list-group-item.active:hover .list-group-item-heading>.small, - .list-group-item.active:hover .list-group-item-heading>small { - color: inherit -} - -.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, - .list-group-item.active:hover .list-group-item-text { - color: #c7ddef -} - -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8 -} - -a.list-group-item-success { - color: #3c763d -} - -a.list-group-item-success .list-group-item-heading { - color: inherit -} - -a.list-group-item-success:focus, a.list-group-item-success:hover { - color: #3c763d; - background-color: #d0e9c6 -} - -a.list-group-item-success.active, a.list-group-item-success.active:focus, - a.list-group-item-success.active:hover { - color: #fff; - background-color: #3c763d; - border-color: #3c763d -} - -.list-group-item-info { - color: #31708f; - background-color: #d9edf7 -} - -a.list-group-item-info { - color: #31708f -} - -a.list-group-item-info .list-group-item-heading { - color: inherit -} - -a.list-group-item-info:focus, a.list-group-item-info:hover { - color: #31708f; - background-color: #c4e3f3 -} - -a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover - { - color: #fff; - background-color: #31708f; - border-color: #31708f -} - -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3 -} - -a.list-group-item-warning { - color: #8a6d3b -} - -a.list-group-item-warning .list-group-item-heading { - color: inherit -} - -a.list-group-item-warning:focus, a.list-group-item-warning:hover { - color: #8a6d3b; - background-color: #faf2cc -} - -a.list-group-item-warning.active, a.list-group-item-warning.active:focus, - a.list-group-item-warning.active:hover { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b -} - -.list-group-item-danger { - color: #a94442; - background-color: #f2dede -} - -a.list-group-item-danger { - color: #a94442 -} - -a.list-group-item-danger .list-group-item-heading { - color: inherit -} - -a.list-group-item-danger:focus, a.list-group-item-danger:hover { - color: #a94442; - background-color: #ebcccc -} - -a.list-group-item-danger.active, a.list-group-item-danger.active:focus, - a.list-group-item-danger.active:hover { - color: #fff; - background-color: #a94442; - border-color: #a94442 -} - -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px -} - -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3 -} - -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05) -} - -.panel-body { - padding: 15px -} - -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel-heading>.dropdown .dropdown-toggle { - color: inherit -} - -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit -} - -.panel-title>.small, .panel-title>.small>a, .panel-title>a, .panel-title>small, - .panel-title>small>a { - color: inherit -} - -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.list-group, .panel>.panel-collapse>.list-group { - margin-bottom: 0 -} - -.panel>.list-group .list-group-item, .panel>.panel-collapse>.list-group .list-group-item - { - border-width: 1px 0; - border-radius: 0 -} - -.panel>.list-group:first-child .list-group-item:first-child, .panel>.panel-collapse>.list-group:first-child .list-group-item:first-child - { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.list-group:last-child .list-group-item:last-child, .panel>.panel-collapse>.list-group:last-child .list-group-item:last-child - { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel-heading+.list-group .list-group-item:first-child { - border-top-width: 0 -} - -.list-group+.panel-footer { - border-top-width: 0 -} - -.panel>.panel-collapse>.table, .panel>.table, .panel>.table-responsive>.table - { - margin-bottom: 0 -} - -.panel>.panel-collapse>.table caption, .panel>.table caption, .panel>.table-responsive>.table caption - { - padding-right: 15px; - padding-left: 15px -} - -.panel>.table-responsive:first-child>.table:first-child, .panel>.table:first-child - { - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child, .panel>.table:first-child>thead:first-child>tr:first-child - { - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child, - .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child td:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child th:first-child, - .panel>.table:first-child>thead:first-child>tr:first-child td:first-child, - .panel>.table:first-child>thead:first-child>tr:first-child th:first-child - { - border-top-left-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child, - .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child, - .panel>.table:first-child>tbody:first-child>tr:first-child td:last-child, - .panel>.table:first-child>tbody:first-child>tr:first-child th:last-child, - .panel>.table:first-child>thead:first-child>tr:first-child td:last-child, - .panel>.table:first-child>thead:first-child>tr:first-child th:last-child - { - border-top-right-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child, .panel>.table:last-child - { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child, .panel>.table:last-child>tfoot:last-child>tr:last-child - { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child, - .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child, - .panel>.table:last-child>tbody:last-child>tr:last-child td:first-child, - .panel>.table:last-child>tbody:last-child>tr:last-child th:first-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child - { - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child, - .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child { - border-bottom-right-radius: 3px -} - -.panel>.panel-body+.table, .panel>.panel-body+.table-responsive, .panel>.table+.panel-body, - .panel>.table-responsive+.panel-body { - border-top: 1px solid #ddd -} - -.panel>.table>tbody:first-child>tr:first-child td, .panel>.table>tbody:first-child>tr:first-child th - { - border-top: 0 -} - -.panel>.table-bordered, .panel>.table-responsive>.table-bordered { - border: 0 -} - -.panel>.table-bordered>tbody>tr>td:first-child, .panel>.table-bordered>tbody>tr>th:first-child, - .panel>.table-bordered>tfoot>tr>td:first-child, .panel>.table-bordered>tfoot>tr>th:first-child, - .panel>.table-bordered>thead>tr>td:first-child, .panel>.table-bordered>thead>tr>th:first-child, - .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child, - .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child, - .panel>.table-responsive>.table-bordered>thead>tr>td:first-child, - .panel>.table-responsive>.table-bordered>thead>tr>th:first-child { - border-left: 0 -} - -.panel>.table-bordered>tbody>tr>td:last-child, .panel>.table-bordered>tbody>tr>th:last-child, - .panel>.table-bordered>tfoot>tr>td:last-child, .panel>.table-bordered>tfoot>tr>th:last-child, - .panel>.table-bordered>thead>tr>td:last-child, .panel>.table-bordered>thead>tr>th:last-child, - .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child, .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child, .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child, - .panel>.table-responsive>.table-bordered>thead>tr>td:last-child, .panel>.table-responsive>.table-bordered>thead>tr>th:last-child - { - border-right: 0 -} - -.panel>.table-bordered>tbody>tr:first-child>td, .panel>.table-bordered>tbody>tr:first-child>th, - .panel>.table-bordered>thead>tr:first-child>td, .panel>.table-bordered>thead>tr:first-child>th, - .panel>.table-responsive>.table-bordered>tbody>tr:first-child>td, - .panel>.table-responsive>.table-bordered>tbody>tr:first-child>th, - .panel>.table-responsive>.table-bordered>thead>tr:first-child>td, - .panel>.table-responsive>.table-bordered>thead>tr:first-child>th { - border-bottom: 0 -} - -.panel>.table-bordered>tbody>tr:last-child>td, .panel>.table-bordered>tbody>tr:last-child>th, - .panel>.table-bordered>tfoot>tr:last-child>td, .panel>.table-bordered>tfoot>tr:last-child>th, - .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td, .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th, - .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td, .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th - { - border-bottom: 0 -} - -.panel>.table-responsive { - margin-bottom: 0; - border: 0 -} - -.panel-group { - margin-bottom: 20px -} - -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px -} - -.panel-group .panel+.panel { - margin-top: 5px -} - -.panel-group .panel-heading { - border-bottom: 0 -} - -.panel-group .panel-heading+.panel-collapse>.list-group, .panel-group .panel-heading+.panel-collapse>.panel-body - { - border-top: 1px solid #ddd -} - -.panel-group .panel-footer { - border-top: 0 -} - -.panel-group .panel-footer+.panel-collapse .panel-body { - border-bottom: 1px solid #ddd -} - -.panel-default { - border-color: #ddd -} - -.panel-default>.panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd -} - -.panel-default>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #ddd -} - -.panel-default>.panel-heading .badge { - color: #f5f5f5; - background-color: #333 -} - -.panel-default>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #ddd -} - -.panel-primary { - border-color: #337ab7 -} - -.panel-primary>.panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7 -} - -.panel-primary>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #337ab7 -} - -.panel-primary>.panel-heading .badge { - color: #337ab7; - background-color: #fff -} - -.panel-primary>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #337ab7 -} - -.panel-success { - border-color: #d6e9c6 -} - -.panel-success>.panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6 -} - -.panel-success>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #d6e9c6 -} - -.panel-success>.panel-heading .badge { - color: #dff0d8; - background-color: #3c763d -} - -.panel-success>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #d6e9c6 -} - -.panel-info { - border-color: #bce8f1 -} - -.panel-info>.panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1 -} - -.panel-info>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #bce8f1 -} - -.panel-info>.panel-heading .badge { - color: #d9edf7; - background-color: #31708f -} - -.panel-info>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #bce8f1 -} - -.panel-warning { - border-color: #faebcc -} - -.panel-warning>.panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc -} - -.panel-warning>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #faebcc -} - -.panel-warning>.panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b -} - -.panel-warning>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #faebcc -} - -.panel-danger { - border-color: #ebccd1 -} - -.panel-danger>.panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1 -} - -.panel-danger>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #ebccd1 -} - -.panel-danger>.panel-heading .badge { - color: #f2dede; - background-color: #a94442 -} - -.panel-danger>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #ebccd1 -} - -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden -} - -.embed-responsive .embed-responsive-item, .embed-responsive embed, - .embed-responsive iframe, .embed-responsive object, .embed-responsive video - { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0 -} - -.embed-responsive-16by9 { - padding-bottom: 56.25% -} - -.embed-responsive-4by3 { - padding-bottom: 75% -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05) -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15) -} - -.well-lg { - padding: 24px; - border-radius: 6px -} - -.well-sm { - padding: 9px; - border-radius: 3px -} - -.close { - float: right; - font-size: 21px; - font-weight: 700; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity = 20); - opacity: .2 -} - -.close:focus, .close:hover { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity = 50); - opacity: .5 -} - -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: 0 0; - border: 0 -} - -.modal-open { - overflow: hidden -} - -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0 -} - -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%) -} - -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0) -} - -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto -} - -.modal-dialog { - position: relative; - width: auto; - margin: 10px -} - -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5) -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000 -} - -.modal-backdrop.fade { - filter: alpha(opacity = 0); - opacity: 0 -} - -.modal-backdrop.in { - filter: alpha(opacity = 50); - opacity: .5 -} - -.modal-header { - min-height: 16.43px; - padding: 15px; - border-bottom: 1px solid #e5e5e5 -} - -.modal-header .close { - margin-top: -2px -} - -.modal-title { - margin: 0; - line-height: 1.42857143 -} - -.modal-body { - position: relative; - padding: 15px -} - -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5 -} - -.modal-footer .btn+.btn { - margin-bottom: 0; - margin-left: 5px -} - -.modal-footer .btn-group .btn+.btn { - margin-left: -1px -} - -.modal-footer .btn-block+.btn-block { - margin-left: 0 -} - -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll -} - -@media ( min-width :768px) { - .modal-dialog { - width: 600px; - margin: 30px auto - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5) - } - .modal-sm { - width: 300px - } -} - -@media ( min-width :992px) { - .modal-lg { - width: 900px - } -} - -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: 400; - line-height: 1.4; - filter: alpha(opacity = 0); - opacity: 0 -} - -.tooltip.in { - filter: alpha(opacity = 90); - opacity: .9 -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px -} - -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - text-decoration: none; - background-color: #000; - border-radius: 4px -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000 -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000 -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: left; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2) -} - -.popover.top { - margin-top: -10px -} - -.popover.right { - margin-left: 10px -} - -.popover.bottom { - margin-top: 10px -} - -.popover.left { - margin-left: -10px -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0 -} - -.popover-content { - padding: 9px 14px -} - -.popover>.arrow, .popover>.arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid -} - -.popover>.arrow { - border-width: 11px -} - -.popover>.arrow:after { - content: ""; - border-width: 10px -} - -.popover.top>.arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0 -} - -.popover.top>.arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0 -} - -.popover.right>.arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0 -} - -.popover.right>.arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0 -} - -.popover.bottom>.arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25) -} - -.popover.bottom>.arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff -} - -.popover.left>.arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25) -} - -.popover.left>.arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff -} - -.carousel { - position: relative -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden -} - -.carousel-inner>.item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left -} - -.carousel-inner>.item>a>img, .carousel-inner>.item>img { - line-height: 1 -} - -@media all and (transform-3d) , ( -webkit-transform-3d ) { - .carousel-inner>.item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000; - perspective: 1000 - } - .carousel-inner>.item.active.right, .carousel-inner>.item.next { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0) - } - .carousel-inner>.item.active.left, .carousel-inner>.item.prev { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0) - } - .carousel-inner>.item.active, .carousel-inner>.item.next.left, - .carousel-inner>.item.prev.right { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0) - } -} - -.carousel-inner>.active, .carousel-inner>.next, .carousel-inner>.prev { - display: block -} - -.carousel-inner>.active { - left: 0 -} - -.carousel-inner>.next, .carousel-inner>.prev { - position: absolute; - top: 0; - width: 100% -} - -.carousel-inner>.next { - left: 100% -} - -.carousel-inner>.prev { - left: -100% -} - -.carousel-inner>.next.left, .carousel-inner>.prev.right { - left: 0 -} - -.carousel-inner>.active.left { - left: -100% -} - -.carousel-inner>.active.right { - left: 100% -} - -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - filter: alpha(opacity = 50); - opacity: .5 -} - -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), - to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', - endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x -} - -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), - to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', - endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x -} - -.carousel-control:focus, .carousel-control:hover { - color: #fff; - text-decoration: none; - filter: alpha(opacity = 90); - outline: 0; - opacity: .9 -} - -.carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next, .carousel-control .icon-prev { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block -} - -.carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev - { - left: 50%; - margin-left: -10px -} - -.carousel-control .glyphicon-chevron-right, .carousel-control .icon-next - { - right: 50%; - margin-right: -10px -} - -.carousel-control .icon-next, .carousel-control .icon-prev { - width: 20px; - height: 20px; - margin-top: -10px; - font-family: serif; - line-height: 1 -} - -.carousel-control .icon-prev:before { - content: '\2039' -} - -.carousel-control .icon-next:before { - content: '\203a' -} - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none -} - -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px -} - -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff -} - -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6) -} - -.carousel-caption .btn { - text-shadow: none -} - -@media screen and (min-width:768px) { - .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next, .carousel-control .icon-prev { - width: 30px; - height: 30px; - margin-top: -15px; - font-size: 30px - } - .carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev - { - margin-left: -15px - } - .carousel-control .glyphicon-chevron-right, .carousel-control .icon-next - { - margin-right: -15px - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px - } - .carousel-indicators { - bottom: 20px - } -} - -.btn-group-vertical>.btn-group:after, .btn-group-vertical>.btn-group:before, - .btn-toolbar:after, .btn-toolbar:before, .clearfix:after, .clearfix:before, - .container-fluid:after, .container-fluid:before, .container:after, - .container:before, .dl-horizontal dd:after, .dl-horizontal dd:before, - .form-horizontal .form-group:after, .form-horizontal .form-group:before, - .modal-footer:after, .modal-footer:before, .nav:after, .nav:before, - .navbar-collapse:after, .navbar-collapse:before, .navbar-header:after, - .navbar-header:before, .navbar:after, .navbar:before, .pager:after, - .pager:before, .panel-body:after, .panel-body:before, .row:after, .row:before - { - display: table; - content: " " -} - -.btn-group-vertical>.btn-group:after, .btn-toolbar:after, .clearfix:after, - .container-fluid:after, .container:after, .dl-horizontal dd:after, - .form-horizontal .form-group:after, .modal-footer:after, .nav:after, - .navbar-collapse:after, .navbar-header:after, .navbar:after, .pager:after, - .panel-body:after, .row:after { - clear: both -} - -.center-block { - display: block; - margin-right: auto; - margin-left: auto -} - -.pull-right { - float: right !important -} - -.pull-left { - float: left !important -} - -.hide { - display: none !important -} - -.show { - display: block !important -} - -.invisible { - visibility: hidden -} - -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0 -} - -.hidden { - display: none !important -} - -.affix { - position: fixed -} - -@ --ms-viewport { - width: device-width -} - -.visible-lg, .visible-md, .visible-sm, .visible-xs { - display: none !important -} - -.visible-lg-block, .visible-lg-inline, .visible-lg-inline-block, - .visible-md-block, .visible-md-inline, .visible-md-inline-block, - .visible-sm-block, .visible-sm-inline, .visible-sm-inline-block, - .visible-xs-block, .visible-xs-inline, .visible-xs-inline-block { - display: none !important -} - -@media ( max-width :767px) { - .visible-xs { - display: block !important - } - table.visible-xs { - display: table - } - tr.visible-xs { - display: table-row !important - } - td.visible-xs, th.visible-xs { - display: table-cell !important - } -} - -@media ( max-width :767px) { - .visible-xs-block { - display: block !important - } -} - -@media ( max-width :767px) { - .visible-xs-inline { - display: inline !important - } -} - -@media ( max-width :767px) { - .visible-xs-inline-block { - display: inline-block !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm { - display: block !important - } - table.visible-sm { - display: table - } - tr.visible-sm { - display: table-row !important - } - td.visible-sm, th.visible-sm { - display: table-cell !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-block { - display: block !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-inline { - display: inline !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-inline-block { - display: inline-block !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md { - display: block !important - } - table.visible-md { - display: table - } - tr.visible-md { - display: table-row !important - } - td.visible-md, th.visible-md { - display: table-cell !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-block { - display: block !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-inline { - display: inline !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-inline-block { - display: inline-block !important - } -} - -@media ( min-width :1200px) { - .visible-lg { - display: block !important - } - table.visible-lg { - display: table - } - tr.visible-lg { - display: table-row !important - } - td.visible-lg, th.visible-lg { - display: table-cell !important - } -} - -@media ( min-width :1200px) { - .visible-lg-block { - display: block !important - } -} - -@media ( min-width :1200px) { - .visible-lg-inline { - display: inline !important - } -} - -@media ( min-width :1200px) { - .visible-lg-inline-block { - display: inline-block !important - } -} - -@media ( max-width :767px) { - .hidden-xs { - display: none !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .hidden-sm { - display: none !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .hidden-md { - display: none !important - } -} - -@media ( min-width :1200px) { - .hidden-lg { - display: none !important - } -} - -.visible-print { - display: none !important -} - -@media print { - .visible-print { - display: block !important - } - table.visible-print { - display: table - } - tr.visible-print { - display: table-row !important - } - td.visible-print, th.visible-print { - display: table-cell !important - } -} - -.visible-print-block { - display: none !important -} - -@media print { - .visible-print-block { - display: block !important - } -} - -.visible-print-inline { - display: none !important -} - -@media print { - .visible-print-inline { - display: inline !important - } -} - -.visible-print-inline-block { - display: none !important -} - -@media print { - .visible-print-inline-block { - display: inline-block !important - } -} - -@media print { - .hidden-print { - display: none !important - } -} \ No newline at end of file diff --git a/file-server/embedding-files-into-app/assets/css/main.css b/file-server/embedding-files-into-app/assets/css/main.css new file mode 100644 index 00000000..9749e5ad --- /dev/null +++ b/file-server/embedding-files-into-app/assets/css/main.css @@ -0,0 +1,5 @@ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} \ No newline at end of file diff --git a/file-server/embedding-files-into-app/assets/js/jquery-2.1.1.js b/file-server/embedding-files-into-app/assets/js/jquery-2.1.1.js deleted file mode 100644 index 9f7b3d38..00000000 --- a/file-server/embedding-files-into-app/assets/js/jquery-2.1.1.js +++ /dev/null @@ -1,9190 +0,0 @@ -/*! - * jQuery JavaScript Library v2.1.1 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-05-01T17:11Z - */ - -(function( global, factory ) { - - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Can't do this because several apps including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// Support: Firefox 18+ -// - -var arr = []; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var support = {}; - - - -var - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - version = "2.1.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android<4.1 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; - }, - - isPlainObject: function( obj ) { - // Not plain objects: - // - Any object or value whose internal [[Class]] property is not "[object Object]" - // - DOM nodes - // - window - if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.constructor && - !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { - return false; - } - - // If the function hasn't returned already, we're confident that - // |obj| is a plain object, created by {} or constructed with new Object - return true; - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - // Support: Android < 4.0, iOS < 6 (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call(obj) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - var script, - indirect = eval; - - code = jQuery.trim( code ); - - if ( code ) { - // If the code includes a valid, prologue position - // strict mode pragma, execute code by injecting a - // script tag into the document. - if ( code.indexOf("use strict") === 1 ) { - script = document.createElement("script"); - script.text = code; - document.head.appendChild( script ).parentNode.removeChild( script ); - } else { - // Otherwise, avoid the DOM node creation, insertion - // and removal by using an indirect global eval - indirect( code ); - } - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); - - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -function isArraylike( obj ) { - var length = obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.nodeType === 1 && length ) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v1.10.19 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-04-18 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }; - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - - context = context || document; - results = results || []; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; - } - - if ( documentIsHTML && !seed ) { - - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== strundefined && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent !== parent.top ) { - // IE11 does not have attachEvent, so all must suffer - if ( parent.addEventListener ) { - parent.addEventListener( "unload", function() { - setDocument(); - }, false ); - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", function() { - setDocument(); - }); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowclip^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome<14 -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = "<a href='#'></a>"; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = "<input/>"; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - - -var rneedsContext = jQuery.expr.match.needsContext; - -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - -var risSimple = /^.[^:#\[\.,]*$/; - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); -}; - -jQuery.fn.extend({ - find: function( selector ) { - var i, - len = this.length, - ret = [], - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -}); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.extend({ - dir: function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }, - - sibling: function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - } -}); - -jQuery.fn.extend({ - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter(function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.unique( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return elem.contentDocument || jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.unique( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -}); -var rnotwhite = (/\S+/g); - - - -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); - - -// The deferred used on DOM ready -var readyList; - -jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; -}; - -jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } -}); - -/** - * The ready event handler and self cleanup method - */ -function completed() { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - jQuery.ready(); -} - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); - - } else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); - } - } - return readyList.promise( obj ); -}; - -// Kick off the DOM ready check even if the user does not -jQuery.ready.promise(); - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - len ? fn( elems[0], key ) : emptyGet; -}; - - -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( owner ) { - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - /* jshint -W018 */ - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - -function Data() { - // Support: Android < 4, - // Old WebKit does not have Object.preventExtensions/freeze method, - // return new empty object instead with no [[set]] accessor - Object.defineProperty( this.cache = {}, 0, { - get: function() { - return {}; - } - }); - - this.expando = jQuery.expando + Math.random(); -} - -Data.uid = 1; -Data.accepts = jQuery.acceptData; - -Data.prototype = { - key: function( owner ) { - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return the key for a frozen object. - if ( !Data.accepts( owner ) ) { - return 0; - } - - var descriptor = {}, - // Check if the owner object already has a cache key - unlock = owner[ this.expando ]; - - // If not, create one - if ( !unlock ) { - unlock = Data.uid++; - - // Secure it in a non-enumerable, non-writable property - try { - descriptor[ this.expando ] = { value: unlock }; - Object.defineProperties( owner, descriptor ); - - // Support: Android < 4 - // Fallback to a less secure definition - } catch ( e ) { - descriptor[ this.expando ] = unlock; - jQuery.extend( owner, descriptor ); - } - } - - // Ensure the cache object - if ( !this.cache[ unlock ] ) { - this.cache[ unlock ] = {}; - } - - return unlock; - }, - set: function( owner, data, value ) { - var prop, - // There may be an unlock assigned to this node, - // if there is no entry for this "owner", create one inline - // and set the unlock as though an owner entry had always existed - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - // Handle: [ owner, key, value ] args - if ( typeof data === "string" ) { - cache[ data ] = value; - - // Handle: [ owner, { properties } ] args - } else { - // Fresh assignments by object are shallow copied - if ( jQuery.isEmptyObject( cache ) ) { - jQuery.extend( this.cache[ unlock ], data ); - // Otherwise, copy the properties one-by-one to the cache object - } else { - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } - } - } - return cache; - }, - get: function( owner, key ) { - // Either a valid cache is found, or will be created. - // New caches will be created and the unlock returned, - // allowing direct access to the newly created - // empty data object. A valid owner object must be provided. - var cache = this.cache[ this.key( owner ) ]; - - return key === undefined ? - cache : cache[ key ]; - }, - access: function( owner, key, value ) { - var stored; - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ((key && typeof key === "string") && value === undefined) ) { - - stored = this.get( owner, key ); - - return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase(key) ); - } - - // [*]When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, name, camel, - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - if ( key === undefined ) { - this.cache[ unlock ] = {}; - - } else { - // Support array or space separated string of keys - if ( jQuery.isArray( key ) ) { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = key.concat( key.map( jQuery.camelCase ) ); - } else { - camel = jQuery.camelCase( key ); - // Try the string as a key before any manipulation - if ( key in cache ) { - name = [ key, camel ]; - } else { - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - name = camel; - name = name in cache ? - [ name ] : ( name.match( rnotwhite ) || [] ); - } - } - - i = name.length; - while ( i-- ) { - delete cache[ name[ i ] ]; - } - } - }, - hasData: function( owner ) { - return !jQuery.isEmptyObject( - this.cache[ owner[ this.expando ] ] || {} - ); - }, - discard: function( owner ) { - if ( owner[ this.expando ] ) { - delete this.cache[ owner[ this.expando ] ]; - } - } -}; -var data_priv = new Data(); - -var data_user = new Data(); - - - -/* - Implementation Summary - - 1. Enforce API surface and semantic compatibility with 1.9.x branch - 2. Improve the module's maintainability by reducing the storage - paths to a single mechanism. - 3. Use the same single mechanism to support "private" and "user" data. - 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) - 5. Avoid exposing implementation details on user objects (eg. expando properties) - 6. Provide a clear path for implementation upgrade to WeakMap in 2014 -*/ -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - data_user.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend({ - hasData: function( elem ) { - return data_user.hasData( elem ) || data_priv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return data_user.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - data_user.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to data_priv methods, these can be deprecated. - _data: function( elem, name, data ) { - return data_priv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - data_priv.remove( elem, name ); - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = data_user.get( elem ); - - if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - data_priv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - data_user.set( this, key ); - }); - } - - return access( this, function( value ) { - var data, - camelKey = jQuery.camelCase( key ); - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - // Attempt to get data from the cache - // with the key as-is - data = data_user.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to get data from the cache - // with the key camelized - data = data_user.get( elem, camelKey ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, camelKey, undefined ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each(function() { - // First, attempt to store a copy or reference of any - // data that might've been store with a camelCased key. - var data = data_user.get( this, camelKey ); - - // For HTML5 data-* attribute interop, we have to - // store property names with dashes in a camelCase form. - // This might not apply to all properties...* - data_user.set( this, camelKey, value ); - - // *... In the case of properties that might _actually_ - // have dashes, we need to also store a copy of that - // unchanged property. - if ( key.indexOf("-") !== -1 && data !== undefined ) { - data_user.set( this, key, value ); - } - }); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each(function() { - data_user.remove( this, key ); - }); - } -}); - - -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = data_priv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = data_priv.access( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return data_priv.get( elem, key ) || data_priv.access( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - data_priv.remove( elem, [ type + "queue", key ] ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = data_priv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); - }; - -var rcheckableType = (/^(?:checkbox|radio)$/i); - - - -(function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // #11217 - WebKit loses check when the name is after the checked attribute - // Support: Windows Web Apps (WWA) - // `name` and `type` need .setAttribute for WWA - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE9-IE11+ - div.innerHTML = "<textarea>x</textarea>"; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -})(); -var strundefined = typeof undefined; - - - -support.focusinBubbles = "onfocusin" in window; - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.hasData( elem ) && data_priv.get( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - data_priv.remove( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG <use> instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } - - return handlerQueue; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: Cordova 2.5 (WebKit) (#13255) - // All events should have a target; Cordova deviceready doesn't - if ( !event.target ) { - event.target = document; - } - - // Support: Safari 6.0+, Chrome < 28 - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } -}; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && e.preventDefault ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && e.stopPropagation ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -// Support: Chrome 15+ -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// Create "bubbling" focus and blur events -// Support: Firefox, Chrome, Safari -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - data_priv.remove( doc, fix ); - - } else { - data_priv.access( doc, fix, attaches ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -}); - - -var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /^$|\/(?:java|ecma)script/i, - rscriptTypeMasked = /^true\/(.*)/, - rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - - // Support: IE 9 - option: [ 1, "<select multiple='multiple'>", "</select>" ], - - thead: [ 1, "<table>", "</table>" ], - col: [ 2, "<table><colgroup>", "</colgroup></table>" ], - tr: [ 2, "<table><tbody>", "</tbody></table>" ], - td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], - - _default: [ 0, "", "" ] - }; - -// Support: IE 9 -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: 1.x compatibility -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute("type"); - } - - return elem; -} - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - data_priv.set( - elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) - ); - } -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( data_priv.hasData( src ) ) { - pdataOld = data_priv.access( src ); - pdataCur = data_priv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( data_user.hasData( src ) ) { - udataOld = data_user.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - data_user.set( dest, udataCur ); - } -} - -function getAll( context, tag ) { - var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : - context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; -} - -// Support: IE >= 9 -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Support: IE >= 9 - // Fix Cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - buildFragment: function( elems, context, scripts, selection ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Fixes #12346 - // Support: Webkit, IE - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - }, - - cleanData: function( elems ) { - var data, elem, type, key, - special = jQuery.event.special, - i = 0; - - for ( ; (elem = elems[ i ]) !== undefined; i++ ) { - if ( jQuery.acceptData( elem ) ) { - key = elem[ data_priv.expando ]; - - if ( key && (data = data_priv.cache[ key ]) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - if ( data_priv.cache[ key ] ) { - // Discard any remaining `private` data - delete data_priv.cache[ key ]; - } - } - } - // Discard any remaining `user` data - delete data_user.cache[ elem[ data_user.expando ] ]; - } - } -}); - -jQuery.fn.extend({ - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each(function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - }); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1></$2>" ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var arg = arguments[ 0 ]; - - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; - - jQuery.cleanData( getAll( this ) ); - - if ( arg ) { - arg.replaceChild( elem, this ); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - self.domManip( args, callback ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } - } - } - } - - return this; - } -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: QtWebKit - // .get() because push.apply(_, arraylike) throws - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - - -var iframe, - elemdisplay = {}; - -/** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ -// Called only from within defaultDisplay -function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? - - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; -} - -/** - * Try to determine the default display value of an element - * @param {String} nodeName - */ -function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); - - // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse - doc = iframe[ 0 ].contentDocument; - - // Support: IE - doc.write(); - doc.close(); - - display = actualDisplay( nodeName, doc ); - iframe.detach(); - } - - // Store the correct default display - elemdisplay[ nodeName ] = display; - } - - return display; -} -var rmargin = (/^margin/); - -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); - }; - - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - style = elem.style; - - computed = computed || getStyles( elem ); - - // Support: IE9 - // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - } - - if ( computed ) { - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // Support: iOS < 6 - // A tribute to the "awesome hack by Dean Edwards" - // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - // Support: IE - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - // Hook not needed (or it's not possible to use it due to missing dependency), - // remove it. - // Since there are no other hooks for marginRight, remove the whole object. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - - return (this.get = hookFn).apply( this, arguments ); - } - }; -} - - -(function() { - var pixelPositionVal, boxSizingReliableVal, - docElem = document.documentElement, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - if ( !div.style ) { - return; - } - - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" + - "position:absolute"; - container.appendChild( div ); - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computePixelPositionAndBoxSizingReliable() { - div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + - "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + - "border:1px;padding:1px;width:4px;position:absolute"; - div.innerHTML = ""; - docElem.appendChild( container ); - - var divStyle = window.getComputedStyle( div, null ); - pixelPositionVal = divStyle.top !== "1%"; - boxSizingReliableVal = divStyle.width === "4px"; - - docElem.removeChild( container ); - } - - // Support: node.js jsdom - // Don't assume that getComputedStyle is a property of the global object - if ( window.getComputedStyle ) { - jQuery.extend( support, { - pixelPosition: function() { - // This test is executed only once but we still do memoizing - // since we can use the boxSizingReliable pre-computing. - // No need to check if the test was already performed, though. - computePixelPositionAndBoxSizingReliable(); - return pixelPositionVal; - }, - boxSizingReliable: function() { - if ( boxSizingReliableVal == null ) { - computePixelPositionAndBoxSizingReliable(); - } - return boxSizingReliableVal; - }, - reliableMarginRight: function() { - // Support: Android 2.3 - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. (#3333) - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // This support function is only executed once so no memoizing is needed. - var ret, - marginDiv = div.appendChild( document.createElement( "div" ) ); - - // Reset CSS: box-sizing; display; margin; border; padding - marginDiv.style.cssText = div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - docElem.appendChild( container ); - - ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight ); - - docElem.removeChild( container ); - - return ret; - } - }); - } -})(); - - -// A method for quickly swapping in/out CSS properties to get correct calculations. -jQuery.swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), - rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name[0].toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); - } - - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } else { - // at this point, extra isn't content, so add padding - val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var valueIsBorderBox = true, - val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name, styles ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && - ( support.boxSizingReliable() || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles - ) - ) + "px"; -} - -function showHide( elements, show ) { - var display, elem, hidden, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - values[ index ] = data_priv.get( elem, "olddisplay" ); - display = elem.style.display; - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) ); - } - } else { - hidden = isHidden( elem ); - - if ( display !== "none" || !hidden ) { - data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": "cssFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set. See: #7116 - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, - // but it would mean to define eight (for every problematic property) identical functions - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - style[ name ] = value; - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - } -}); - -jQuery.each([ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? - jQuery.swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - }) : - getWidthOrHeight( elem, name, extra ); - } - }, - - set: function( elem, value, extra ) { - var styles = extra && getStyles( elem ); - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - styles - ) : 0 - ); - } - }; -}); - -// Support: Android 2.3 -jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, - function( elem, computed ) { - if ( computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, - curCSS, [ elem, "marginRight" ] ); - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each({ - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -}); - -jQuery.fn.extend({ - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( jQuery.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each(function() { - if ( isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - if ( tween.elem[ tween.prop ] != null && - (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { - return tween.elem[ tween.prop ]; - } - - // passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE9 -// Panic based approach to setting things on disconnected nodes - -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - } -}; - -jQuery.fx = Tween.prototype.init; - -// Back Compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), - rrun = /queueHooks$/, - animationPrefilters = [ defaultPrefilter ], - tweeners = { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ), - target = tween.cur(), - parts = rfxnum.exec( value ), - unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && - rfxnum.exec( jQuery.css( tween.elem, prop ) ), - scale = 1, - maxIterations = 20; - - if ( start && start[ 3 ] !== unit ) { - // Trust units reported by jQuery.css - unit = unit || start[ 3 ]; - - // Make sure we update the tween properties later on - parts = parts || []; - - // Iteratively approximate from a nonzero starting point - start = +target || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } - - // Update tween properties - if ( parts ) { - start = tween.start = +start || +target || 0; - tween.unit = unit; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[ 1 ] ? - start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : - +parts[ 2 ]; - } - - return tween; - } ] - }; - -// Animations created synchronously will run synchronously -function createFxNow() { - setTimeout(function() { - fxNow = undefined; - }); - return ( fxNow = jQuery.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4 ; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( (tween = collection[ index ].call( animation, prop, value )) ) { - - // we're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - /* jshint validthis: true */ - var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHidden( elem ), - dataShow = data_priv.get( elem, "fxshow" ); - - // handle queue: false promises - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function() { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE9-10 do not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - display = jQuery.css( elem, "display" ); - - // Test default display if display is currently "none" - checkDisplay = display === "none" ? - data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; - - if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { - style.display = "inline-block"; - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always(function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - }); - } - - // show/hide pass - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.exec( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - - // Any non-fx value stops us from restoring the original display value - } else { - display = undefined; - } - } - - if ( !jQuery.isEmptyObject( orig ) ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = data_priv.access( elem, "fxshow", {} ); - } - - // store state if its toggle - enables .stop().toggle() to "reverse" - if ( toggle ) { - dataShow.hidden = !hidden; - } - if ( hidden ) { - jQuery( elem ).show(); - } else { - anim.done(function() { - jQuery( elem ).hide(); - }); - } - anim.done(function() { - var prop; - - data_priv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( prop in orig ) { - tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - - // If this is a noop like .hide().hide(), restore an overwritten display value - } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { - style.display = display; - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( jQuery.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always( function() { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ]); - - if ( percent < 1 && length ) { - return remaining; - } else { - deferred.resolveWith( elem, [ animation ] ); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { specialEasing: {} }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // resolve when we played the last frame - // otherwise, reject - if ( gotoEnd ) { - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - }), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length ; index++ ) { - result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( jQuery.isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - }) - ); - - // attach callbacks from options - return animation.progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweener: function( props, callback ) { - if ( jQuery.isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length ; index++ ) { - prop = props[ index ]; - tweeners[ prop ] = tweeners[ prop ] || []; - tweeners[ prop ].unshift( callback ); - } - }, - - prefilter: function( callback, prepend ) { - if ( prepend ) { - animationPrefilters.unshift( callback ); - } else { - animationPrefilters.push( callback ); - } - } -}); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - jQuery.isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( jQuery.isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend({ - fadeTo: function( speed, to, easing, callback ) { - - // show any hidden elements after setting opacity to 0 - return this.filter( isHidden ).css( "opacity", 0 ).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || data_priv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each(function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = data_priv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - }); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each(function() { - var index, - data = data_priv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // enable finishing flag on private data - data.finish = true; - - // empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // turn off finishing flag - delete data.finish; - }); - } -}); - -jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -}); - -// Generate shortcuts for custom animations -jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -}); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = jQuery.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - // Checks the timer has not already been removed - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - if ( timer() ) { - jQuery.fx.start(); - } else { - jQuery.timers.pop(); - } -}; - -jQuery.fx.interval = 13; - -jQuery.fx.start = function() { - if ( !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } -}; - -jQuery.fx.stop = function() { - clearInterval( timerId ); - timerId = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); -}; - - -(function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: iOS 5.1, Android 4.x, Android 2.3 - // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) - support.checkOn = input.value !== ""; - - // Must access the parent to make an option select properly - // Support: IE9, IE10 - support.optSelected = opt.selected; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Check if an input maintains its value after becoming a radio - // Support: IE9, IE10 - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -})(); - - -var nodeHook, boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend({ - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - } -}); - -jQuery.extend({ - attr: function( elem, name, value ) { - var hooks, ret, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === strundefined ) { - return jQuery.prop( elem, name, value ); - } - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - - } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var name, propName, - i = 0, - attrNames = value && value.match( rnotwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { - propName = jQuery.propFix[ name ] || name; - - // Boolean attributes get special treatment (#10870) - if ( jQuery.expr.match.bool.test( name ) ) { - // Set corresponding property to false - elem[ propName ] = false; - } - - elem.removeAttribute( name ); - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - jQuery.nodeName( elem, "input" ) ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - } -}); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle; - if ( !isXML ) { - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ name ]; - attrHandle[ name ] = ret; - ret = getter( elem, name, isXML ) != null ? - name.toLowerCase() : - null; - attrHandle[ name ] = handle; - } - return ret; - }; -}); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i; - -jQuery.fn.extend({ - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each(function() { - delete this[ jQuery.propFix[ name ] || name ]; - }); - } -}); - -jQuery.extend({ - propFix: { - "for": "htmlFor", - "class": "className" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? - ret : - ( elem[ name ] = value ); - - } else { - return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? - ret : - elem[ name ]; - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? - elem.tabIndex : - -1; - } - } - } -}); - -// Support: IE9+ -// Selectedness for an option in an optgroup can be inaccurate -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - } - }; -} - -jQuery.each([ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -}); - - - - -var rclass = /[\t\r\n\f]/g; - -jQuery.fn.extend({ - addClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call( this, j, this.className ) ); - }); - } - - if ( proceed ) { - // The disjunction here is for better compressibility (see removeClass) - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - " " - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = jQuery.trim( cur ); - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = arguments.length === 0 || typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call( this, j, this.className ) ); - }); - } - if ( proceed ) { - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - "" - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = value ? jQuery.trim( cur ) : ""; - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value; - - if ( typeof stateVal === "boolean" && type === "string" ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - classNames = value.match( rnotwhite ) || []; - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( type === strundefined || type === "boolean" ) { - if ( this.className ) { - // store className if set - data_priv.set( this, "__className__", this.className ); - } - - // If the element has a class name or if we're passed "false", - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - } -}); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend({ - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - // Support: IE10-11+ - // option.text throws exceptions (#14686, #14858) - jQuery.trim( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one" || index < 0, - values = one ? null : [], - max = one ? index + 1 : options.length, - i = index < 0 ? - max : - one ? index : 0; - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // IE6-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - // Don't return options that are disabled or in a disabled optgroup - ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && - ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) { - optionSet = true; - } - } - - // force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -}); - -// Radios and checkboxes getter/setter -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - // Support: Webkit - // "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - }; - } -}); - - - - -// Return jQuery for attributes-only inclusion - - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; -}); - -jQuery.fn.extend({ - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - } -}); - - -var nonce = jQuery.now(); - -var rquery = (/\?/); - - - -// Support: Android 2.3 -// Workaround failure to string-cast null input -jQuery.parseJSON = function( data ) { - return JSON.parse( data + "" ); -}; - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE9 - try { - tmp = new DOMParser(); - xml = tmp.parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rts = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat("*"); - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set -try { - ajaxLocation = location.href; -} catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; -} - -// Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - while ( (dataType = dataTypes[i++]) ) { - // Prepend if requested - if ( dataType[0] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); - - // Otherwise append - } else { - (structure[ dataType ] = structure[ dataType ] || []).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - }); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s[ "throws" ] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend({ - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: ajaxLocation, - type: "GET", - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - // URL without anti-cache param - cacheURL, - // Response headers - responseHeadersString, - responseHeaders, - // timeout handle - timeoutTimer, - // Cross-domain detection vars - parts, - // To know if global events are to be dispatched - fireGlobals, - // Loop variable - i, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks("once memory"), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( (match = rheaders.exec( responseHeadersString )) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - var lname = name.toLowerCase(); - if ( !state ) { - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( state < 2 ) { - for ( code in map ) { - // Lazy-add the new callback in a way that preserves old ones - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } else { - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ).complete = completeDeferred.add; - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) - .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ); - s.crossDomain = !!( parts && - ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || - ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== - ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) - ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger("ajaxStart"); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - cacheURL = s.url; - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add anti-cache in url if needed - if ( s.cache === false ) { - s.url = rts.test( cacheURL ) ? - - // If there is already a '_' parameter, set its value - cacheURL.replace( rts, "$1_=" + nonce++ ) : - - // Otherwise add one to the end - cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; - } - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout(function() { - jqXHR.abort("timeout"); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch ( e ) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader("etag"); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger("ajaxStop"); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - url: url, - type: method, - dataType: type, - data: data, - success: callback - }); - }; -}); - -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -}); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax({ - url: url, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); -}; - - -jQuery.fn.extend({ - wrapAll: function( html ) { - var wrap; - - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapAll( html.call(this, i) ); - }); - } - - if ( this[ 0 ] ) { - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function( i ) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - } -}); - - -jQuery.expr.filters.hidden = function( elem ) { - // Support: Opera <= 12.12 - // Opera reports offsetWidths and offsetHeights less than zero on some elements - return elem.offsetWidth <= 0 && elem.offsetHeight <= 0; -}; -jQuery.expr.filters.visible = function( elem ) { - return !jQuery.expr.filters.hidden( elem ); -}; - - - - -var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( jQuery.isArray( obj ) ) { - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - // Item is non-scalar (array or object), encode its numeric index. - buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); - } - }); - - } else if ( !traditional && jQuery.type( obj ) === "object" ) { - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, value ) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); - s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if ( traditional === undefined ) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ).replace( r20, "+" ); -}; - -jQuery.fn.extend({ - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map(function() { - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - }) - .filter(function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - }) - .map(function( i, elem ) { - var val = jQuery( this ).val(); - - return val == null ? - null : - jQuery.isArray( val ) ? - jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }) : - { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }).get(); - } -}); - - -jQuery.ajaxSettings.xhr = function() { - try { - return new XMLHttpRequest(); - } catch( e ) {} -}; - -var xhrId = 0, - xhrCallbacks = {}, - xhrSuccessStatus = { - // file protocol always yields status code 0, assume 200 - 0: 200, - // Support: IE9 - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -// Support: IE9 -// Open requests must be manually aborted on unload (#5280) -if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ](); - } - }); -} - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport(function( options ) { - var callback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(), - id = ++xhrId; - - xhr.open( options.type, options.url, options.async, options.username, options.password ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers["X-Requested-With"] ) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - delete xhrCallbacks[ id ]; - callback = xhr.onload = xhr.onerror = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - complete( - // file: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - // Support: IE9 - // Accessing binary-data responseText throws an exception - // (#11426) - typeof xhr.responseText === "string" ? { - text: xhr.responseText - } : undefined, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - xhr.onerror = callback("error"); - - // Create the abort callback - callback = xhrCallbacks[ id ] = callback("abort"); - - try { - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -// Install script dataType -jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /(?:java|ecma)script/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -}); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -}); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery("<script>").prop({ - async: true, - charset: s.scriptCharset, - src: s.url - }).on( - "load error", - callback = function( evt ) { - script.remove(); - callback = null; - if ( evt ) { - complete( evt.type === "error" ? 404 : 200, evt.type ); - } - } - ); - document.head.appendChild( script[ 0 ] ); - }, - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -var oldCallbacks = [], - rjsonp = /(=)\?(?=&|$)|\?\?/; - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? - "url" : - typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if ( jsonProp ) { - s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); - } else if ( s.jsonp !== false ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - overwritten = window[ callbackName ]; - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); - - - - -// data: string of html -// context (optional): If specified, the fragment will be created in this context, defaults to document -// keepScripts (optional): If true, will include scripts passed in the html string -jQuery.parseHTML = function( data, context, keepScripts ) { - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec( data ), - scripts = !keepScripts && []; - - // Single tag - if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ); - - if ( scripts && scripts.length ) { - jQuery( scripts ).remove(); - } - - return jQuery.merge( [], parsed.childNodes ); -}; - - -// Keep a copy of the old load method -var _load = jQuery.fn.load; - -/** - * Load a url into a page - */ -jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - var selector, type, response, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = jQuery.trim( url.slice( off ) ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // If we have elements to modify, make the request - if ( self.length > 0 ) { - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - self.html( selector ? - - // If a selector was specified, locate the right elements in a dummy div - // Exclude scripts to avoid IE 'Permission Denied' errors - jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : - - // Otherwise use the full result - responseText ); - - }).complete( callback && function( jqXHR, status ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - }); - } - - return this; -}; - - - - -jQuery.expr.filters.animated = function( elem ) { - return jQuery.grep(jQuery.timers, function( fn ) { - return elem === fn.elem; - }).length; -}; - - - - -var docElem = window.document.documentElement; - -/** - * Gets a window from an element - */ -function getWindow( elem ) { - return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; -} - -jQuery.offset = { - setOffset: function( elem, options, i ) { - var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, - position = jQuery.css( elem, "position" ), - curElem = jQuery( elem ), - props = {}; - - // Set position first, in-case top/left are set even on static elem - if ( position === "static" ) { - elem.style.position = "relative"; - } - - curOffset = curElem.offset(); - curCSSTop = jQuery.css( elem, "top" ); - curCSSLeft = jQuery.css( elem, "left" ); - calculatePosition = ( position === "absolute" || position === "fixed" ) && - ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; - - // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if ( calculatePosition ) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - - } else { - curTop = parseFloat( curCSSTop ) || 0; - curLeft = parseFloat( curCSSLeft ) || 0; - } - - if ( jQuery.isFunction( options ) ) { - options = options.call( elem, i, curOffset ); - } - - if ( options.top != null ) { - props.top = ( options.top - curOffset.top ) + curTop; - } - if ( options.left != null ) { - props.left = ( options.left - curOffset.left ) + curLeft; - } - - if ( "using" in options ) { - options.using.call( elem, props ); - - } else { - curElem.css( props ); - } - } -}; - -jQuery.fn.extend({ - offset: function( options ) { - if ( arguments.length ) { - return options === undefined ? - this : - this.each(function( i ) { - jQuery.offset.setOffset( this, options, i ); - }); - } - - var docElem, win, - elem = this[ 0 ], - box = { top: 0, left: 0 }, - doc = elem && elem.ownerDocument; - - if ( !doc ) { - return; - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if ( !jQuery.contains( docElem, elem ) ) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== strundefined ) { - box = elem.getBoundingClientRect(); - } - win = getWindow( doc ); - return { - top: box.top + win.pageYOffset - docElem.clientTop, - left: box.left + win.pageXOffset - docElem.clientLeft - }; - }, - - position: function() { - if ( !this[ 0 ] ) { - return; - } - - var offsetParent, offset, - elem = this[ 0 ], - parentOffset = { top: 0, left: 0 }; - - // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent - if ( jQuery.css( elem, "position" ) === "fixed" ) { - // We assume that getBoundingClientRect is available when computed position is fixed - offset = elem.getBoundingClientRect(); - - } else { - // Get *real* offsetParent - offsetParent = this.offsetParent(); - - // Get correct offsets - offset = this.offset(); - if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { - parentOffset = offsetParent.offset(); - } - - // Add offsetParent borders - parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); - parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); - } - - // Subtract parent offsets and element margins - return { - top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), - left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) - }; - }, - - offsetParent: function() { - return this.map(function() { - var offsetParent = this.offsetParent || docElem; - - while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { - offsetParent = offsetParent.offsetParent; - } - - return offsetParent || docElem; - }); - } -}); - -// Create scrollLeft and scrollTop methods -jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { - var top = "pageYOffset" === prop; - - jQuery.fn[ method ] = function( val ) { - return access( this, function( elem, method, val ) { - var win = getWindow( elem ); - - if ( val === undefined ) { - return win ? win[ prop ] : elem[ method ]; - } - - if ( win ) { - win.scrollTo( - !top ? val : window.pageXOffset, - top ? val : window.pageYOffset - ); - - } else { - elem[ method ] = val; - } - }, method, val, arguments.length, null ); - }; -}); - -// Add the top/left cssHooks using jQuery.fn.position -// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 -// getComputedStyle returns percent when specified for top/left/bottom/right -// rather than make the css module depend on the offset module, we just check for it here -jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, - function( elem, computed ) { - if ( computed ) { - computed = curCSS( elem, prop ); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( computed ) ? - jQuery( elem ).position()[ prop ] + "px" : - computed; - } - } - ); -}); - - -// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods -jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { - // margin is only for outerHeight, outerWidth - jQuery.fn[ funcName ] = function( margin, value ) { - var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), - extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); - - return access( this, function( elem, type, value ) { - var doc; - - if ( jQuery.isWindow( elem ) ) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement[ "client" + name ]; - } - - // Get document width or height - if ( elem.nodeType === 9 ) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], - // whichever is greatest - return Math.max( - elem.body[ "scroll" + name ], doc[ "scroll" + name ], - elem.body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, extra ) : - - // Set width or height on the element - jQuery.style( elem, type, value, extra ); - }, type, chainable ? margin : undefined, chainable, null ); - }; - }); -}); - - -// The number of elements contained in the matched element set -jQuery.fn.size = function() { - return this.length; -}; - -jQuery.fn.andSelf = jQuery.fn.addBack; - - - - -// Register as a named AMD module, since jQuery can be concatenated with other -// files that may use define, but not via a proper concatenation script that -// understands anonymous AMD modules. A named AMD is safest and most robust -// way to register. Lowercase jquery is used because AMD module names are -// derived from file names, and jQuery is normally delivered in a lowercase -// file name. Do this after creating the global so that if an AMD module wants -// to call noConflict to hide this version of jQuery, it will work. - -// Note that for maximum portability, libraries that are not jQuery should -// declare themselves as anonymous modules, and avoid setting a global if an -// AMD loader is present. jQuery is a special case. For more information, see -// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon - -if ( typeof define === "function" && define.amd ) { - define( "jquery", [], function() { - return jQuery; - }); -} - - - - -var - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$; - -jQuery.noConflict = function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; -}; - -// Expose jQuery and $ identifiers, even in -// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) -// and CommonJS for browser emulators (#13566) -if ( typeof noGlobal === strundefined ) { - window.jQuery = window.$ = jQuery; -} - - - - -return jQuery; - -})); diff --git a/file-server/embedding-files-into-app/assets/js/main.js b/file-server/embedding-files-into-app/assets/js/main.js new file mode 100644 index 00000000..07f93514 --- /dev/null +++ b/file-server/embedding-files-into-app/assets/js/main.js @@ -0,0 +1 @@ +console.log("example"); \ No newline at end of file diff --git a/file-server/embedding-files-into-app/bindata.go b/file-server/embedding-files-into-app/bindata.go deleted file mode 100644 index cb9e89ee..00000000 --- a/file-server/embedding-files-into-app/bindata.go +++ /dev/null @@ -1,287 +0,0 @@ -// Code generated by go-bindata. -// sources: -// assets/css/bootstrap.min.css -// assets/favicon.ico -// assets/js/jquery-2.1.1.js -// DO NOT EDIT! - -package main - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _assetsCssBootstrapMinCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\xef\x8f\xe3\x38\x92\x20\xfa\xb9\x1a\xe8\xff\x41\x5b\x8d\x41\x57\x4d\x59\x2e\xf9\x77\xda\x89\xce\xb7\xfb\xe6\x0e\xb7\x03\xdc\xec\x97\x9b\x0f\x07\xf4\xf4\x7b\xa0\x25\xda\xd6\x94\x2c\x69\x24\x39\x2b\xb3\xfb\xf6\xfe\xf6\x83\xf8\x4b\x41\x32\x48\xd1\x4e\x77\xcf\xdc\x62\xb7\xee\x7a\x9c\x62\x44\x30\x18\x0c\x06\x83\x41\x32\xf8\xf9\xf7\xff\xf4\xed\x37\xd1\xef\xa3\xff\xb7\xaa\xba\xb6\x6b\x48\x1d\x3d\x2f\xa6\x8b\xe9\x32\xfa\x70\xea\xba\x7a\xf7\xf9\xf3\x91\x76\x7b\x59\x36\x4d\xab\xf3\x47\x06\xfe\x87\xaa\x7e\x6d\xf2\xe3\xa9\x8b\xe6\xc9\x6c\x16\xcf\x93\xd9\x2a\xfa\xf3\xd7\xbc\xeb\x68\x33\x89\xfe\x58\xa6\x53\x06\xf5\xdf\xf3\x94\x96\x2d\xcd\xa2\x4b\x99\xd1\x26\xfa\xd3\x1f\xff\xcc\xc9\xb6\x3d\xdd\xbc\x3b\x5d\xf6\x3d\xc5\xcf\xdd\xd7\x7d\xfb\x59\x55\xf2\x79\x5f\x54\xfb\xcf\x67\xd2\x76\xb4\xf9\xfc\xdf\xff\xf8\x87\xff\xfa\x6f\xff\xe3\xbf\xb2\x4a\x3f\x47\x9f\x7f\xff\x4f\x51\x59\x35\x67\x52\xe4\x3f\xd3\x69\xda\xb6\x3d\xb3\xc9\x74\x1e\xfd\x2f\x46\x5b\x54\x17\xfd\xaf\xe8\x98\x77\xd3\xbc\xfa\xac\x60\xa3\xdf\x7f\xfe\xf6\x9b\x53\x77\x2e\xa2\x5f\xbe\xfd\xe6\xdd\xa1\x2a\xbb\xf8\x40\xce\x79\xf1\xba\x8b\x5a\x52\xb6\x71\x4b\x9b\xfc\xf0\xf8\xed\x37\xef\xe2\xaf\x74\xff\x25\xef\xe2\x8e\xbe\x74\x71\x9b\xff\x4c\x63\x92\xfd\xf5\xd2\x76\xbb\x68\x96\x24\xbf\x63\x10\xe7\xd6\x51\xfa\xed\x37\xff\xfe\xed\x37\xdf\x7e\xb3\xaf\xb2\x57\x56\xcd\x99\x34\xc7\xbc\xdc\x45\x89\x28\x20\x4d\x97\xa7\x05\x9d\x44\xa4\xcd\x33\x3a\x89\x32\xda\x91\xbc\x68\x27\xd1\x21\x3f\xa6\xa4\xee\xf2\xaa\x64\xbf\x2f\x0d\x9d\x44\x87\xaa\x62\xb2\x3c\x51\x92\xb1\xff\x3d\x36\xd5\xa5\x9e\x30\xb2\x79\x39\x89\xce\xb4\xbc\x4c\xa2\x92\x3c\x4f\xa2\x96\xa6\x1c\xb7\xbd\x9c\xcf\xa4\xe1\x95\x67\x79\x5b\x17\xe4\x75\x17\xed\x8b\x2a\xfd\x22\x39\xb8\x64\x79\x35\x89\x52\x52\x3e\x93\x76\x12\xd5\x4d\x75\x6c\x68\xdb\x4e\xa2\xe7\x3c\xa3\x95\x8e\x97\x97\x45\x5e\xd2\x98\xa1\xf7\xed\x7e\xa6\x3d\xfb\xa4\x88\x49\x91\x1f\xcb\x5d\xb4\x27\x2d\xed\x21\x20\xe9\x5d\x59\x75\xd1\x87\x1f\xd3\xaa\xec\x9a\xaa\x68\x7f\x8a\x3e\x6a\x24\xcb\xaa\xa4\x3d\xa9\x13\xed\x35\x67\x10\xcc\x8f\xa7\x3c\xcb\x68\xf9\xd3\x24\xea\xe8\xb9\x2e\x48\x47\x23\x0b\x4f\x56\xc3\x4a\xf6\x24\xfd\xd2\xcb\xa3\xcc\xe2\xb4\x2a\xaa\x66\x17\x75\x0d\x29\xdb\x9a\x34\xb4\xec\x24\xe4\x8e\xa4\x5d\xfe\xdc\x8b\x7b\x77\xaa\x9e\x69\xc3\x30\xab\x4b\xd7\x33\x0d\x3a\x65\xbf\x6f\x7e\xec\xf2\xae\xa0\x3f\x71\xd2\x55\x93\xd1\x26\xde\x57\x5d\x57\x9d\x77\xd1\xac\x7e\x89\xb2\xaa\xeb\x68\x26\x7b\x77\x12\xb5\x5d\x53\x95\xc7\x41\x93\xbe\x8a\xe6\x6c\x12\x49\x34\x3b\x94\x43\x71\xdb\xbd\x16\x74\x17\xe5\x1d\x29\xf2\x54\x00\x9c\x66\x9a\x86\x4c\xd7\x1b\x7a\x8e\x92\x47\x85\x92\xff\x4c\x77\xd1\x9c\x9e\x05\xf8\x99\x34\x5f\x18\x82\x68\xed\x77\x49\xc2\x80\x07\x39\xec\xa2\xef\x0e\x07\x59\x7d\x7b\x26\x05\xd0\x74\x4e\xed\x41\x29\x68\x7b\xe9\x1b\x71\xa9\x19\x44\x5d\xb5\x79\xaf\x3d\xbb\xa8\xa1\x05\xe9\x05\x66\x70\xb1\x59\x31\xb5\x67\xca\xa0\x3a\x2e\x40\x21\x64\x05\x5d\x55\xef\xa2\x78\xba\x52\x8d\x69\x2f\x7b\x21\x69\x2e\xe2\x78\x3a\x1f\x0a\xf3\xf3\x11\x74\xc3\xd0\x4d\xed\xf3\x91\x2b\xd7\xae\xa9\xaa\x8e\xeb\x55\xdf\xa9\x87\xa2\xfa\xba\x8b\xb8\xfe\x08\x50\x3e\x82\x34\xf9\xce\xe8\x39\x5a\x26\xf5\x8b\x94\x3e\xd7\x05\xad\x35\x72\xe0\xef\xab\x97\xbe\xe1\x79\x79\xdc\x45\xbd\x1e\xd3\x92\x7d\xe3\x23\xbf\xfa\xd9\x57\xee\x28\x12\x95\xd6\x82\xa7\x81\x6b\x72\xe9\x2a\x51\x98\x56\xbd\x41\xf8\xb2\xcf\xfa\x41\x49\x27\x51\x4b\xce\xb5\x6d\xaa\xce\x55\x59\xb5\x35\x49\xe9\x64\xf8\x69\xf4\xd6\x4c\x49\x72\x7f\xe9\xba\xde\x28\xe4\x65\x7d\xe9\x26\x51\x55\x77\xdc\x82\x44\x2d\x2d\x68\xda\xf5\x63\xed\xa5\x23\x0d\x25\xba\xad\x92\xf4\x7a\x03\x70\xa2\x4d\xde\x3d\x0e\x6a\x27\xbe\x68\x15\x18\x6d\x7a\xce\xdb\x7c\x5f\x50\x83\x07\x5e\x25\x57\x87\xde\x74\xb2\xd1\x7a\xa8\x9a\xb3\x36\xb6\x25\x34\xb3\xd3\x8c\xed\x1f\xbb\xd7\x9a\xfe\xc0\xbf\xff\x34\x81\xdf\x1a\xda\xd2\x4e\xff\xd4\x5e\xf6\xe7\xbc\xe3\xa3\x58\xf6\x26\xa9\x6b\x4a\x1a\x52\xa6\x74\x17\x71\x32\xac\x39\x97\xa6\xed\xdb\x53\x57\x79\xd9\xd1\x46\xab\xfe\xc7\x2c\x6f\xc9\xbe\xa0\xd9\x4f\x1a\x23\xea\x2b\x1f\x86\x82\x40\x46\x0f\xe4\x52\xe8\x02\xd9\xed\x98\x9e\x1c\xaa\xf4\xd2\xc6\x79\x59\xf6\xc6\x9b\xd1\xb0\x0b\xf8\x00\x24\x59\xc6\x54\x86\x8f\x68\x43\xef\x19\x26\x83\xd3\x06\x20\x9f\xd8\x20\x0c\x97\x41\x7a\xa2\xe9\x97\x7d\xf5\x62\x08\x8b\x64\x79\xa5\x0b\x06\xea\xaa\x32\x79\xb8\x96\xeb\xc5\xee\x92\xa1\x21\x36\x5f\xe5\xe5\xbc\xa7\xcd\x4f\xbb\x9d\xac\x9f\xb5\x3f\x6e\xeb\xbc\x8c\x35\x45\x75\x80\x57\x97\x4e\x07\xff\xf6\x9b\x77\x70\x08\x83\xa1\x04\x35\x82\x92\x26\x3d\xb9\x1b\x7e\x9f\xf1\xfd\xe8\xd0\xb7\x5e\xd3\x0f\x39\x2d\x32\x27\x63\x43\xfb\xf8\x87\x38\xed\x31\x0b\x4c\x22\x2e\x8c\x8c\xa6\x55\x43\x7a\x03\x2e\x24\x82\x71\x02\xc6\x18\x63\xa8\xa5\x9d\xae\x7a\xd3\xc5\x8a\x9e\xa3\xe9\x7a\xce\xfe\x67\xb3\xa2\xe7\x47\x68\x13\xa2\x79\xfd\x02\x95\xb3\x9f\x14\xdb\xaa\xc8\xb3\xa8\xcd\x8b\x67\x35\x80\x0a\x7a\xa4\x65\x16\xa0\xd4\x9a\xe5\x41\xed\xa1\xb4\x56\xbe\x49\xb6\xeb\x07\x24\x9c\xb3\x7b\x7b\x68\x56\xda\xfb\x07\x05\xa9\x5b\xda\x77\x19\xff\x25\xd1\xb3\x49\xd4\x9d\x0c\x6e\x59\xd9\xbb\xde\xcd\xfc\x1f\xd5\xa5\xe9\x65\x87\xb8\xab\xa7\xd5\xbe\xfe\xdc\xdb\x86\x55\xbc\xaf\xf2\x82\x36\xcc\x65\xd1\xdc\xd6\xb6\x49\x3f\xa7\x6d\xfb\xb9\xf7\xd5\x98\x9f\xda\xfb\x9f\xff\x7c\xa6\x59\x4e\xa2\xba\xc9\x4b\x2e\xff\xdf\x4f\xa2\x1d\x39\x30\x37\x6f\xb7\xa7\x87\x4a\xcc\x10\x70\x96\x8f\xfe\x29\x3f\xd7\x55\xd3\x91\x92\x19\x62\x6e\x3e\xdb\x13\xc9\x7a\x81\xf5\xfd\x6a\x02\x40\x97\x20\x89\x2c\x7c\x6d\x18\xf8\xc8\xb8\xcb\xbf\xfd\xe6\x5d\x2f\x24\xd2\x3b\x56\xbd\xb9\xef\x28\xef\x73\xce\xdb\xa0\x90\x3b\xee\xf5\x73\x97\x80\xa3\xfc\x78\x6a\xe8\xe1\x27\xde\x66\xd9\x54\x36\x8e\x76\xd1\xfb\xe8\xc3\xfb\x88\x74\x5d\xf3\xa1\x87\xf9\x18\xbd\xff\xf8\x5e\x62\x0d\x1e\xda\x08\x26\x03\xd2\x50\x59\x85\xff\xdf\x0f\xef\xff\x4a\x9e\x49\x9b\x36\x79\xdd\xed\xde\xff\x24\x65\xae\x4a\xbf\x7b\xef\xa0\x2c\xe9\x30\x27\xf8\x6f\x97\xaa\xa3\x6c\x7e\xe6\x60\xf6\x68\xf8\x6e\xbb\xdd\x32\xe9\xd5\xe4\x48\xe3\x7d\x43\xc9\x97\x38\x2f\x7b\x67\x7f\x17\x91\xe7\x2a\xcf\x04\xb9\xae\x77\xea\x39\x11\xe5\xe3\x32\x6d\x8e\xb9\xb7\x1f\x33\xdd\x17\xc0\xf9\xf9\x38\x89\x3a\xc1\xda\x08\x61\xe9\x3d\xbd\x3b\x93\x97\xf8\x6b\x9e\x75\x27\xbe\x32\xb1\x7b\xef\x34\x9f\x44\xa7\xc5\x24\xe2\x23\xec\x5d\xd5\xd4\x27\x52\xb6\xbb\x68\xc1\xf8\xff\x9a\x67\xd5\xd7\xfe\x2f\x0d\xda\x62\x81\xc9\x4c\xe7\x00\xcc\xf4\xa6\x77\x7a\xb0\xb9\x98\x96\xe4\x79\x4f\x1a\x43\x14\xdc\x5c\x71\x80\x7d\x57\x3e\x4d\x53\xd2\xd0\x6e\x12\x4d\xb3\xa6\xaa\x2f\xf5\x13\xf8\x08\x7b\x22\xee\xaa\x3a\xc6\x87\x8e\xa4\x56\x90\x3d\x2d\x9c\xbd\x97\xf4\xa6\x85\x03\x0e\xb6\xc5\x6d\x47\x10\xfa\x1c\xad\xb7\x2c\xf2\xe7\xc9\x14\x85\xe2\x10\x17\x08\x57\x03\x5e\x27\xcd\x00\x29\xf0\xed\xe4\x6c\x41\x96\x65\x16\x4d\x66\xec\xfe\x59\xf8\x91\x29\xb5\xbd\xca\xef\xff\x5b\xf1\x5a\x9f\xf2\xb4\x2a\xdb\xe8\x5f\x49\x71\x28\xf2\xf2\xd8\x7e\xdf\xeb\x41\xdb\xa4\xbb\xe8\xd2\x14\x1f\xa6\xd3\xcf\x3d\x4a\xfb\xf9\xa8\x40\xe3\x93\x04\x8d\x1b\x7a\xbc\x14\xa4\x99\xd2\xaa\xfb\x78\x1b\xda\xff\xf3\x5d\x4e\x0f\xf9\xcb\xc7\xbe\x59\xbd\x5b\x48\xba\x0f\xdf\xd3\xf3\x9e\x66\x19\xcd\xe2\xaa\xa6\x65\x3f\x07\x7e\xff\xb1\x5f\xfd\xbe\x0b\x27\xfc\xb5\x3a\x1c\xe6\x1f\x23\x49\x90\xfd\x79\x13\x11\x9d\xc6\xd5\x24\xba\x0e\x50\xe8\x9a\x0b\xbd\xa9\x35\xed\xf3\xf1\xbb\x01\xe0\xff\x57\x00\xa2\x5c\x93\x5d\xfb\x7c\xfc\xfe\xa3\xe8\xfa\xa9\x42\xf2\xac\xf7\xd8\x22\x6d\xc6\x67\x79\x67\x04\x20\x50\x6b\xe0\xa2\x97\xfb\xa9\x8f\xe6\x24\xbe\xe4\xcb\x57\xcd\xa5\x9d\x41\x3f\x8a\xd3\x38\x57\x55\x77\x62\x13\x33\x29\xbb\x9c\x14\x39\x69\x69\xa6\x3c\xb5\xaa\x7d\xb1\xe0\x8e\x0d\x79\x6d\x53\xa2\x16\x20\x43\xe3\x63\x36\x31\xe7\xed\x17\x38\xd3\x0e\x96\xfe\x2f\x73\xf2\xde\xc6\xa9\x8b\x4b\xeb\x82\xdf\x23\xf0\xf4\xd2\x08\xf0\x49\xa4\x7f\xae\x5c\x64\x12\x92\x22\x84\xce\x79\xe9\xae\x79\x3e\x9b\x23\x28\x69\x51\x5d\x32\x17\xca\x3a\x99\x61\xec\x96\xcf\xb4\xa8\x6a\xea\xc2\xda\x24\x5b\x4c\x28\xb4\x4c\xf3\xc2\x8d\x73\x40\x70\x8e\x05\x69\x5d\xed\xa1\x09\xca\xdc\xf9\xd2\xe6\xa9\x1b\x05\x13\x01\xf7\x89\xdd\x38\x0b\x04\xe7\x44\x49\xd3\xb9\x51\x56\x58\x35\x1d\x69\xdc\x18\x6b\x07\x46\x4c\xcf\x75\xf7\xea\xc6\xdb\x20\x78\x97\x96\x7a\x6a\x7a\x40\x30\x0e\x79\x71\x76\x63\x60\xdd\xd9\x9d\xe2\x82\x34\x47\x97\x12\xd0\x64\x96\xa0\x58\x6e\x78\xac\x37\xfb\x5a\xf2\xd6\x2d\x68\x54\xa5\x2b\xd7\x60\xa5\xc9\x0c\xeb\xcb\x86\x9e\xab\x67\x4f\x43\x96\x08\xce\xcf\x55\x75\x8e\xf3\xd2\x8d\x84\x69\x00\x43\xaa\x2e\x9e\xe6\x60\x5a\x50\x1d\x0e\x6e\x04\xac\xfb\xdb\xfc\x58\x12\xd7\x48\xa3\xc9\x0c\x53\x80\xb4\x3a\xba\x11\xd0\xfe\x6f\x48\xeb\xee\xcc\x39\xd6\xf9\xa7\xea\xec\x96\xf2\x1c\xeb\xfe\x43\x5e\x78\x30\xb0\xbe\xef\x72\x5f\x1d\x68\xef\x57\xc4\x65\xff\x68\x32\xc7\xfa\x3e\xab\xbe\x96\x45\x45\xb2\x98\x14\xee\xae\x9c\x63\x0a\x20\x31\xdd\x58\x98\x02\x5c\x6a\x3f\x0e\xa6\x03\x79\xb9\xaf\x5e\xdc\x28\x98\x0a\xf4\xb3\x77\x9c\xe6\x4d\xea\x93\x39\xa6\x0a\x0d\xad\x29\x71\x4b\x62\x81\xe9\x42\x43\x0f\x0d\xf5\x28\xd0\x02\x53\x87\xde\x14\x78\x85\xbe\xc0\x54\xa2\xf7\x43\xdc\x18\x98\x4a\x1c\x0a\xe2\x1e\x0d\x0b\x4c\x25\xfa\x05\x58\x7d\xaa\x4a\xea\x9e\xad\x16\x98\x42\x3c\x57\xc5\xe5\x4c\xbd\x43\x7c\x81\xa9\x84\xc0\xeb\xf5\xc9\x8d\x88\xe9\x85\x40\xbc\xd4\x6e\x34\x4c\x37\xfe\xd6\xa4\x55\xe6\x56\x8b\x05\xa6\x16\x7b\xe2\x47\x5a\xa2\x13\x84\x47\xf2\x4b\x74\x86\x20\x47\xb7\xcc\x97\x98\x3e\xec\x2b\xcf\x04\xb1\xc4\xf4\xa1\xc7\x38\x93\xc6\x83\x85\xe9\x04\x0b\xd8\xb8\x51\x30\x75\x48\xc9\x99\x36\xc4\x8d\x83\xa9\x02\x8b\xba\x3b\x31\x30\x1d\xd8\x57\x85\xdb\x9a\x2c\xb1\xee\xe7\x9b\x50\x6e\x1c\x74\x82\xa0\x2f\x9d\xf4\xd2\x5d\x88\x2b\x54\x05\x7a\x44\x1e\x85\x70\xe2\x61\x9a\xc0\xf6\x93\xe2\x82\x1e\x3c\xf5\x61\xfa\xc0\xf1\x52\x5a\x76\x1e\xaf\x69\x85\xe9\x05\xc7\x6c\xfc\x4d\xc4\x54\x83\x23\xfe\xf5\xd2\x76\xf9\xc1\xed\xdb\xad\x30\x15\xf1\xba\x43\x2b\x4c\x41\xf2\x32\xa3\x65\x37\x22\x18\x7c\x0e\x61\x88\x23\xed\x43\xdd\x49\x92\xd2\x7e\x26\x8e\xd9\x06\xb1\x1b\x17\x5d\x27\xe4\x69\x77\x69\xdc\x66\x63\x8d\xe9\xcc\x99\xd4\x71\x3f\x42\x3d\x3d\xb8\x46\xfb\x9e\xef\xc3\x3b\x71\xb0\x5e\xef\x7c\xc3\x7a\x8d\x75\x37\xcd\x72\x0f\x06\xba\x56\x38\x11\x9f\x08\xb0\x6e\x66\x7b\x38\x6e\x14\xac\x83\xbd\x6e\xef\x1a\xeb\xd8\xb6\xa3\x75\xbc\x27\xe9\x97\xaf\xa4\x71\xdb\x90\x35\xd6\xaf\x07\xd2\x76\xe3\xa8\x1b\xac\x77\xc7\xb1\x30\x7b\xc0\xa2\x11\x4e\x0c\x4c\x1b\x6a\x72\x69\xdd\x02\xd9\x60\xca\xd0\x76\x95\x7b\x2a\xdd\x60\xca\x70\xa8\x1a\x7f\x5b\x30\x7d\x60\xc2\x1b\xc5\xc4\xd7\x90\xb4\x1e\xc7\xc4\xb4\x83\xfe\x95\xa6\x6e\xb5\xdd\xa0\xab\x88\x13\x7d\x6e\xaa\x11\x23\xbc\xc1\xb4\x43\x62\xfa\x8d\xcd\x03\xa6\x1d\x75\x71\x69\xd9\x9a\xc7\x8d\x86\x06\x0a\xf2\x72\x14\x0f\x53\x12\xbe\x5a\x1c\x41\xc4\x54\xa5\xfa\x32\x82\x84\x69\xcb\xdf\x2e\xb4\xed\x72\xb1\xa8\x73\xa3\x62\x3a\x93\x97\x87\x6a\x04\x0d\x55\x98\xb4\xa1\xb4\x6c\x4f\x95\xa7\x1b\x30\x75\x11\x72\x19\x59\x40\x3c\x60\x6a\x53\x7d\x19\x45\xc3\x1d\xcc\x72\x0c\x6f\x8b\x29\x0c\x69\x9a\xea\xab\x5f\x47\xb7\xa8\x83\xc1\xf0\xfc\x1a\xba\x45\x67\x19\x86\xe8\xf1\xb9\xb7\xa8\x77\xc1\xb0\xbc\x2e\xfe\x16\x53\x19\x36\x77\x78\x97\x49\x5b\x4c\x5d\x1a\xca\x4e\xa6\x1d\x2e\x85\x3b\x74\xb0\xc5\x14\x46\x20\xb2\xd3\x43\x6e\x4c\xd4\xc2\xbc\xa4\x05\x39\x93\x51\xfd\x9e\xa1\x91\xbe\x63\xee\xee\xc0\x19\x1a\xe8\x2b\x28\x71\xae\xb3\x66\x68\x98\xef\x90\xbb\xa7\xe1\x59\x82\xce\xf5\xaf\x94\x6d\x3d\xb8\xb1\x30\xe1\xf7\x58\x69\x51\xb9\x67\x9f\x19\x1a\x20\xfc\x4a\x9a\x32\x2f\x8f\x23\xc2\xc3\x44\x5f\x17\xa4\xf4\x54\x86\x1a\x77\x52\xd0\x32\x73\xc7\x30\x67\x68\x9c\xb0\x21\x65\x56\x39\x63\x8b\x33\x34\x4a\x98\x56\xe7\x33\x75\x3b\x59\x33\x34\x54\x78\x26\xc7\x92\x7a\x70\xd0\xe0\xb7\x98\x75\xdc\x43\x73\x86\x46\x0c\x25\x9e\x6f\x70\xce\xd0\xb8\x61\x43\xbb\xaf\xd4\xc7\x26\xee\x0d\x56\x75\xdd\xf7\x73\xea\x09\x3a\xcf\xd0\xe0\xe1\xa1\x2a\xd8\x36\xa4\x57\xb7\xd0\x28\xa2\xc0\xf4\xea\x32\x1a\x4a\x14\xf6\x40\x9e\xf3\x73\x23\xe3\xb1\x24\x86\x7c\xaa\x9a\xfc\xe7\xaa\xec\x3c\xe8\x78\x88\x31\x73\x3a\x39\x33\x34\xc2\xb8\xbf\x14\xc5\xa9\x6a\xdc\x4d\x44\xa3\x8c\x7b\xea\x36\x75\x33\x34\xca\x98\xf6\xd2\x38\xe4\x29\xe9\xdc\xdd\x80\x06\x1b\xbb\xd3\xe5\xbc\x6f\x7d\x1a\x8a\x46\x1a\x05\x9a\x57\x41\xd1\x60\xe3\x89\x94\x99\x7f\x8e\x9b\xa1\x01\x47\x86\xe7\x9b\x53\x67\x68\xd0\x91\xa1\xf9\x1a\x87\x29\x09\x43\xf2\x36\x0d\x8d\x39\x72\x5f\x21\x64\x1a\x9f\xa1\xe1\x47\x0d\xdf\xdb\x54\x34\x0e\xa9\xa1\x7b\x9a\x8c\x86\x24\x35\x64\x7f\xd3\x31\x2d\x3a\x16\xd5\xde\xad\x78\x68\x68\xf2\x6b\x43\x4b\xf7\xae\xd8\x0c\x0d\x4b\x76\xa4\xfd\xe2\x8c\xc6\xcd\xd0\x80\xe4\x21\x2f\x3c\x71\x97\x19\x1a\x8d\xdc\x37\x39\x3d\xa4\xc4\x63\xd1\xd0\x80\x64\xef\xda\x70\xef\xd6\x89\x87\xc6\x24\x33\xd2\x9e\xf6\x95\x67\xfd\x34\x43\x23\x93\x35\xa9\x69\x93\x16\xb9\xbb\xa7\xd1\xf0\x24\xdb\x59\xf4\xef\xfa\xcd\xd0\x28\x65\x91\x97\xce\xf5\xff\x0c\x8f\x50\x9e\x2a\x8f\x13\x80\x46\x28\xeb\x4b\x7b\xaa\xdd\xfb\x5e\x33\x34\x44\x79\x69\x3d\xa2\xc3\x3a\xf8\xb8\xf7\x08\x0d\xeb\xda\xb6\xf2\x4c\x8c\x68\x94\xb1\xc7\x88\xf7\xaf\x31\x29\xea\x13\xd9\x7b\x66\x64\x34\xd6\x68\x62\xfb\xdc\xed\x19\x1a\x75\x94\x14\xf8\x69\x1c\x27\x2a\x1a\x73\x80\xa8\xfe\x9a\xd1\xf5\x81\xe4\xbd\xeb\x9a\x7c\x7f\xe9\xdc\x7b\x16\x33\x34\x02\x69\xe3\xfb\x79\x40\x35\xa2\x64\xe1\x2a\xea\xd6\x0b\x34\x22\x49\x5f\x6a\x52\x7a\x70\xf0\x9d\x4d\x7e\xee\xca\x6f\x35\xd1\x50\xa4\x42\xf5\x58\x6b\x34\x1c\x59\x54\x47\xcf\xe6\xf0\x6c\x8d\xee\x75\x16\x9e\x0d\xd5\x19\x1a\xbd\xec\xab\xf1\x6c\x27\xcf\xd0\xf0\x65\x49\xbf\xc6\x5f\xf3\x32\xab\xbe\xba\xf1\x70\xcf\x35\xad\x3c\x26\x10\x0f\x63\x12\x77\x80\x71\x86\x46\x31\xbd\xee\x26\x1a\xc4\xec\xeb\xf0\xb0\x85\x6e\x67\xb0\xa3\x6e\x6e\x1c\x4c\x17\xe8\x8b\x17\x07\x8d\x5b\xb6\xd4\xa3\xac\x68\xcc\xf2\x50\x54\x75\xfd\x1a\x67\xee\x03\x47\x74\x86\x86\x2e\x05\xa2\x5f\x18\x68\x04\x53\x60\xfa\x0f\x41\xcc\xf0\x50\xe6\x50\xa9\x1b\x11\x0d\x67\x72\x44\x6f\x67\xa3\xd1\xcc\xb4\xa1\x59\xde\xf5\xeb\x20\x4f\x2b\x31\x2d\xe1\x57\x47\x3c\x96\x16\x8f\x67\x5e\xba\x82\x36\xee\x79\x18\x0d\x65\xf2\xc3\xb8\x4e\x1c\x34\x86\x99\x56\xe7\xba\xa1\x6d\xeb\xe9\x3c\x34\x88\x49\x49\xe3\x9f\xc4\xd1\x10\x26\x43\xf1\x1a\x6d\x34\x80\xd9\x55\x5f\x7d\xed\x42\xe7\x9a\x8e\x74\xee\xe9\x05\x0d\x5b\xb6\x99\x7f\xd7\x68\x86\x46\x2d\x4f\xa3\x58\xa8\xed\xb8\xec\xd9\xe1\x6f\x0f\x8b\xe8\x2e\x08\x3b\x91\xdb\x76\xb4\xf1\x55\x88\xfb\x29\x17\xb6\x74\x29\xf6\x6e\xa5\x42\x63\x96\x1c\x71\x15\xcf\xdc\x68\xb8\x9f\xd2\xa3\xad\x7d\x68\xb8\x73\xd2\xa3\x6d\x7c\x68\xe8\x22\x45\xde\xee\x8d\x7d\xbb\xe5\x33\x34\x6a\xd9\xd0\x63\xde\x76\xfc\x0a\xc0\x08\x3a\xba\x73\x5e\x54\x97\x6c\xf4\x7c\xcd\x0c\x0d\x43\x72\x5c\xff\x29\x9b\xd9\x16\x53\x84\xae\xa1\x34\x4e\xab\x32\xf7\x59\x96\x2d\x7e\x7c\x8a\xd2\x38\xa3\x69\x9e\x5d\x2a\xe7\x91\x4d\x3a\x4f\x50\x63\xe1\xe4\x72\x8e\x06\x4a\x7b\xfb\xec\x3d\x4a\x35\x47\xa3\xa5\xbd\x75\x1e\x41\x43\x97\x21\xf4\x99\x16\x1e\x8f\x69\x8e\x86\x4d\x7b\xd5\x71\x63\xa0\x2b\x11\xd2\xba\x63\x29\x73\x34\x5c\x4a\x0a\xea\x9e\xc2\xe7\x68\xf8\x92\xfe\xed\xc2\x6e\x82\x3b\xbb\x77\x8e\x46\x30\xbf\xe4\xa5\xf3\x1c\xcb\x1c\x0d\x5f\xfe\xed\xe2\x59\x97\xe2\x47\x77\x6b\xe2\x76\x68\xe7\x68\xdc\x72\x9f\xb7\x27\xf7\x7e\xe5\x1c\x8d\x58\x7e\x29\x7d\x91\x92\x39\x1a\xb0\xdc\x93\xfd\x6b\x7c\xa8\x9a\xf3\xa5\x70\x9e\x66\x99\xa3\xf1\xca\xce\x1d\xf7\x9d\xaf\x0f\xd8\x61\xeb\x7d\x41\xd2\x2f\xde\xe5\xf9\x1c\x0d\x53\xee\xdd\x73\xed\x1c\x0d\x4d\x92\xba\x76\x8e\x85\xc3\xc3\x01\x3b\xbf\x4c\x1b\x4f\x90\x62\x8e\x06\x24\x4f\xd5\xa5\xf1\x1d\x7b\x9e\x2f\x66\xd8\x11\xf2\x82\x9c\xdd\xfd\x8a\x46\x24\xb3\x4b\x5d\x78\xe3\x91\x73\x34\x1e\x59\xe7\xc7\xe3\x6b\xbc\x27\xee\x58\xc3\x1c\x0d\x48\xb6\x69\xde\xb6\x55\xe3\x36\x75\x68\x34\x72\x9f\x77\x69\xe5\x5e\x49\xcd\xd1\x50\xe4\xbe\x73\x1e\x55\xc2\x11\x5e\xf6\x6e\xfd\x46\x11\x5e\x9d\x43\x35\x49\x08\xd6\xfa\xbf\x3a\xad\x9b\x03\xa1\xb9\xec\x9d\xca\x36\x4f\xf6\x19\x8e\x72\x1d\x02\xbb\xf1\xe0\x6c\x38\x1a\x42\xcd\x53\x1a\x17\x55\x51\xb8\x6d\x35\x1a\x39\x55\x68\x71\xd7\x5b\x6d\xf7\xc0\x43\x03\xa7\x34\xbb\xa4\xfc\x6a\xa0\x13\x0d\xdd\x6f\x67\xa9\x31\x02\xb6\x12\xe6\x68\xc8\x54\xa0\x8f\x6d\x63\xcc\xd1\xe0\xe9\x99\x96\x97\xf8\x44\xce\xfb\x4b\x73\xf4\xcc\x1d\x68\x10\xf5\x5c\x65\xa4\x18\x59\xa2\xcf\xd1\x58\x6a\xe5\xbc\x5f\x41\xe7\x68\x20\xf5\xd8\x10\xcf\xe0\x42\x83\xa8\xed\xa5\x64\xe6\xc9\xed\x33\xcf\xf1\x83\x9d\x32\xf7\x89\x1b\x0d\x3d\xde\xd9\xa3\xf1\xbb\x6f\x4e\x3c\xf4\x1c\x78\x8f\x07\x6e\x12\x3a\x91\x51\xcd\xd9\xff\x95\xa6\x9d\x38\xa5\xe7\x39\xe0\x33\x47\xa3\xaa\x1a\xb6\xc8\x56\xe1\x24\x80\x29\x8f\x46\x20\x40\x7d\xd1\x98\xab\x46\xc4\xb7\x59\x31\x47\xcf\x88\x6a\xe8\xa3\x63\x00\x0d\xe2\x6a\x24\xbc\xdb\x2d\x73\xfc\x00\x69\x93\x93\xf2\x58\xd0\x11\x5c\xfc\x0c\xa9\xc4\xf5\xb6\x1c\x0d\xed\x2a\xd4\x91\xae\x43\xa3\xba\x0a\xd9\xa7\x35\x68\x50\x37\xad\xca\xb6\xf2\x98\x63\x3c\x94\x7b\xa9\x69\x23\x2e\x28\x3b\x11\xd1\xd9\xf8\xb2\x1f\x43\x43\x4d\x53\x6f\xd6\xfc\x22\x45\xcf\x19\xf6\x68\x23\xbd\x88\x69\x10\xc3\xf3\x85\x6d\xe7\x68\xd8\x96\xa1\x79\x16\x20\x43\xc8\xf6\xf7\xac\xf0\x57\x4a\x6e\x21\xea\xc0\xae\xea\xff\xba\x35\xea\x09\xab\x44\x82\x97\xa4\xd6\x32\x4e\x74\xa4\x8e\x4f\xf9\xf1\x54\xb0\xe5\xba\xb8\x5c\xdc\x1c\xf7\xe4\x43\x32\x89\xc4\xff\x93\x57\x41\x55\x66\x2a\xed\x26\xe7\xfb\x7f\xa5\xc5\x33\xed\xed\x42\xf4\x6f\xf4\x42\xdf\x4f\x22\xf5\x61\x12\xfd\x4b\x93\x93\x62\x62\x24\xc9\x82\xec\x2c\x39\x3b\xfa\x55\xce\xe9\x72\xfe\xb0\xda\xcc\x96\x0b\x90\x3c\xe6\xbb\xc5\x62\xf1\x88\xe6\x6e\xfa\xee\x70\x38\x48\x0e\xf5\xa4\x35\x68\xaa\x1a\x8d\x79\x90\xa4\x06\x70\x05\xbe\x6a\x8c\xe9\x09\x6c\x88\xd0\x28\xc9\xde\x86\xec\x37\x8f\x32\x45\x0d\xcc\x63\x00\xf3\x4f\xed\x58\xfe\x16\x3d\xa9\x94\x24\x31\x5f\xac\xe6\x9b\x14\x25\x01\x52\x21\x40\x3a\x0c\x5d\xe5\xa4\xea\x4e\x79\x29\xb2\x4d\x3d\xc2\xef\xab\xfa\x85\x25\xc7\x88\x86\xeb\xb1\xe9\xa5\x8d\x1b\x76\x92\xa4\xaf\x1b\x40\xc7\xd5\xe1\xd0\xd2\x6e\x17\xc5\x73\x95\xef\x08\xc9\x88\xa4\x72\xb4\x88\x8c\x01\x66\x32\xa7\x73\x9e\x65\xc3\x2d\xda\x94\x34\xd5\xa5\xa5\x05\x4f\xdb\xf2\x34\xcd\x3b\x7a\x7e\x22\x4f\x2c\x35\x01\x5e\xc8\x8b\xf2\xf3\x31\x6e\x68\x5b\x57\x65\x9b\x3f\xd3\x09\xbb\xe0\x7e\xba\x9c\xf7\x25\xc9\x8b\x48\xe2\xab\x2f\x4f\x92\x19\x3d\x77\x19\x4f\x45\xa2\xe5\x33\x78\xc4\x53\xbf\xf0\xfa\x7a\xd5\x12\x29\x29\xc4\x88\x6a\x48\x96\x5f\xda\x5d\xb4\x56\x12\x61\x90\x03\x2b\xbf\xf8\xae\x3d\x8f\xd4\xad\xa5\xbe\x19\x1f\x0d\xb8\xfa\xe3\xd9\x55\xbe\xcb\xb2\xec\xd1\x6e\xc6\xd2\xb0\x00\x0d\x29\xe5\x9d\x6e\x52\x14\xd1\x74\xde\x46\x94\xb4\x34\xce\xcb\xb8\xba\xb0\x41\x10\x57\x21\x50\x23\x20\x50\x74\xfc\x14\x03\x26\xe3\x95\x4a\x33\x26\xb2\x6c\x71\x8d\x63\xf3\x68\x34\x17\xc6\x4b\x7c\x93\x19\xc0\xe4\x67\x95\x27\x06\x34\x5a\xde\x4c\x97\x22\xa1\x54\x69\x65\xdb\xc4\x55\x59\x70\x8b\x36\x5c\x6b\x27\xfb\xb6\x2a\x2e\x1d\xbb\xd6\x2e\xbb\x8d\x93\x57\x1d\x52\x1b\xf9\x8a\x60\xb2\x9b\x58\x94\x9a\xc9\xc5\x98\x25\x2b\xf2\x7a\x17\x35\x34\xed\xa0\x71\xc5\x32\xdc\x48\xde\xf8\x48\x25\xfd\x12\x50\x66\xa3\x43\x8a\x06\x53\x30\x34\xa3\xed\x48\x97\xa7\xa0\x11\x52\xd7\x4c\xdd\xd3\x32\x77\x59\x89\xb8\x06\xb6\xc1\x38\xf9\xb1\xa9\x0a\x95\x56\x8b\x5b\x30\x34\x23\xd6\xf4\x34\x9b\x44\xd3\xd3\xbc\xff\xcf\xa2\xff\xcf\xb2\xff\xcf\xaa\xff\xcf\x7a\x12\xf5\x85\x32\x8d\x48\x5f\xd2\x17\x9c\xd6\xe3\x26\x5a\x26\x01\x58\x61\x49\x00\xa6\x33\x67\xbe\xb1\xe9\x69\x16\x4d\xd9\xe1\xd4\x9e\x81\x59\xa4\x7e\xce\xc1\xe7\xf9\xf0\x79\x01\x3e\x2f\x86\xcf\x4b\xf9\xb9\xb7\x46\xa7\xe5\x50\xb0\x02\xf0\xab\xe1\xf3\x1a\x7c\x5e\xcb\xcf\x80\x15\xc5\x09\xcb\x93\x32\x7c\x56\x9c\x00\x46\x06\x3e\x06\x36\xa2\x81\x87\x81\x85\x9e\x96\xe2\x01\xb0\x20\x39\x18\xa4\x3c\x9a\x52\x41\x5a\x99\xcd\x66\x83\x77\xeb\xd0\x8f\xa1\xe3\x75\x36\xa4\xd2\xbb\x4b\xa7\x0c\x34\xfa\x76\x2b\x22\xa1\xd2\x34\x5d\xa4\xf5\xea\x77\x8a\x3b\x5d\x63\x75\x2d\x85\x2d\x9d\x05\xb4\x74\x09\x78\xbf\x55\x6f\xa0\xf6\x61\x1d\x1f\x05\x76\xbb\xca\xcd\x08\xfb\x54\x64\x95\x04\x00\x0b\x30\xe5\xb1\x3e\x9e\x5b\x10\xb0\x85\x0b\xa5\x05\x30\x0d\xe5\x12\xca\x80\xb5\xc1\xf4\x49\x1f\x00\xc4\x8a\xb5\xc1\x84\x80\x34\xd6\xba\x9d\x10\x10\x83\xbb\x52\xeb\x9e\x4a\x94\x68\xdd\x50\xc8\xdc\x49\x8e\x49\x04\xd2\x5c\x83\x4f\x72\xa0\x2c\x50\xb3\xb3\x14\xe4\x45\x8e\xae\x0f\xd1\x39\x2f\xf9\xac\x1f\xed\x36\xeb\x87\xfa\xe5\x23\xab\x73\xa8\x5d\x93\xd0\xac\x67\x4f\x25\xdb\x91\xbd\x86\xa7\xe1\x1c\xba\xec\x4c\x9a\x2f\x93\x48\xe5\xf6\x1c\xb2\xb1\xcd\x79\xfe\x35\xcc\x55\x48\x0f\x0f\x74\x21\x09\x30\x2f\xb3\x5f\xc5\x31\x7c\xf6\x97\x70\xdf\xfa\x8f\x1a\x14\xcf\xd5\x6b\x82\xb1\xaf\x1a\x1c\xbf\x3d\x69\x01\xf2\xcf\x1a\xa4\xb8\xf4\x68\x81\x8a\xef\x1a\x6c\x59\x7d\x6d\x08\xef\xd6\xaf\xa7\xbc\xa3\x2c\x55\x1b\x4b\x0f\xd3\x7f\xd7\x9b\x53\x7d\xa5\x4d\x4a\x5a\x3a\x10\x06\xd9\x22\x55\xa9\x86\x73\xa9\x6b\x0f\x8e\x2a\xd5\x1b\x4a\x6a\x76\x19\xf6\x67\x1c\x69\x28\xd6\xb0\xce\x17\x99\xed\x0c\x31\xab\x0c\xa2\x6e\x72\x95\x83\x57\x5f\x5a\x48\xcf\x5f\x83\xc3\x56\x11\x0f\xeb\x64\x9b\x68\x44\xdb\x4b\x9a\xd2\xb6\xd5\x89\xa6\x9b\xf5\x22\xd3\x89\x0a\x38\x8c\xe8\x7e\xb5\x9c\xa7\x1a\xd1\xbc\x3c\x54\x3a\xc5\xd9\x26\x79\x38\xe8\x14\x7b\x20\x8c\xdc\x72\x35\x5f\x6f\x35\x72\xe2\x0a\x83\x06\xf6\x40\xd6\xd9\x62\xaf\x53\x14\x70\x08\xd1\xf5\x7a\x35\x33\x78\xcc\x48\x79\x34\xa0\xc8\x76\xb9\x5c\xce\x75\x9a\x1c\x0c\x21\xf9\xb0\x5c\xac\x16\x72\x6c\x4f\xf7\x47\xb4\x7b\xa4\xff\x6d\x0f\x37\xa3\xe3\x06\x7c\x50\x15\x82\xa6\xf7\xe0\xfe\xa8\xf5\x1f\x02\x9f\x1d\x0e\x49\xf6\x00\xab\xb1\x3b\x12\x41\x4b\x67\x74\xbe\x5f\x80\x6a\x54\x8f\x62\x75\x6c\x69\x76\xd0\x9a\x62\x74\x2d\x82\x43\x0e\xd9\x76\x70\xb7\xf7\x47\xad\x8f\xc7\xac\x13\x01\x08\xfe\x6a\x0e\x1b\x9a\xee\x57\xa0\x1a\xd0\xeb\x18\xf8\x3c\xa3\x19\x85\xb5\x58\xdd\x8f\x60\xd1\xe5\x7e\xbb\x57\x1a\xcb\x92\xd8\xf1\xf3\x3d\xd0\xf6\xaa\xc9\x64\x0b\xbd\x81\x1d\xcb\x1d\x1c\x25\xc6\x3a\x45\xcb\x11\x6d\xad\x4e\xaa\x62\x12\x5d\x0a\xcb\xcf\x48\xfc\x4e\x46\x55\x44\x3d\x62\x55\x44\x17\x8e\x2f\xc8\xe8\x94\x24\xa2\x52\x31\x96\x4f\xe3\x52\xb2\xa4\x5b\x5a\x02\x4e\x1e\xe3\x8b\xc4\x8c\xd7\x82\xbc\x5c\x2a\x12\xc1\x91\xf9\xa2\xd7\x85\x2a\xea\xe5\x5f\xe2\x95\x5c\xe4\x8e\xd2\x7b\x2a\x72\xff\xda\x5a\xd6\xd5\x88\x25\x81\xb6\x32\x13\xf5\xad\x94\x74\xb2\x30\x79\xce\x07\x79\x66\xd9\x24\xca\x90\xfc\xb9\xc3\x9a\x5c\x02\x76\xb6\x4b\x0d\xf2\x79\x6b\x1e\x87\x10\x4c\xa0\xc7\x90\x15\x20\xf4\x2f\x99\x79\x77\x28\x2a\xd2\xf1\x79\x5a\x66\x5c\x64\x2b\xd5\xb5\x50\x31\x74\xfd\xf9\x2e\x2d\x28\x69\x00\x96\x35\x97\x0f\x5f\x07\x7c\x5a\x14\x79\xdd\xe6\x2d\xaf\x07\x9b\x7e\x79\xea\x41\x83\x51\xe1\xe6\x68\x6d\x9e\x3d\x24\x9a\xa7\xc3\x52\x73\x66\xa4\x23\x71\xd5\xe4\xc7\xbc\x24\x45\xcc\x13\x75\x4e\x22\x33\xaf\xba\x5c\x61\x9e\x68\x51\x3b\xc6\x10\x8f\x7c\x69\x53\x6a\x5e\xe6\x2c\xf1\x5b\x7b\x36\xfd\xa8\x2d\x8f\xc4\x8c\x4d\xf6\x43\xe6\x4e\xdd\xc7\xea\xc7\x9c\xb1\xbc\xe1\xae\x26\xe6\x46\x6e\xa6\x2b\x6d\xe0\x2b\xbd\xb4\x87\x3d\xa8\xaf\x2a\x76\x05\x69\xbb\x38\x3d\xe5\x45\x36\x89\x40\x49\xed\x2a\xb8\x40\x14\x91\xd0\xd7\x31\xe6\x01\x96\xf4\x37\xc1\x27\xf9\x7a\x00\xf8\x34\x78\xa3\x76\x78\x4d\x4f\x13\x1f\x18\xcf\x1d\xba\xc9\xe2\x45\x84\xc8\x11\x96\xb0\x12\x88\x22\x1a\xad\xc2\xfc\xdf\xff\x65\x9e\xcc\x96\xd1\x5f\x92\xe4\x5f\x92\xef\xd5\x14\xa1\x70\xe3\x86\x3e\xd3\xa6\xd5\xe8\x4d\xeb\x4b\x51\x00\x87\xd7\xb0\x31\x33\xd4\xc8\x24\x8f\x98\x6b\x0c\x83\x6f\xca\x42\x81\x4e\xb7\x74\x22\x71\xb3\x68\x8a\x06\x03\xd1\x65\xc4\xf2\x9f\xda\x40\x2e\x09\xc3\x76\xeb\x75\x69\x19\x6c\x21\x98\xb3\x4f\x20\x90\xb7\x7b\x3c\x7d\x22\x99\x10\xdb\x26\x9e\xf6\x72\x08\x6f\x73\x05\x11\x6f\x6b\x15\x19\x6f\x63\xbd\x94\x00\xa1\xc8\xd0\xc3\x5e\x03\x23\xa6\x8d\xb2\xcd\x24\xcb\x1a\xe9\xd5\x79\x17\xa3\x66\x2e\x4c\xff\x54\x14\xf6\x16\xc0\x9f\x68\x59\x54\x93\xe8\x4f\x55\x49\xd2\x6a\x12\xfd\x81\xed\x3a\x92\x76\x12\xbd\xff\x43\x75\x69\x72\xda\x44\xff\x46\xbf\xbe\x07\x0f\x05\x00\xea\xba\x29\x9c\xd7\x2f\x32\xa4\x6c\xdb\x57\xe5\x6b\x6e\xe6\xab\x25\x75\xad\x4a\xb7\x87\xf9\x61\x89\x47\xaa\x45\xb5\x5f\xf6\xd9\x0d\xb5\xfa\x3c\xf3\x05\x52\xdf\x42\x8f\x8c\xc3\x24\xd6\x79\xd9\xd2\x2e\x4a\x58\x7c\x37\x4a\x8c\x1d\xb2\xe9\x7c\xf5\x51\xed\xc6\x85\x22\x80\x96\x59\xad\x33\x9f\xf2\x90\x1b\x07\xa6\x7f\xe1\xe2\x56\xbe\x94\x62\x7e\x93\x11\x12\xb1\x9b\x63\x5b\x72\xc5\xc1\x56\xce\x59\x66\x1c\xc5\xe4\x6c\x71\xed\x06\xde\xd7\xaa\xc9\x78\x02\xe8\x5d\x24\xf2\x40\x17\x85\x2a\xe8\x3d\x0a\xf9\xbd\xff\xe0\x52\x99\x55\xff\xcf\xb1\xed\x91\xa6\xa9\x57\x99\xfa\xe6\xdb\x7a\x6c\xca\xdc\xf9\x7e\xc5\xa3\x19\x86\xa8\x1b\xca\xf8\xc6\x79\x05\x4f\xcb\x20\x5c\x29\x8b\xdf\x13\x69\xd3\xa6\x2a\x0a\x95\x3b\xfa\x4c\x5e\x94\x48\x17\xcb\x44\xdf\x58\x88\x5f\x77\x11\x87\x57\xbb\x6c\xbd\xe7\x95\x1b\xef\x42\xf8\xa7\xad\x99\xd6\xc9\x12\x56\xdf\x1a\x10\xa0\x20\xfe\x3f\xe6\xb2\xea\x8c\x48\xdf\x74\xb3\xd2\x9d\x3f\x8c\xca\x76\x3b\x1f\xa1\xb2\xdd\x8c\x53\x99\xcd\x93\x64\x84\xcc\x6c\x66\xd0\x19\xe0\xe2\x43\x71\xc9\xb3\x5f\x5b\x86\xd3\xa6\xfa\x0a\x2d\xbf\x40\x8b\x0d\x6a\x62\xc9\x34\x1b\x16\x31\xd3\xb4\x2a\xe2\xe2\x18\xcf\x26\x91\xfa\x99\x80\xdf\xf0\xfb\x7c\xf8\x0d\x7e\x2e\x26\x5c\x2e\xec\x8f\xe5\xf0\x7d\x35\xfc\x5c\x0f\x3f\x37\xc3\xcf\x87\xe1\xe7\x56\xd1\x38\x67\x8a\x95\xfe\x67\x02\x7e\xc3\xef\xf3\xe1\x37\xf8\xb9\x80\x64\x96\xc3\xf7\xd5\xf0\x73\x3d\xfc\xdc\x0c\x3f\x1f\x86\x9f\x03\x2b\xed\x59\xb1\xd2\xff\x4c\xc0\x6f\xf8\x7d\x3e\xfc\x06\x3f\x17\x90\xcc\x72\xf8\xbe\x1a\x7e\xae\x87\x9f\x9b\xe1\xe7\xc3\xf0\x73\x60\xe5\xa5\x55\xac\xf4\x3f\x13\xf0\x1b\x7e\x9f\x0f\xbf\xc1\xcf\x05\x24\xb3\x1c\xbe\xaf\x86\x9f\xeb\xe1\xe7\x66\xf8\xf9\x30\xfc\xdc\x1a\xfb\x81\x30\x5b\x77\x3f\x54\xf0\xcd\xcc\x71\x4d\x87\x5a\xf8\x0f\xd2\x48\xb0\x16\x36\xb9\xe3\xdb\x15\x60\xf7\xdd\x04\x98\x41\x80\xed\x6c\xba\xe6\xff\xb7\xb1\x00\x13\x08\xf8\xb0\x98\x2e\xc4\xff\x99\x80\x5b\x08\x07\xf6\x57\x24\xf3\xb0\x78\xbd\x76\xd6\xb7\x81\x70\xab\x07\x67\x75\x6b\x0d\xce\x6a\xdf\x0a\x16\x2f\xdd\xcd\x5b\x42\xb8\x85\xbb\x75\x0b\x08\x37\xb7\x5a\xa7\x8b\xdb\xdd\x3a\x4d\xea\xee\xc6\x31\xc7\x5a\xf4\xa1\x54\x4c\xbb\x0f\x39\xd4\x0c\x42\x79\x3a\x92\x43\x27\x10\xda\xd3\x9b\x0c\x7a\x0b\x81\xed\x2e\x65\x30\x0f\x10\xc6\xd3\xaf\x0c\x78\x03\x81\x3d\x9d\xcb\x80\xd7\x1a\x30\xde\xfa\x15\x84\xf1\x74\x33\x03\x5e\x42\x60\x4f\x5f\x33\xe0\x05\x04\xb6\x3b\x9c\xc1\xe8\x1d\x34\xd2\x76\xad\x9f\x46\x9a\xae\xf5\x12\x9c\x3b\x15\x50\x7b\x92\xfa\x21\x2c\x14\xa6\x1e\x3d\xd0\x0c\x00\x79\xb5\xa3\x07\x4e\x00\xb0\x57\x39\xda\x93\x50\x0e\x0e\x8b\xe9\x46\x7b\x12\xba\xc1\x41\xbc\xaa\xd1\x9e\x84\x6a\x88\x00\x91\x4f\x3c\xed\x49\x68\x86\x80\xc5\xdb\xbd\x02\x20\x5e\xbd\x68\x4f\x42\x2f\x38\xac\x57\x2d\xda\x93\x50\x0b\x0e\x8b\x69\x45\x7b\x8a\xb5\x6e\x19\x69\x35\xec\x9d\x91\x46\xc3\xbe\x41\x54\x82\x9f\x5e\x93\x4a\xa1\x07\x1f\x6d\xdd\x90\xd0\x33\x1b\xda\xa3\x24\x12\x2b\xb1\xb1\x3c\xda\x22\xb0\xb6\x36\x92\xad\x36\x02\xf6\xc1\x86\xf5\xe8\x8f\x40\xda\xd8\x48\x1e\x45\x12\x48\x6b\x04\xc9\x25\xad\x95\x0d\xeb\x51\x2d\x81\xb4\xb4\x91\x3c\x3a\x26\x90\x16\x36\x92\xad\x6c\x02\x16\xeb\xf0\x51\x59\x21\xfd\x3e\x2a\x2a\xa4\xd7\x43\x43\xf9\xf7\xf1\x51\xdf\xec\xa4\x5a\x3b\x08\x32\x82\xaf\x2a\xd7\x97\x4a\x6c\xdc\xe8\x10\x33\x7d\x4d\xa6\x75\xbf\x0e\x99\x68\x90\xfa\xf8\xd0\x20\xb7\xc6\x62\xd1\x2c\x7f\xd0\xca\xf5\x71\xa0\x01\x6e\x34\x40\x5d\xf7\x35\xc0\xb5\x0e\x68\xb5\x72\xa5\x95\x2f\xdd\x8d\x5c\x6a\x80\x0b\x77\x1b\x17\x1a\xe0\xdc\x6a\xa3\x21\x78\x77\x1b\x75\xf9\xbb\x9b\x08\x3d\x28\xdd\x85\x42\xc0\x66\x1a\x98\xa7\x53\xa1\x0f\x85\x3b\x51\x36\xf8\x56\x83\xb6\xbb\x17\x78\x51\xb8\x1b\x65\x43\x6f\x34\x68\x4f\x47\x03\x3f\x4a\x73\xa4\x6c\xa0\x95\x06\xe4\xe9\x72\xe0\x49\xe1\xae\x94\x0d\xbd\xd0\xa0\xed\xce\x07\xbe\x14\xee\x4c\x21\x7d\xa0\x77\x81\xbf\x7e\xbd\xbf\xf8\xdc\x69\x40\x0d\xee\x94\xe6\x4f\x21\x50\x33\x08\xe5\x55\x95\xc1\xa1\x42\x3d\x2a\x1b\x7a\x0b\x81\x31\x45\x51\x2e\x15\xea\x53\xd9\xc0\x1b\x08\xec\x55\x13\xe5\x54\x41\xaf\xca\x86\x59\x41\x18\xaf\x92\x28\xb7\x0a\xf5\xab\x6c\xe0\x05\x04\xc6\x54\x44\x39\x56\xa8\x67\x85\x88\x5e\x93\xbc\xbf\x72\xad\x97\x10\xfd\xd0\x7d\x2b\xcc\xb9\x42\xc1\x67\x08\xb8\x47\x63\x74\xef\xca\xe7\x5e\x61\x68\x5b\x04\xcb\xd6\x21\xcd\xbf\xf2\x39\x58\x18\xd6\x06\xc1\xf2\x68\x95\xe6\x61\x21\x2e\x16\x06\xbc\x42\x80\x3d\x7a\xa6\xf9\x58\x3e\x27\x0b\xc3\x5a\x20\x58\xb6\xe6\x69\x5e\x96\xcf\xcd\x42\xfb\x12\xeb\xca\x31\xbe\xb0\xfe\x4f\xae\x0a\x1f\xdf\x23\x36\xf9\xe6\xe0\xa4\xd7\xd9\x62\x95\x7b\x9d\x2d\xc6\x6a\x90\xb3\xc5\x1a\x18\xe4\x6c\x0d\x6c\xe1\xce\x56\xdf\x82\x20\x67\xab\x6f\x75\x90\xb3\xd5\x4b\xca\xe7\x6c\xf5\x42\x0d\x72\xb6\xfa\x8e\x08\x72\xb6\xfa\xfe\xf3\x39\x5b\x7d\x57\x07\x39\x5b\xbd\x58\x43\x9c\xad\x73\x16\xe4\x6c\x29\xb0\x30\x67\x4b\x81\x87\x39\x5b\x12\xdc\xeb\x6c\x49\xa0\x30\x67\x4b\x42\x87\x39\x5b\x12\xda\xeb\x6c\x49\xa0\x30\x67\x4b\x42\x87\x39\x5b\x12\xda\xeb\x6c\x49\xa0\x30\x67\x4b\xf5\x41\x88\xb3\x25\x81\xfd\xce\x16\x83\x1a\x75\xb6\x14\x54\x90\xb3\xa5\xa0\x83\x9c\x2d\x09\xed\x73\xb6\x24\x4c\x90\xb3\x25\x81\x83\x9c\x2d\x09\xec\x73\xb6\x24\x4c\x90\xb3\x25\x81\x83\x9c\x2d\x09\xec\x73\xb6\x24\x4c\x90\xb3\xa5\x44\x1f\xe0\x6c\x49\x58\xaf\xb3\x75\xce\xae\x72\xb6\x00\xf8\x35\xce\x16\x40\xbb\xc6\xd9\x1a\xd0\x02\x9c\xad\x01\xf8\x1a\x67\x6b\xc0\xba\xc6\xd9\x1a\xb0\x02\x9c\xad\x01\xf8\x1a\x67\x6b\xc0\xba\xc6\xd9\x1a\xb0\x02\x9c\xad\x01\xf8\x1a\x67\x0b\xf4\x65\xb8\xb3\x35\x20\xdd\xe2\x6c\x19\xbb\xec\xf7\xd8\x94\x7e\xf3\xae\xb4\xd7\xdb\x62\x95\x7b\xbd\x2d\xc6\x6a\x90\xb7\xc5\x1a\x18\xe4\x6d\x0d\x6c\xe1\xde\x56\xdf\x82\x20\x6f\xab\x6f\x75\x90\xb7\xd5\x4b\xca\xe7\x6d\xf5\x42\x0d\xf2\xb6\xfa\x8e\x08\xf2\xb6\xfa\xfe\xf3\x79\x5b\x7d\x57\x07\x79\x5b\xbd\x58\x43\xbc\xad\xe2\x18\xe4\x6d\x29\xb0\x30\x6f\x4b\x81\x87\x79\x5b\x12\xdc\xeb\x6d\x49\xa0\x30\x6f\x4b\x42\x87\x79\x5b\x12\xda\xeb\x6d\x49\xa0\x30\x6f\x4b\x42\x87\x79\x5b\x12\xda\xeb\x6d\x49\xa0\x30\x6f\x4b\xf5\x41\x88\xb7\x25\x81\xfd\xde\x16\x83\x1a\xf5\xb6\x14\x54\x90\xb7\xa5\xa0\x83\xbc\x2d\x09\xed\xf3\xb6\x24\x4c\x90\xb7\x25\x81\x83\xbc\x2d\x09\xec\xf3\xb6\x24\x4c\x90\xb7\x25\x81\x83\xbc\x2d\x09\xec\xf3\xb6\x24\x4c\x90\xb7\xa5\x44\x1f\xe0\x6d\x49\x58\xaf\xb7\x55\x1c\xaf\xf2\xb6\x00\xf8\x35\xde\x16\x40\xbb\xc6\xdb\x1a\xd0\x02\xbc\xad\x01\xf8\x1a\x6f\x6b\xc0\xba\xc6\xdb\x1a\xb0\x02\xbc\xad\x01\xf8\x1a\x6f\x6b\xc0\xba\xc6\xdb\x1a\xb0\x02\xbc\xad\x01\xf8\x1a\x6f\x0b\xf4\x65\xb8\xb7\x35\x20\x8d\x79\x5b\x9d\x3a\x01\xea\x3d\x4d\x2a\x4f\x64\x13\x96\xa0\x8e\xc1\xcb\xf3\x5a\xec\x6e\xd3\x83\x7e\x86\x4b\x9e\x2d\x17\x9f\xc1\x35\x0c\xf3\xee\x02\x38\x49\xd5\x9d\x18\x5d\xe7\xdd\x60\xc5\xa9\x91\xe1\x04\x49\x7a\xe2\xbe\x65\xc5\xc9\x3c\x75\xfb\x2a\x7b\x7d\xea\x9a\xa7\x2e\x9b\x44\xd6\xb7\xd3\xf0\xed\x50\x55\x9d\x09\xa7\xbe\x9d\x78\x9a\x18\xfe\xf5\x44\x49\x66\x42\xaa\x6f\x27\x28\x32\x25\x17\xcf\x41\x66\x33\xc9\x4d\x57\xd5\x9e\x4c\x23\x59\x96\x19\xed\x33\x6a\x36\xc9\x71\xc9\x20\x97\x9b\xe6\x1e\xa2\xa2\xf7\x3f\x49\xe2\xbb\x43\xde\xc8\x1b\x40\xb0\xd9\x7e\x38\x28\xb4\xb4\x2a\x7a\x95\xab\xc7\x49\xfa\x01\xad\x8e\xd0\x8b\x9d\x64\xc7\x61\x4f\xe2\x1a\x09\x14\x7c\x82\xe8\xd2\xa7\x4e\x65\xac\x82\xa0\x1e\x71\x46\x53\xdf\xd8\x03\x89\xa6\x38\x5c\x9c\x56\x65\x46\xcb\x96\x66\x98\xf2\xa2\xa5\x40\x2a\xb0\xdc\x56\x69\xb4\xd4\x81\x6d\xab\x39\x5a\x6a\x28\xfc\xca\x18\x80\x31\x17\x92\x96\xfb\xc8\xab\xd1\x0a\x01\x6d\x3d\x52\x08\xd9\x1f\x8a\x91\xb6\x23\x85\x38\x2e\xd2\x72\xa4\xf0\x74\x43\x8b\xae\xa7\x2c\xc6\xab\xb4\x7b\x73\x53\xbc\x6d\xd7\xe4\x35\x90\xc7\xae\xec\x4e\x71\x75\x88\xbb\xd7\x9a\x7e\xa8\xb2\xec\xa3\x53\xed\xb6\xfd\x3f\x9d\x18\xbb\xac\x3c\x90\xf2\x5f\x90\x66\x97\x25\xb4\xc9\x25\xad\x8a\x1f\xd3\x82\xb4\xed\xef\x7f\xe8\xe7\x26\x7e\xc7\x12\xcb\x1e\xa4\xae\x88\x48\xb5\x2a\x2e\x67\x76\x99\x54\x2c\xb2\xc1\xad\x12\x4e\xb9\xcb\x34\xc2\x93\x48\x7c\x3e\xdd\x56\x1f\xe5\x77\x43\xec\xda\x8c\x09\x62\xca\xf3\x23\x61\x73\x87\x2a\x3a\x21\xd3\x4a\x26\x4a\xa1\xb1\x1a\xf4\x75\xaa\xb2\x2e\xe9\xd3\x0c\x56\x9b\x59\xa4\xd9\xbf\x41\xc7\x5d\x24\xb1\xda\x84\x9a\x81\xda\xec\xb9\x0d\x6b\xdd\xa0\xbb\x2e\x92\x43\x6d\xd2\x96\x8e\xa8\x0d\xaa\x76\x82\xc4\x4e\x7c\x1d\x46\x8a\x17\x0c\x8e\x64\x4c\x8d\x9f\x0c\xa6\x0d\xa0\xa1\x55\x1c\xdc\x49\x6d\x68\xe3\xc8\xd5\xfe\x87\xfe\x9f\x43\xad\x44\x26\x05\x54\xaf\x54\x19\xae\x58\xa2\xd8\xa1\x59\xb2\xd4\xd2\x1f\xac\x46\xab\xcc\xa5\x5c\x2e\xaa\x68\x8d\x52\x83\x40\x8d\x88\x7e\x61\xad\x04\x0a\xe6\xa2\x0a\x6a\x74\xab\x98\x96\xb9\x02\xd7\x1d\x2d\x95\x85\x47\xc7\x0c\xb8\x71\x25\x33\x18\x47\xb4\x4c\x23\xe9\x55\xb3\xa0\x7c\x1b\x59\x42\xb7\xe9\xda\xa1\x67\x79\x79\xa8\x50\x25\xe3\x05\xb8\x86\xf5\x65\x0e\xf5\x62\x45\x96\xfe\x58\xb5\xe8\x05\x2e\xad\x42\x89\xd9\xb5\x48\x8d\x91\xb5\x20\xca\x64\xb5\x06\x68\x12\x4a\x4c\xd6\xe2\xd1\x21\x98\x99\x04\xd7\x8d\x21\x55\x89\x47\x81\x20\xd0\xb8\xf6\x40\x66\x11\xd5\x19\x88\x79\xf5\x66\x3c\x87\x4a\xba\xa4\x8b\xc3\xc2\xa1\x34\x22\x3d\x0a\xaa\x37\xaa\x0c\x57\x1d\x51\xec\xd0\x1e\x59\x6a\xe9\x09\x56\xa3\x55\xe6\x52\x23\x17\x55\xb4\x46\xa9\x31\xa0\x46\x44\x9f\xb0\x56\x02\x95\x72\x51\x05\x35\x7a\xe6\x3f\x3d\x59\x16\xa6\x33\x5a\x7e\x1a\x8f\x6e\x19\x70\xe3\xea\x65\x30\x8e\x68\x98\x46\xd2\xab\x64\x61\x49\x74\xc8\x61\x9e\xa6\x0e\x3d\xe3\x09\x72\x50\x35\x93\x45\xb8\x96\xf1\x52\x87\x92\x89\x42\x4b\x8f\x90\xda\xcc\x22\x97\x86\x39\x48\x62\xb5\x49\x0d\x1a\x6a\x43\xd4\x0b\x69\x1d\xd0\x2e\x07\xc9\xa1\x36\x8f\x6e\xc1\x24\x44\xb8\xce\xc0\xac\x44\x1e\xd5\xd2\xc1\xc6\x35\x4b\x67\x1a\x51\x2c\x48\xd0\xab\x57\x41\x69\x93\xf6\x69\x6a\xa8\x15\xc8\xe8\xcb\xb0\xe0\x6d\xc4\x69\x32\xfb\x9d\x76\xc9\xf9\x05\xbb\x78\xcc\xdf\x6e\x8d\x48\x99\x45\x1f\x86\x40\xd3\x66\xbd\x51\xdb\x91\x68\x45\x66\x8c\xca\xca\xa3\xb4\x32\x72\xe7\xc4\xaf\x5a\xf6\x9c\xf8\xdc\xaa\xb4\x38\x32\x29\x43\xff\xad\x67\xf0\x94\xb3\x18\x1b\xbf\x90\xbd\x27\x2c\xa3\xb2\x73\xc1\xc9\x63\x82\x26\x8f\x4f\x20\xf6\x80\x64\x6d\xf1\x22\xa1\x0b\x70\x1f\xd4\x89\x6f\xb7\x3a\x01\x91\x35\xb9\x0f\x6a\x8c\x1c\xb2\x98\xf6\x41\x9d\x7a\x6a\xbc\xcb\xdc\xf9\x86\x1c\x64\xf4\x28\x06\xcc\xac\x1b\x86\x06\x45\x09\xc3\x4e\xde\x16\xa2\xc1\x8e\x5b\xb0\x07\xb9\xbf\x09\xfb\xa6\xba\x87\x4e\x7a\x13\xb6\x56\x37\xec\x04\x3d\xd2\x7d\x65\x4f\x80\x8c\x47\xd7\x77\xc4\xf5\xc8\xa0\x1f\xde\x80\x7c\x4b\xcd\xa0\x17\xde\x80\x0c\x6b\xd6\xfa\x40\xec\x91\x5e\xdf\x09\x80\xa0\x98\x2c\x6f\x45\xf6\x1b\x0b\x5b\x8e\xb7\xd5\x8c\x21\x9f\x34\x51\x18\xc6\x95\xcd\x30\x87\x9c\x16\x59\x4b\x3b\x35\x33\x89\x39\x23\x71\x67\xfc\x4e\xb0\x04\xde\x05\x3d\xd2\x92\x4b\xde\x4e\xb2\x62\xcc\x43\x18\x59\x5f\x5a\xda\xf9\x0c\xd9\xa9\xb0\xb3\x95\xe8\x39\x6e\xf4\xac\xe8\x58\xea\xc1\x55\xff\x4f\xb2\x4f\xf6\xf4\xfa\xb4\xf6\x06\xeb\x2b\x24\x7b\xee\x90\x13\x8f\x3d\xd1\xf0\x63\xf7\x5a\xd3\x1f\x5a\x4a\x9a\xf4\xc4\x63\x82\xbf\xee\x8b\x18\xa0\x52\xf6\xee\xf4\xbe\x7a\xf9\x49\xbc\x16\xc1\xbf\x36\x24\xcb\x2b\xce\x89\x4a\xde\xc8\xf2\xf7\xc0\xbe\x51\x3b\x3d\x7f\xd9\x5a\xfd\xc0\xb3\x34\xd9\xd5\x1d\x72\x99\xc9\x4e\xd7\x07\x1b\xb2\xe9\xdd\x2a\x0c\xf4\x11\x4d\x65\xc0\xdf\xb8\xf8\xf1\x7c\x29\xba\xbc\x66\xa9\xf3\xc4\x97\x5e\x59\x38\x19\xe4\xa9\x03\x93\x33\xf9\x2c\x05\x26\x20\xa4\x8c\x8b\x89\x17\x08\x27\xf7\x57\x7f\x85\xa2\xba\x74\xf5\xa5\x73\xc8\x45\xdb\xf8\xdc\xd8\x59\x8a\xc2\x9f\x19\x59\xad\x54\xc8\xf3\x50\x35\xe7\x38\xad\xca\xae\xa9\x5c\x99\xef\x1c\x0f\x3b\x2c\x96\xc6\x1b\x01\xeb\xfa\x85\xa5\xa8\x7e\x13\x5f\xae\x5c\x48\x56\x96\xab\xfc\x4c\x8e\x14\x66\x81\x0a\x4f\x91\x34\x96\xff\xaa\xa7\xd1\xff\x7f\x23\x9f\x55\xb2\x71\x67\xc0\x1a\x41\xc1\xde\xa1\x10\x7c\xb1\x16\xc2\x37\x24\xa2\xe9\x6c\xd5\x4e\x22\x9b\xc1\xde\xac\x9b\x70\x8f\xf6\xcb\x15\x23\x74\x07\x7a\xfa\xc3\x15\xef\xde\x49\x7a\x6f\x26\xc6\x0a\x31\x05\x03\xaf\x38\x40\xc2\x2c\xaf\x31\x39\xd0\xad\x36\x96\x9c\x89\xbf\x02\x64\x3e\x61\xa9\xbc\x58\xca\xf5\x77\xef\x58\xf9\x2c\x99\x4f\xa2\xd9\x66\x35\x89\xe6\x8b\xc5\x24\x9a\xae\x6f\xe9\xca\x10\xb2\x68\xbb\x77\xcc\xa0\xd7\x05\x49\xe9\xa9\x2a\x32\x23\x03\xf3\x76\xcb\x5b\x5e\x93\x34\xef\x5e\x77\xd1\x0c\xa5\xd1\x2f\xc3\x98\x79\xf2\xd1\x71\xd4\x2e\xa4\x78\x13\xfa\x8f\x59\xce\x9e\xe0\xc8\x7e\x9a\x44\x7a\x41\x43\x49\x56\x95\xc5\xeb\x4f\x93\x48\xfa\x14\x03\xb0\x0e\xeb\x8e\x12\x88\x14\x91\xfe\xc6\x43\x1e\xc6\xaa\xe2\x6d\x12\xa9\x54\xcb\xaa\x8b\x49\x51\x54\x5f\xa9\xdc\x04\x95\xef\x24\xd9\x38\xfe\x29\x04\x9b\xc0\x49\x5d\x53\xd2\x90\x32\xd5\xd3\xfb\x22\x4b\x78\x89\xd1\xbb\x5b\x19\x7d\xce\x53\x1a\xd7\xf9\x0b\x2d\x62\xf6\xf8\xd1\x2e\xe1\x6b\x7a\x50\x5d\x46\x3a\xaa\x4f\xdb\x5d\x7e\x36\xbe\xf4\x30\xfd\xd7\xb8\xa8\x52\x52\xe8\x65\xe7\xaa\xec\x4e\x3f\xa9\x35\xa6\x66\x7c\x17\x4b\x99\x16\xec\xdd\x94\xab\x04\x3b\xe3\x10\xb7\x67\x93\x7a\xdf\xe5\x6e\x08\xce\x11\x33\x1d\x7e\x32\x1a\x93\x1e\x58\xce\x34\xa3\x68\x32\x22\xb0\xda\xb3\x2d\x13\xbc\xc8\xa8\x77\x00\x32\xa8\xf3\x3a\x55\x71\x84\x88\x2b\xc1\xc5\x55\x1c\xc7\xc4\xa5\x43\x38\xc4\x65\x93\x71\x8b\x4b\x87\x1d\x17\x57\x71\x74\x8a\xcb\x28\xc2\xc5\x55\x1c\xbd\xe2\x2a\x8e\x88\xb8\x96\x6b\x3d\xe9\x1c\x1b\x67\x8c\x7d\xe0\x72\x6a\x01\x29\x95\x84\x42\x78\x63\x93\x68\xca\x9c\x2f\x63\x03\x1d\xa6\xf7\xc2\x9e\xbf\xba\xea\xa5\x12\x59\x57\xc4\x96\x01\xaa\xc6\x61\x51\x00\x43\x76\x72\x81\xa2\xa7\x0a\x73\xbc\xfc\x92\x58\x0b\x02\xf1\xee\x8c\xe3\x01\x21\xc5\x09\xee\xb8\xab\x72\x99\x7f\x1c\x05\xeb\x75\x93\xb7\xc0\xf2\x60\x65\xdb\x10\x7c\xb0\x12\xc0\x1f\x87\x82\x42\x5d\xaa\xc5\x80\x9e\xb7\x6f\x8e\x48\xf5\x93\xd5\x97\x9f\x40\x97\x42\xaa\x31\xd2\xff\x82\x53\x93\xf1\x00\x6d\x70\xe5\x4e\xbf\xad\xc3\xf0\x07\xdf\x02\xba\x52\x70\xfc\x69\xa4\x45\x9f\xec\xf6\xb9\xf2\xb6\xcb\x63\xba\xe0\xbd\x3a\x6b\x16\xc4\xf5\xc7\x0f\x28\x54\x44\x9f\x7b\x14\xf6\x54\xe2\xe0\x8b\x26\x38\x2b\x5b\x34\x07\x5c\x9d\x38\x2f\x05\xdc\xf8\xa7\x6b\x53\x84\x80\x25\x4d\x7a\xe0\x3b\xe6\x20\x98\x1d\xd1\xf7\x38\x02\x66\xf5\x47\x00\x63\xaa\x66\xdd\x94\x58\x9f\x7d\x6c\x09\x18\x1f\x57\xc0\x34\x79\x98\x82\x4e\x4d\xcc\x4f\x1c\x59\xd6\xcc\x58\xb8\x69\xeb\x49\xf3\x20\xed\x06\x1f\x31\x9e\xea\xc0\xf4\xe2\x29\x16\x13\xad\x91\x92\x31\x41\x92\x8e\xcb\xaa\x34\x3c\x38\x35\x3f\x1a\xe7\xfd\xd0\x0c\xbe\x73\x74\x0d\xba\xc2\xf3\x23\x6b\x51\x07\x7f\xc5\x88\xa3\x80\x46\x2c\x80\x8f\xa2\x1c\x50\x94\x30\xcc\xf7\x35\xcc\x9c\x3d\x94\xdb\x61\xfd\x2d\xa4\x70\x2d\x2f\xc1\x82\xf1\x10\x06\xb2\xf2\x40\x89\xa5\xc5\x95\x02\x84\x83\xc3\xe4\x5d\x1b\x2c\xf3\xb7\xc9\x56\x57\x5f\xe1\x30\x41\x57\xe9\xd1\x7a\x72\x41\x7b\x92\x6b\x78\x3d\x0c\xa1\x2e\x8e\xe0\x23\xfd\xb7\xc6\xb5\xd8\x51\x3f\xe2\xbf\xf9\xb4\xb8\x1f\xdb\x86\x16\x1b\x84\x1d\x9d\x50\x1c\x3d\x9a\xf3\x1b\x0a\xe3\x5a\x96\x82\xe5\xe3\x21\x8c\x2b\xb3\x09\x15\xa6\xcc\x26\x16\xa6\xcc\x92\x77\x4d\x99\x1f\xee\x22\x62\xc9\xd1\x89\xb4\xf1\x81\xd2\xac\x5f\xd5\x3b\xbc\x33\x14\xd4\x16\xb8\x31\x0f\x2c\xe7\x53\xe0\x16\x6a\x2d\x75\xd4\x07\x9d\xd6\xc1\x79\x82\xd3\xca\xcf\x71\x5e\x66\xf4\x65\x17\xcd\xf1\xf5\x83\xbc\xfe\xb9\xd4\x1f\x42\x5d\x60\xd1\x4b\xf9\xd1\x7e\xfe\x8d\x49\x97\x3b\x85\x31\x7d\xa6\x65\xd7\xea\x07\x7a\xe5\x68\xf9\xe4\x69\x95\xbc\xb1\xba\xd6\x39\x19\x53\x46\x35\x9f\x04\xd0\x96\x96\x2e\xd4\x6a\xb3\xfe\x93\x2f\x74\x41\xdf\x1e\xfd\x3e\x78\xbb\x7a\xb1\x60\x48\xf9\x3a\x7a\xf1\x89\x16\x35\xf7\xdc\x4d\x44\xe6\xff\xa0\x1f\x81\x3b\x07\x4b\xed\xd5\x1d\x56\x28\xfd\x3c\x94\x1f\xe8\x74\x19\xf8\x9a\x93\x08\xbc\x32\xec\xd1\x39\x9d\x67\x4b\xef\x8d\x28\x28\x47\xfd\x6d\xc3\xd3\xa3\x8c\xba\x83\xb6\xfc\xc1\xbc\x37\x87\x69\xd7\xf5\x4b\xf4\xdd\x7a\xb3\x9f\xad\x1f\x6e\x8e\xc9\x02\x1a\x68\x83\x60\x10\x85\x64\x99\xb8\x4a\x66\xcb\xdd\x79\x7e\xf7\xd1\xd5\x5b\xa3\xf2\xd3\x07\xa0\x1b\x59\x3e\x1c\x67\x0e\x2f\xeb\xbb\x3e\xbc\x86\x62\x74\x78\xa9\x62\x6b\x78\xa9\x12\x38\xbc\xf4\x8f\xe6\xf0\x12\xa5\xf8\xf0\x32\x0b\xf1\xe1\x25\xa1\xec\xe1\xa5\x95\xb8\x87\x97\xf6\x5e\xa2\xce\xf3\xd8\xf0\xe2\xa8\x7f\xbf\xe1\x85\x32\xea\xdb\x13\x59\xcd\xee\x35\xbc\xd2\x84\xcc\xd6\xfb\xb7\x0d\x2f\x4e\x03\x6d\x90\x7f\x78\x0d\x72\x77\x9e\x40\x45\x86\x57\x60\x47\xe3\xc3\xcb\x46\xa6\x4d\x53\x35\xd6\xe0\x32\xbe\xea\x43\x4b\x16\xa2\x03\x4b\x14\x5a\xc3\x4a\x7c\x87\x83\x0a\x7e\x32\x87\x14\x2b\xc3\x07\x94\x5e\xa4\x0f\x27\x08\x01\x87\x92\x4e\x76\x64\x28\x69\xcf\x84\x42\x4e\xc7\x06\x12\x47\xfc\xfb\x0d\x24\x84\x4d\xf7\x30\xe2\xef\x9b\xde\x69\x18\xd1\x87\xe5\xc3\xe2\x8d\xc3\x88\xd1\x40\x9a\xe3\x1f\x44\x83\xcc\x9d\x47\x6d\x91\x41\x14\xd4\xc5\xf8\x10\xb2\x51\x15\x18\x57\xa5\xff\xed\x21\xc2\x2f\xa1\xae\x74\x07\x52\xc7\x97\x8f\xfc\x8f\xd3\x51\x31\xa0\x61\xb0\x39\x8e\x2a\xc0\xf0\xe9\xca\xb9\x07\x00\x8f\x1c\x6c\x16\xfd\xbf\xc0\xe4\xd6\x8c\x4f\x31\x9c\xcc\x7d\x0d\x77\x10\x1a\x8d\x37\x3b\x82\xcb\x72\x9f\xc9\xae\x09\x0e\x47\x4f\x5d\xc2\xc1\x97\x4f\xf3\xdc\x5a\x0d\x5c\x51\xe2\xb5\xa1\x24\x80\x0a\xe3\xa8\xec\x04\xdb\xb5\x8c\x41\xaa\xc6\x9a\xda\x03\x68\x0d\x27\xbe\xf5\x16\x86\xb0\xef\x4a\xed\x3c\x35\xcc\xa7\xe1\xa2\xf0\x84\x74\x14\x92\x84\x49\x43\xd7\xe6\x16\xfc\x58\xf4\xb5\xd2\x02\x33\x9c\xf6\x7d\xd8\x7f\x19\x57\xd5\x61\x09\x7d\x37\x76\xd4\xc4\x85\x30\x05\x5a\x6f\x45\x7f\x7d\x24\x1d\x3b\x66\x48\x0d\xd6\x06\x84\xda\x19\xc7\x77\x94\xd0\xc4\x15\x06\x1b\xee\x98\x86\x6e\xc3\x94\x11\x33\xf6\x44\xc1\x4b\xb2\x56\xa7\x61\x65\xd0\x75\xb0\x80\xa4\xbf\x81\x17\x60\x6f\x17\xc3\xb0\xff\xd8\x73\xc1\xc9\x4d\x8c\x83\x1d\x3f\xb8\x99\xba\x31\x42\x3b\x10\x05\xdf\x2c\x0e\x7e\x38\x2c\xc8\x80\x6b\xec\xdb\xe3\x0f\x93\x0f\x3e\x0a\xac\xb7\x50\xbd\x5d\x1c\xaa\x2e\xe0\x79\xaa\x5b\x5b\x65\x84\x0a\xc7\x1a\x39\x5b\x4e\x17\x8b\xd1\x17\xe7\x42\x6b\x6c\xcf\xe3\x35\x1a\x47\x04\xa4\xb5\x1d\xdb\xc7\xd5\xcf\x18\x3a\xb7\x71\xf5\x73\x87\xd8\xce\xae\xe7\x2c\x22\x1e\xd3\x43\xee\x68\xf8\x77\x88\xe3\x73\x1b\x77\xd5\x25\x3d\xc5\x24\xe5\xe6\xe5\x4c\xca\xbc\xbe\xf4\x26\xa6\x2a\x79\x98\xd2\x57\x6a\xec\x30\x43\xf7\xf5\xd2\xd2\x26\xe6\xa1\xe7\xe1\xfc\x23\x3b\x60\xe6\x28\x69\xf1\x02\xf4\xe3\x35\x27\x2c\xfd\xaf\x3e\x0e\x6f\x51\xf6\xfd\x2b\x6e\xa9\x4f\xc5\x39\x5b\xf0\x69\x07\x3f\x81\xdf\x3b\x0d\xa3\xd7\xba\xe1\x23\xc4\x01\x9e\xff\xaf\x7e\x3e\xd7\xe2\x11\xfe\x1e\x2e\x89\x19\xa7\xd3\x99\x4a\x65\x34\xad\xd8\x61\xaf\x52\x8f\x08\x0f\x82\xd0\x9a\x6d\x5e\x36\x33\x3a\x23\xfc\x94\xe4\xa2\x7e\x61\xcd\x36\x16\x25\x33\xcf\x73\xae\x1e\x14\xc8\x35\xd8\x89\xdf\x77\xe5\xd8\x11\x3d\x39\xc6\xb1\xe8\xf8\x23\xbe\xa9\xcd\x46\x6f\x5e\x74\xbd\xd6\x91\xa2\x3e\x91\x0f\xe2\x94\x60\xf4\x43\xb4\xd6\x0f\xd6\x86\x3c\x0c\xab\x1d\x33\x9c\xae\x57\xa0\x2d\x71\x46\x0f\xe4\x52\x74\x58\xef\x79\x4e\x23\xeb\x6b\x2d\x70\x09\x10\x90\xd4\x3a\x57\x7d\x04\x7a\x23\xbf\xed\x40\x92\x0e\xf8\x19\x03\xe5\x17\x17\xa3\x69\x55\xd3\xf2\x69\x9a\x35\x55\x9d\x55\x5f\xfb\xf9\xfb\x78\x2c\x28\x84\x54\x8f\x51\x8f\x35\x89\xae\xfb\x7f\xd8\x0a\x32\xeb\xff\x85\x36\x6c\xa7\x3e\x86\xb2\x86\xeb\x38\x56\x9f\xae\x6f\xd6\x67\x5c\xd0\xaa\x54\x33\x23\x56\xf1\xce\x8b\x8c\xf5\xc1\x50\x38\xdc\x22\x05\xc5\xda\xa9\x59\xf4\x3b\xca\x2f\x28\x46\x19\x1e\xca\x51\x8e\x41\xf1\x18\xba\x50\x21\xc7\x50\x95\x08\xa3\x00\x20\xb5\xcc\x18\xa4\x10\xe2\x08\xd8\x2e\x98\xe0\x2e\x90\x20\x6b\xa9\xe7\x9a\xf2\x15\x83\x39\x9a\xee\x49\x76\xa4\x9a\x99\xf0\x3e\xc0\x0d\x69\xd4\x4d\x7e\x26\xcd\x6b\x30\xf2\x86\xec\x37\x08\x67\x73\xba\xce\xc8\x12\x21\xac\x2b\x94\xfc\x08\x55\x57\x7c\x33\x2d\x8d\xfc\x8c\x81\x8e\x5b\x1a\x01\x69\x58\x1a\x77\xc3\xe6\x0f\xeb\x64\x9b\x60\x0d\x4b\x96\xd9\x26\xb8\x61\x21\x96\x46\x67\x6d\xdc\xd2\xc8\xfa\x0c\x4b\x63\x7e\xc6\x05\xed\xb0\x34\x66\xf1\xce\x8b\x8c\xf5\x81\xcb\xd2\x88\x62\xcb\xd2\x58\xdf\x51\x7e\x9d\x96\xc6\x2a\x47\x39\x76\x5a\x1a\xbb\x7c\xc4\xd2\x08\x84\x51\x80\x00\x4b\x63\xe8\xfc\x08\x58\x80\xa5\x31\x46\xc6\x18\xd8\x88\xa5\xb9\x7e\x48\x63\xf6\x06\x50\xf1\x66\xef\xeb\xc9\xc8\x0d\xc9\xb0\x91\xb9\x4a\xf7\x0f\xab\x14\xe1\x6f\x99\x12\xba\x4c\x11\xc2\xba\x66\xc9\x8f\x50\x87\x65\xd6\x20\xc3\xe4\xc8\xcf\x18\xe8\xb8\xc9\xd1\x73\x2e\x8d\x37\x6c\xb9\xdc\x66\xcb\x25\xb6\x85\xbb\x7d\x58\x2e\xb6\xa1\x0d\x0b\x31\x39\xce\x74\x50\x0e\x93\x23\xeb\x33\x4c\x8e\xf9\x19\x17\xb4\xc3\xe4\x98\xc5\x3b\x2f\x32\xd6\x07\x2e\x93\x23\x8a\x2d\x93\x63\x7d\x47\xf9\x75\x9a\x1c\xab\x1c\xe5\xd8\x69\x72\xec\xf2\x11\x93\xa3\xd2\x62\x8d\x00\x04\x98\x1c\x43\xe7\x47\xc0\x02\x4c\x8e\x31\x32\xc6\xc0\x46\x4c\xce\xf5\x43\x1a\x33\x39\x80\xca\xa8\xc9\xc9\xcb\x43\x15\x6a\x6f\xf6\x69\x82\xee\x5a\x2d\xd7\xfb\x87\x8c\x98\x54\x75\x9d\x62\x5f\xa0\xea\xb2\x3c\x53\x16\x88\xa1\x2a\x20\x67\x95\x6f\x14\x5f\xd1\x88\xc5\x6c\x9f\x64\x2b\xcc\xa8\xaf\xb7\x64\x9f\x8e\x37\x22\xc4\xaa\x28\x7e\xc6\x0d\x0a\xab\xc4\xb0\x26\xda\x37\x44\x8c\x0e\x3b\xa2\x95\xd9\xa2\xc5\x2d\x88\x5e\xa2\x9b\x8f\xbe\xcc\xb2\x1d\xfa\x47\x9b\x3b\xa7\xd5\xd0\x0b\x6d\xfe\x2c\x7b\x81\x16\x29\x0e\x5d\x23\x8d\x67\x41\xf3\x95\x06\x98\x09\xa8\xad\x3e\x98\x00\x03\x01\xb4\xda\x4f\x6a\xcc\x34\x5c\x37\xfa\x50\xbb\x30\x90\x18\xb5\x0b\xf2\xf0\x46\xd8\xa8\x3a\x24\x24\x5b\x62\xcc\x51\x4a\xe6\x8b\x35\x42\x58\x57\x1c\xf9\x11\x76\xbc\xcc\x11\x66\xb8\x22\xf2\x33\x06\x3a\x6e\x29\xf4\x0c\x6b\xe3\x0d\xa3\xe9\x76\x33\xc3\x16\x9c\xd9\xea\x61\x35\x9b\x87\x36\x2c\xc4\x68\x38\x93\xbf\x39\x2c\x87\xac\xcf\x30\x1e\xe6\x67\x5c\xd0\x0e\x13\x62\x16\xef\xbc\xc8\x58\x1f\xb8\x6c\x89\x28\xb6\xcc\x89\xf5\x1d\xe5\xd7\x69\x54\xac\x72\x94\x63\xa7\x2b\x62\x97\x8f\xb8\x22\x2a\x09\xde\x08\x40\x80\x8d\x31\x74\x7e\x04\x2c\xc0\xd2\x18\x23\x63\x0c\x6c\x2c\xce\x72\xf5\x90\x46\xa3\x2d\x03\x95\x51\x93\xc3\x93\xb7\x05\x5a\x9c\x6c\xbb\x5a\x2c\xd1\x81\xb9\x5c\x1c\x16\xc4\xa6\x6b\xc4\xef\xf8\x37\x2d\x50\xc8\x73\xc7\x21\x60\x66\x70\x0e\x66\xa3\xf3\x46\x4e\xaf\x69\x50\xba\x5d\x24\x73\xcc\xf5\x23\xe9\x7c\x3b\x5f\x85\x35\x28\x28\x9e\xeb\xc8\x03\xe8\x0a\xe7\xf2\xca\xcc\x68\xae\xfe\x15\x15\xae\x2b\x96\xab\x97\x62\x02\x77\x44\x72\x8d\x32\x23\x90\xcb\x4a\xed\x38\xae\xf1\x19\xe3\xd4\x1d\xc5\x35\x8a\x31\x5e\x1d\x6e\x8b\x55\x38\xea\xb8\xc8\x2c\x88\xfe\xf2\x90\x00\xae\xa6\xdb\x7e\xa8\x90\xf0\x2d\x1c\x03\x63\xe4\x46\x8c\xca\xd5\xa3\x16\xb3\x29\x80\xc8\xa8\x4d\x29\xf2\x92\x6f\xd3\xa3\x37\xbc\x5d\x81\x1e\xb9\x27\x9a\x98\xa4\x44\xe7\xf6\x3f\x75\x45\xea\xbf\xec\xac\x2f\x40\x1b\x3d\x02\x56\x3c\x7a\x9f\x56\xb9\x76\xfb\xcc\xc3\xba\xcd\xa8\xa6\xba\xec\x03\x48\xa1\xa9\xf5\x94\xfd\xd8\x4b\x10\x11\xb5\xca\x5a\xac\xe6\x9b\x14\xdd\x65\xbd\x94\x19\x6d\x8a\xdc\xda\xd7\x1e\xaf\xd8\x31\x04\x8d\xa2\x91\x99\x1d\xb4\x60\xa4\xaf\x90\x66\xc1\x17\x6b\x3c\x3b\xc7\xea\x90\xc7\x53\xff\x97\x64\xf3\x08\xcf\xf9\xfc\x2a\xf7\xe8\x40\xdd\xed\x19\xd6\xad\xdf\xeb\xbd\xef\x4d\x54\x50\xe9\x4b\x0b\x2b\x7d\x69\x8d\x06\xf3\xfd\xeb\xbb\xd5\xe9\x3b\x71\x6a\x27\x2b\x1b\x50\x3e\x19\xd8\xc6\xe9\x54\x3b\xc7\xcc\xfe\xd2\x75\x55\xf9\xd3\x80\xa6\xdf\xab\xa7\x2d\xed\x5c\x85\xed\x65\x7f\xce\x61\xa9\xb0\x99\x08\x7f\x07\x92\x71\xfb\xa7\x36\xc3\xb5\x43\x04\x30\xfd\x93\xdc\x6f\x9f\xce\x56\x6d\xd4\x0b\x8e\x67\x7d\x35\x32\x4e\x39\xa0\x46\x40\x20\x3b\xd3\xbc\xd4\x39\x52\x59\x80\xd2\xaa\x28\x48\xdd\x52\x5d\xfc\x70\x18\x48\x08\x49\x03\xcd\x3d\xd7\x35\x6e\x38\x91\x67\xb1\xfa\x2a\x61\xf7\x55\xf6\x1a\x00\xce\x75\xd1\x60\x43\x2e\x71\xf1\x63\x85\x52\xed\x98\xc0\x65\x9e\x5d\x98\x80\xd7\xee\x84\xb8\xcb\xcf\x79\x79\x8c\x0f\x97\x52\x1c\x15\xa2\xa4\xa5\x56\x2f\xb8\xc1\x82\x48\xd9\xd5\x66\x17\x69\x73\xa6\x0b\x24\xcf\x18\x52\xee\x47\xb6\x6b\xa8\x9b\xaa\xa6\x4d\xdf\xdb\x5c\x2c\x93\xe8\x39\x6f\xf3\x7d\x5e\xe4\xdd\xab\x5d\xdf\x18\x74\x20\xa8\xea\x2e\xd2\xd0\xce\x7f\xe8\x0c\xa6\xc5\xd4\x3a\x4e\x7f\x6c\x8d\x5b\x15\xf7\x49\x30\xf8\x2c\xd3\xb2\x7e\x89\x32\xd2\x9e\xf8\xd9\x16\x3d\x5d\xe9\x72\xe4\x5c\x95\x78\x47\x0e\x83\x92\x8d\x92\xde\xf9\x24\x62\x3f\xc5\x21\x4a\xf7\xad\x5c\xc3\x9b\xc7\x4e\x52\x25\x16\xec\x99\x96\x97\xb1\xdb\xb7\x32\x57\xa0\x38\x3e\xfb\x08\xef\xdf\xce\x12\xee\x2c\x69\x83\xf9\x71\x78\xff\xa6\xc7\x79\xd4\x33\x93\xce\xd6\x58\x86\x03\x2d\x43\xe9\x7c\xc8\x60\x89\x9c\x01\x34\xdf\x76\xe3\xf3\x40\xdb\xc9\x14\xd7\xc8\xe9\x37\x63\x81\xa5\x3c\x25\x00\x51\xe4\xf5\x2e\x1a\x32\x66\xbc\x98\x14\xd0\xf2\x91\x3c\x85\xb0\xc4\x3c\x7f\x25\x4f\x6c\x85\xe6\x33\x4c\xd4\x71\x49\x8b\x14\x72\x07\xc7\x0f\x8d\xaa\xc1\x94\xbd\x4c\xca\xf4\x17\x1e\x5d\x4d\x86\xae\x87\x17\xd8\x75\x0d\x9a\x66\xf9\x73\x2e\x53\xd0\xa9\xe9\x18\x9e\xec\xdc\x45\x5b\xd9\xcb\x98\xa9\xc4\x82\x6b\x30\xbf\xab\x5e\xdf\x53\x91\x3f\x11\x7f\x62\x4d\x36\xef\xab\x24\x41\x69\x41\x49\xc3\x1e\xac\x3b\xdd\x70\x8a\xd4\x38\x70\x85\xa6\xf8\x76\x71\xa9\x7c\x4e\xa4\x08\x71\x80\xd7\xfd\x3f\xa7\xb3\xe8\xd2\x6a\xed\xdd\x23\xbd\x22\xf9\xda\x12\xb1\x58\x50\x25\x0e\x16\x87\x72\xb8\x6c\x33\x46\xd2\x35\x6c\x0e\x0b\xa9\x11\x83\xf4\xa4\x56\xf1\x18\xdb\x43\x19\x88\xbc\xb8\x61\x50\x77\x7c\xb4\x5a\x97\x4c\x50\xc2\x4e\x21\x38\x8e\x41\x8e\xae\xe4\xdc\x47\x45\xe5\x09\xca\xba\xa9\x8e\x79\xb6\xfb\x2f\xff\xf3\x8f\x7d\xf9\x9f\x7b\xf4\x43\xd5\x9c\xa7\x7f\xca\xd3\xa6\x6a\xab\x43\x37\x3d\xf6\x36\x85\x96\xdd\x07\x5a\x32\x8e\x7f\x38\x90\xa2\xa5\x6a\xe8\x1b\x11\x20\x35\x0f\xa0\x0e\x17\x87\x26\x21\x93\xc9\x6d\x06\x84\xcd\x87\x10\x49\x5e\x79\x32\xf2\x06\x29\xa4\x13\x25\xd2\xdc\x04\x9a\x80\xf1\xc5\x03\x36\xe4\xc5\xd2\x2d\x64\xc8\xf7\x9d\xd6\xff\x61\x4c\xa7\x87\xfc\x85\xf7\x3a\x9e\xc9\x42\x3b\xf0\x8e\xcd\xb0\xdb\xad\x6a\xfd\x60\xa0\xb1\x9e\x1b\x17\xf7\xa5\x8e\xb8\xab\x34\x89\xa6\x25\x79\xde\x93\x26\x66\xdc\x89\x53\xf7\x83\xb2\x47\xc0\xa3\x4a\xab\xb2\xa3\x65\xb7\x8b\xde\xbf\x37\x1d\x20\x2c\x41\xb7\x72\x69\xcc\x8a\x35\x86\xc7\x19\xb0\xdb\xc7\xaa\x94\x7a\x31\xdc\x00\xc4\xdf\x6a\x0d\xbe\x6e\x21\xd8\xe0\x5a\x8b\xd4\xaa\x89\x15\x79\x8f\xd9\x83\x3f\x28\xb5\xa9\xd5\xef\xec\x27\x74\x87\xf5\xb0\x58\x07\xf3\xb5\xb1\xf4\x44\x6f\xc9\x97\xe7\xba\xd7\x65\xae\xbf\x25\x1c\x5c\x85\x8b\x3b\x70\xc3\x39\x6f\xac\x66\xe0\xe3\x8d\x50\xd5\xc3\x61\x08\x80\xb9\x8f\x87\x81\xc0\xe8\x0d\x56\xae\x47\x7c\x87\x16\x20\x95\x6b\x75\x5a\xdf\xf5\x30\x2f\x28\x18\x4c\xfe\x90\x80\xc6\x6a\x39\x23\xf7\xc9\x94\xe5\xf0\xd5\xee\x65\xf0\x93\xe3\x69\x55\x9b\xa5\xf6\x8d\x2a\x79\x75\x4a\x0f\x74\x74\x55\x55\xec\x49\x83\x00\xae\x70\x40\x8b\x39\x55\x60\xde\x04\x75\x74\xbc\x80\x87\x7a\x04\x3f\x61\xb4\x9f\x2c\xda\xfa\xab\xdc\x48\xbc\x88\x77\x45\x59\x75\xd1\x07\xed\xe1\x8e\x8f\xe2\x1b\x78\x47\x42\x7c\x32\x97\x46\xdf\x7e\xf3\xee\xe3\x2f\x23\xf1\x5c\xa8\x0e\xc6\xeb\x20\xe6\x6d\xc2\x31\xa4\x60\xbe\x22\xc8\x55\x57\xd5\xdc\xaa\x0c\xfc\x59\xe6\xd6\x04\x70\xf0\x32\xd4\x8c\x89\x4d\xd7\x7f\x73\x15\x59\x56\xdd\xb7\xdf\xbc\x33\x50\x0c\x36\x7b\x49\xf8\xb8\xd4\xcb\x71\x26\xc7\xb5\xcb\x84\x0d\x54\x81\xc1\x88\x85\x75\xb7\x20\xee\xef\x3f\x53\xae\x88\xb1\x08\xa4\x63\xaa\xc0\xaf\xa2\x01\x82\x17\xbf\x1e\xe0\xca\x7e\xbf\x6e\x8e\x2c\xdd\xb2\xed\x2f\x73\x34\x2d\x40\x87\xdf\xa9\xb7\xf1\x13\x8a\x65\xe4\x22\x7b\xc0\x52\xff\x3e\xb8\x8c\x0c\x4b\xed\x15\x40\x75\x36\xc7\xc8\xce\xe6\x08\x5d\x4f\x03\xff\x2e\xf7\xbe\x7c\x5c\xe9\xdb\x4f\x37\xee\x2e\x41\x57\xd2\x6d\x38\xd9\xc5\x56\x05\x27\xd4\x4a\xc4\x8b\x56\xa2\x21\x88\xc6\xc9\xa0\x9e\xe9\x6b\x8e\x91\x4c\x24\xd1\x2b\x9c\x21\xbd\x44\xcc\x65\x1e\x77\xc5\x74\xa1\xec\x65\x0a\x78\x22\xfa\xd1\x7e\x99\xc3\x78\xae\x66\x84\x53\xb3\x36\xe4\xf9\x69\x07\xa6\xe5\xa9\x20\xc5\xa1\xad\x1d\xa1\x65\x39\x31\x22\xa6\xa0\xa5\x90\x9e\x21\xb7\xc2\xed\x21\x6f\xb8\x7e\x61\x53\x41\xd0\x24\x60\x3a\x9d\x5e\xfb\xed\xb5\xd6\x22\x98\xe7\xb5\xd7\x57\x5b\x51\x83\x3d\xbf\x49\x0f\x35\xe0\x41\x33\x8d\x86\xbd\x1c\x1d\x3b\xd7\x4f\xd2\xf2\x60\xc0\x75\x3d\x74\x87\xf9\xfa\x26\x82\xb6\x4f\xf9\xcb\xaf\xdc\xd9\xb7\xcd\xe2\x3a\x63\xd7\xaa\x81\xcd\xd2\x5f\x2f\x6d\x97\x1f\x72\x9a\x21\x1b\x69\x88\x19\xe3\x1b\x6c\x05\x79\xad\x2e\x1d\x08\x86\x0c\xc7\x06\xd8\xbe\xdc\x2e\x6a\x69\x4d\x1a\xd2\x21\xd6\x4a\x55\x68\x9b\x64\xbd\x08\xb8\x90\xe3\x8f\xf2\x43\x56\x11\xe3\x8a\x52\x56\xd6\xd5\x6b\x97\x71\x54\x3b\xb2\x60\xc5\x68\x7e\xcc\x48\x47\x84\x3a\x89\xdd\xe3\xf6\x27\x6e\xd2\xf1\xdc\x28\x61\x08\x43\x56\x78\x37\x3c\x9c\x3e\xae\xad\xcb\x81\xab\x32\xb3\xb8\x77\x97\xf8\x9e\x4a\x43\xd3\x6e\x70\x50\x12\xe6\xd0\x8c\x67\x5d\x1d\xfa\x7a\x24\x2a\xa2\x14\x73\x54\xe5\x00\xe1\x1f\xd3\x82\xb4\xed\xef\x7f\x48\xab\x22\xfe\xc9\x9c\x50\x1f\x6f\xc9\x75\x7e\xb4\x13\x1e\x79\xb8\xd7\xf3\xdb\x1a\x7b\x69\xfe\x47\xec\xb0\x7a\xd9\x99\x12\x23\xd7\x92\x59\x8c\x66\x58\xf2\x42\xed\xbb\x72\x70\x38\xfe\x6e\x59\xb0\x5d\x0d\x74\x00\xa1\xcd\x0c\x80\xf5\x36\xf6\xca\x94\xdb\x7e\x96\x3d\xe0\x1e\xe6\x03\xb1\x64\x33\xac\x9c\xdf\x0e\x9e\xc4\xee\x06\x0a\x68\x73\xe3\x26\x8a\xf1\xe0\x49\x8f\xad\xbf\x2a\xe4\xd5\xdd\xbe\x78\x5c\x77\x4d\x28\xb4\x3b\x7f\xbb\x07\x08\x5c\x2d\x73\x00\x85\x2a\xed\x55\xad\xbc\xf2\xb5\x03\x3f\xcb\x1e\xf0\xeb\x95\xd6\xd5\x0c\x87\x7e\x59\x3c\xb9\x94\x16\xe7\xc6\x4d\xf4\x76\xa5\xb5\x32\xdb\x21\xd5\xa2\x29\xea\x10\xc7\x65\x94\x7c\xa0\x8f\x6d\x8d\x09\xc6\xc7\xad\xc8\xf7\x59\x75\x85\x8a\x45\x79\x6a\x8e\xcd\xb8\xf1\xed\x0e\x3c\x1f\x67\xe8\x73\x97\xe3\x07\x06\x1e\xed\x97\x2f\xf1\xe4\x53\xee\x57\xf3\xae\x79\xf5\xd2\xd9\x2c\xf4\x49\x96\x51\x4b\xe6\x3e\x32\xe9\xaa\xe0\xda\x73\xa9\xee\xd3\xa7\x76\xcf\x38\x32\x01\x7a\x01\x35\x77\x53\xcb\x80\x37\x3e\x7e\xe0\xe3\xe1\x48\x35\xe6\xe3\xe2\xd6\x38\x00\xe5\x72\x8d\x32\x06\x02\x9c\xe6\x71\x92\xc6\x52\x13\x21\x0f\xde\x8c\xd6\xd7\xde\x2c\x76\x6f\xad\x84\xc7\x29\x58\xe3\xf8\xdb\x6f\xde\xfd\xda\xbb\x16\x5e\xc1\x6b\x11\x7c\xf5\x24\xf8\x58\xcf\x82\x15\x3f\xd6\xb1\x46\x40\x20\xac\xd3\x9c\xab\xee\x20\x1a\x8e\x1d\x98\x91\xee\x40\x49\xa3\x9d\x1e\xd2\xbf\xde\xd0\xc5\xed\x91\x7e\x9f\x7c\x61\xf7\xb9\xd7\x47\xf1\xc8\x7e\xf3\x60\x56\x92\x91\x53\x19\x4e\x2f\xc8\x7d\x7e\x12\x43\xf9\xa4\xf0\x9c\x5b\xad\x18\xda\xb0\xb3\x81\x96\x0e\xfb\xcb\x68\xb1\x6f\x97\xf9\x6e\xa6\x47\xb7\x94\x2a\x27\xa7\xb3\x5d\x96\x46\x06\x1a\x21\xbd\x1e\x5b\x7c\x25\x79\xd6\xb6\x54\xc0\x11\x18\x2c\x25\xa4\x79\xce\x13\x90\x79\x2a\xf2\x90\x78\x80\x76\xae\x89\xa3\x89\x93\x4d\xa1\x8f\x53\x1a\x73\xde\x4a\x6b\x8c\x7e\xe8\x4f\x7d\x08\x38\x2c\x86\x3b\x06\x3a\x69\x70\xfe\xcc\x75\xa4\xcd\x02\x34\x98\x19\x3d\x1b\xe7\x3d\xd6\x77\xcb\x89\x36\xd8\xd5\xe2\x24\x19\xe7\x46\xfe\x05\x39\x54\xdf\xc0\x15\xa3\x11\x8f\xc9\x38\x60\xa8\x55\x57\x92\xe7\xf8\x57\x3f\x9b\x2a\x7b\xf9\x29\x3f\x1f\x85\xb1\x50\x7b\x37\x86\x92\xc6\x1d\xd9\x6b\x89\xed\xd5\x41\xa6\xc1\xe9\xcb\xb2\xcc\xc4\x90\xba\x6d\x9e\xaa\xd6\x47\x88\x31\xae\x24\xa6\xd0\x15\x7d\xa8\x8f\x1f\x81\xbb\x21\x45\x28\xfb\xff\xc9\x60\xda\x35\x26\x9c\x97\xc6\xfa\xde\x14\xff\xc1\x9b\x0e\xcf\xb0\x62\x9f\xa1\xfe\xd8\x85\xd8\xe9\x55\xe1\xa1\x4b\x6d\x16\x09\xe1\x5c\xc7\x6b\x61\x4e\x39\xb3\xa7\xec\xc9\xd1\x3b\x00\x18\x7b\xec\x87\x1e\x47\x37\x62\x7a\x86\x72\x58\x02\xd5\x29\x18\xda\x81\xa9\x9c\x85\xa0\x2b\x85\xac\x68\xe5\x7a\x0a\x6b\x84\x5e\xf8\xc1\x3d\x2b\xea\x1d\x70\x40\xcf\xd3\x64\x57\xa4\x1f\xc6\xf6\xd5\x41\x3d\xaf\x24\x90\x38\xea\x70\x38\x2f\x50\x8c\xfa\xc1\x4e\xd7\x9a\xcd\x25\x43\x44\xcb\x5d\x20\xc0\x85\x18\x05\x35\x87\x9d\xc3\xd6\xdc\xdc\x0f\x52\x7e\x5e\x83\xf6\x08\x20\x50\x83\xe1\xed\xa4\xdb\x44\x73\x95\x6c\xf0\x41\xcc\x2f\x0c\xeb\x7a\x50\xe7\x45\x81\x19\x64\x0c\x46\xc8\xc6\xaf\x0b\x12\xf8\x93\xa0\x69\xde\x48\xc2\x60\x4d\x89\x58\xdf\x35\x9b\x68\x97\x7a\x8e\xf4\x3b\x4f\xee\x43\x3e\xda\x8e\xa4\x5f\x46\x2d\xcf\x00\x65\xb4\x8d\xbf\x28\xe2\xdb\xe9\xf7\x9a\x48\x14\x68\x84\x97\x3b\x19\xbf\xdf\xcc\xe6\xbd\xd1\xd4\xdd\x6a\xe1\x0c\xa1\x8f\x4d\x44\x77\x33\x86\x23\xa3\x3d\xd0\x08\xfe\x16\x06\xf0\x57\x37\x7e\x6f\x12\x45\xb0\x2c\xc2\x0c\x5e\x47\xf6\xb1\xb8\x01\xf0\xc4\xfe\xa8\x49\xe9\xb9\xbe\xab\x81\x83\xdc\xe7\xce\xd5\x17\xf7\x87\x91\x01\x84\x9d\x09\x7a\xe3\x19\x06\x7e\x54\xdf\xb3\xd4\x83\x0f\x5b\xac\xf0\xe7\xe5\xe5\x6d\x12\xaf\x73\x7c\xd5\xd5\x03\xad\x33\xb4\x01\x12\xfc\x80\x83\xb8\x83\x00\xee\xc4\xe8\xf3\x92\x36\xca\x7b\x48\xed\x1e\xb6\x79\x98\x71\x85\x1e\x66\x14\x5f\xe5\xfa\x28\x7e\xd9\xf1\x7b\xb8\x85\x76\xe5\x58\x15\xb7\x69\x53\x15\x05\x5b\x25\xb3\xa7\x11\xcc\xab\x23\xce\x45\xc5\xd8\xb3\x5e\x09\x3f\xd0\x38\x5f\xad\x26\xd1\xf0\x9f\xe9\xcc\xfb\x0a\x99\x13\xc9\x21\x17\x75\x83\x5d\x36\xe7\xf5\x5a\xf3\x6d\x49\xd9\x7a\xcb\xc9\xba\x48\xe3\x3d\x61\x89\x1c\xb1\xd4\xee\x9f\x28\xce\xf5\x4a\xf5\x71\x17\xfd\x53\x7e\xae\xab\xa6\x23\x5c\xd4\xda\x26\x96\x59\x66\xbe\x1d\xcf\x59\x1c\x96\xc7\xa2\xf3\x01\x9a\x8b\x23\x21\x4b\x4d\x98\x02\xdb\x40\xd1\xef\x02\x19\x74\xcc\x2b\x43\x5d\x55\xdb\x30\xd2\x00\xf6\x1f\xf9\xa3\x57\x28\x1c\x67\x08\x3b\xc3\x81\x3f\x59\xa4\x29\xc9\x9b\xb9\x54\x21\xb1\x17\xf0\x06\x71\x82\xdc\x58\x22\x2f\x71\x46\x9f\xf3\x94\x4a\x25\x5b\x3e\x24\xf5\xcb\x47\x52\x66\xd1\x87\xaa\xc9\x69\xd9\xf1\xe8\x4c\x41\xca\xac\x4d\x49\x4d\x75\xfd\xbb\x07\xa3\xef\x84\xe3\x30\xb0\x3a\x4f\x12\xfd\xbd\x97\xde\xde\x93\xbc\xa4\x4d\x7c\x28\x2e\x79\xf6\x84\xd4\xe4\x02\xe1\x16\x8b\xcd\xe0\x0a\xc4\x8b\xff\x84\xd8\xba\x7b\x3f\x2b\x74\x97\xf6\xbc\xa5\x41\x98\x03\x85\x3e\x61\xa5\xa9\x25\x50\xf7\x5f\xb0\x1b\xfa\xe6\x09\x68\x66\x19\xaf\x33\x68\x46\x15\xc8\xae\xae\x77\xb0\x60\x2a\xf7\x0b\x7e\x57\xd2\xbe\xcb\x68\xa6\x1d\x58\x24\xd7\xf1\x1e\xc2\x48\x78\x83\x24\x86\x75\x0d\x12\x15\x2f\x3a\x20\x7f\x31\x2f\x7f\x62\xe1\x6e\x9d\xea\xcc\x8a\xae\xf5\x54\xf7\x4d\x6f\x10\x90\xe8\xa0\xe9\xca\x0c\x71\xeb\x95\x88\x5b\x87\x1c\xc9\x9a\x27\x56\x3b\x58\x8d\x70\x81\x39\x7c\x1c\x89\x73\x63\x84\x54\xd4\x14\x75\x12\xc3\xba\xf7\x69\x18\x51\x3a\x43\x8a\xbf\x27\x73\xd0\xea\x70\xc0\xd4\xd9\x66\xc3\x52\x02\x78\x15\xc4\x77\x33\x92\xa9\xb1\x26\xfa\x2d\xd8\x87\x87\x2e\xee\x83\xf6\xc9\x70\xc5\x0c\xcd\x90\x3b\xea\xb7\xdf\x22\x7f\xc3\xeb\x4f\x9a\x04\xbc\x39\x46\x74\x59\x4d\xf3\xb4\x2a\x63\xe9\xef\x3a\x53\x2f\xcd\xe7\xfa\x5b\xf6\xf8\xf9\x04\x7b\x68\x99\xb5\x7c\xd2\xeb\x83\xa2\x5e\x5e\x6b\xf6\x40\x6f\x9b\xab\x1e\x4b\x33\xe4\x76\x96\xdc\x58\xd8\x4c\xfb\xb1\x16\x1b\x9b\x44\x02\x12\x6c\x3d\x69\x2f\xb8\xe9\xe3\xd5\x7a\xed\xd4\x35\x3c\x35\xc7\x41\x35\x67\x63\x36\x47\x6d\xb2\xa0\xd7\x9d\x07\x7d\xe6\xd6\xfe\x11\xac\x26\x94\x33\x6a\xfa\xb2\xf6\x43\x93\xa3\xca\xa9\x74\xf0\xed\xbe\xaf\xb3\x41\x66\xba\x80\xc1\x58\xb9\x50\x58\x8f\x0c\xaf\x49\x6a\xa7\x67\xe4\x3d\xa4\xb9\xb2\x09\xa3\x1c\x80\x00\x01\xd2\x69\xe1\x24\x4c\x5b\xeb\x07\x96\xb1\x3d\xde\x08\x57\x0e\xcf\x6b\x57\x97\x52\xb3\xcd\x59\x46\xa9\x7a\x62\xb7\x48\x85\xae\xac\xe5\xe8\x3b\x74\x18\x18\xe3\x40\x98\x3f\x7b\x20\xe0\x56\xf9\x50\x35\x67\xec\x50\xd2\x2a\xd0\xdc\x9a\xae\xa3\x61\x6f\xed\x99\x21\x78\x51\xeb\x8c\x0e\xdd\x6b\xf1\x3b\x91\x00\x2c\xd9\xc0\x1d\x17\xc8\x21\x84\xaf\x74\xc4\xfa\x5e\xfa\x75\xdf\x5b\xb6\x6b\xfa\x55\xde\x5b\x76\x56\x13\xfe\xde\xb2\x46\xe2\x6e\xef\x2d\x3b\xa9\x9a\xa7\x52\xdd\x80\x8e\xf7\x96\xc3\x10\x7c\xef\x2d\xbb\x28\x04\xbe\xb7\xac\xa1\xdf\xe7\xbd\x65\x9d\xe4\xf0\x02\xae\xf6\xfd\xb7\x7b\x6f\x19\x65\x47\xbd\xb7\x8c\x30\x35\xfe\xde\x32\x4e\xd2\x71\xca\x12\xa9\xe1\x4e\xef\x2d\x6b\x94\x6f\x7f\x6f\x39\xd0\xcd\xc1\xed\x8c\xbd\xe5\xe3\x1e\xcd\xe6\x75\xbb\xd1\x4d\x94\x6b\x2c\x20\x1a\x13\xd4\xa6\xbf\xc4\x13\x87\x1b\x8f\x10\xdc\xc7\xc7\xc2\x3c\xd6\x91\x60\xbd\x19\x8c\xbf\x3d\x52\x8f\x07\xb0\x46\xb9\xc0\x16\xd0\x16\x23\x4b\x6b\x47\xe1\xd7\xbb\xbb\x2b\xd7\x99\xfa\x49\x42\xc4\x0f\x01\x0e\x87\x8d\x3b\x05\x19\x79\x21\x89\x19\xbe\x51\x31\x43\x96\xed\x82\x88\xc8\xb0\xab\x11\x59\xe2\x44\x90\x85\x1f\x7d\xe9\x6c\x74\xdc\x71\xba\x22\xe8\x66\x52\x77\x78\x99\xe6\xca\x58\x57\x7a\xc3\x2f\x0c\xac\x73\xc8\xd2\x04\xea\x74\xc7\xb5\x87\xfc\x66\xda\x2a\xdf\x8c\x9f\x23\xae\x25\x4a\xe8\x7f\x23\x74\x8d\xd1\x8d\x0c\x45\xf8\xc2\x2d\x76\x62\xe9\xa1\xff\x87\x9c\x90\xa3\x9b\xfe\x9f\x83\x98\x1d\x50\xc2\x8f\x17\x3a\x71\xcc\x65\x0a\x0e\x84\x9e\xc7\x62\x07\xea\xae\x39\x49\x88\xd1\x57\xda\x13\xce\xb7\xb6\xfc\xb8\x1e\x6d\xac\xc5\xfa\xf9\xcf\xd0\xf7\x7b\xc3\x5b\xdc\xd3\x37\xf6\x88\x47\xc1\xf4\x6d\xf3\x71\x70\xfb\x90\xa8\x38\x3d\x87\x9d\x8b\x0c\xd1\x2f\x46\x5e\xcb\xf0\x18\x06\x18\xc8\xb8\xf7\x7c\xab\xbc\x50\xf3\x16\x2d\xb3\x12\xf5\xa8\xa7\x07\xb4\xd3\x8b\x6e\xdc\x31\xad\x11\x50\x63\xaf\x25\x04\xd6\x66\x84\xde\x10\x4a\x0f\x0f\x0f\x23\x94\xec\x5d\x23\x13\x42\x39\x35\xb7\x58\x1c\xd6\x6f\xf0\x64\xf0\x08\x50\xa0\x26\x58\x27\x89\xaf\x54\xe0\x40\x4f\x13\xa9\x7b\x2c\x1a\xa4\x59\x1a\x6d\x56\xb8\x8a\x98\x71\xec\xe3\x7a\x7c\x70\x1c\xc4\xb0\x4a\x63\x43\xe4\x36\xa6\x07\x5b\x75\x13\xcf\xae\xf3\x2e\x37\x12\x41\x5a\x2f\x34\xc3\xa7\x1a\x37\xb6\x1c\x18\xbc\xdb\xd8\xc6\x0c\xe1\xdb\xc8\x20\xed\x17\xf6\x31\xa4\xf7\xbd\x23\x5a\xa5\x8d\x0a\x9f\x53\x1d\x8f\x67\x80\x77\xb7\x4d\x44\x2d\x3f\x55\x40\x45\xd6\x53\x24\x4e\x80\x9b\xd8\x40\x1e\x1a\x09\x00\xf5\xbe\xfc\x33\xd6\x82\xab\x70\x30\x1f\x04\xbc\x8c\x2e\xf0\xf2\xf2\x99\x36\xe2\x88\x04\xf6\xe0\xf7\x7c\x8e\xf8\x95\xc9\x43\xff\xcf\x41\xc9\xed\x57\x6e\xb3\xfe\x5f\x08\x9a\x29\x51\x1c\xe8\xaa\x53\xad\xee\x19\xdf\x24\x6e\xf9\x95\x41\x7c\xa3\xae\xe5\x55\x98\x63\x8d\xf6\x7a\x97\x77\x68\xb7\xc3\xbb\xf4\x82\xd9\x53\xb3\x1f\xdc\x1e\x69\xee\x63\xc8\x41\x5a\xe6\xf4\x2e\x47\x00\x03\x19\xf7\x7a\x97\x4b\xf1\x2e\xf5\x5b\x74\xcd\xe9\x5d\xda\x16\x08\xc7\x1d\xd3\x9a\x30\xef\x32\xb4\xb6\x71\xef\x12\xbc\xb9\xe5\xa0\x64\x7b\x97\x26\x84\xcb\xbb\x9c\x25\xfd\xbf\x10\x8d\x30\xbd\x4b\x0f\x50\xa0\x26\x38\xbd\xcb\x40\x05\x0e\xf4\x2e\x91\xba\x5d\x33\x3b\x92\x1c\xdd\x65\xa8\x35\x27\x26\xb4\x0a\xfd\x99\x07\x5f\x03\x6f\x22\x8f\xf8\xc7\xd2\x5c\xde\x4e\x0f\xf1\x95\xae\xc3\x47\x9c\x24\xd1\xc1\x57\xb9\xc8\xe1\xdd\x88\xba\xc8\xd7\xa3\xbf\xa5\xe1\x5e\x17\xd9\xdd\xfa\x37\x76\xbf\xcb\x45\xbe\x85\xc0\x9b\x5a\xef\x77\x91\x85\x91\xbf\xda\x45\x36\xeb\xb7\x3c\xd7\x20\xdf\xc0\xe1\x9e\x7a\x8c\x2c\xea\x25\xfb\xeb\x72\x39\xca\x36\xc0\x4d\x9c\xb8\x1d\x65\x1f\x68\x88\xa3\xec\x6c\xc1\x55\x38\x98\x3b\xb5\x5c\x2e\x65\xb3\xf6\x0d\x25\x59\xda\x5c\xce\x7b\xfd\xb4\xc1\x83\x7d\xd8\xc0\xbc\x36\x10\xfa\x4c\x11\x7b\xd0\xc5\x7f\x10\x6b\xe0\x42\x9e\xb2\x70\xec\x34\x23\xe0\x9f\x8a\x7c\xb7\xa7\x87\xaa\xa1\x7a\x0b\x12\x79\x07\xca\x58\x0e\x0e\x6f\x40\x7c\xfe\x4b\x92\x90\xe4\x3d\x42\x15\x5e\xf7\x40\xd6\x62\x35\x39\xe6\x25\x3b\x09\xe8\xe6\xd5\xbe\x76\xa0\xbf\x0a\x95\x18\x59\x80\x11\xa9\x0c\xd5\x38\xa4\x82\x02\x32\xc7\x40\xff\xd2\xd6\x24\xf0\xe9\x83\x47\x57\x1e\x21\x2b\xe7\x81\x75\x78\xcb\xf5\xcc\x90\x7c\x27\xe7\xaa\x47\x80\x7c\xb7\x94\xd1\x56\x6b\x99\x21\x2c\x09\x68\xa5\x4a\x1a\xf6\x26\x63\xd8\x0e\xdb\x48\x0e\x59\xbd\x66\x90\x48\xc2\x66\x0b\x14\x2a\xae\xde\xb2\x8d\xe7\xe2\x02\x2c\xbf\xcc\xef\xf2\x6d\x67\x5b\x63\x80\xeb\x88\x14\xfa\x1e\x3c\x0d\x4e\x72\x80\xf7\x26\x5c\xa6\x61\x9f\xb1\xb6\x18\xb3\xbc\xc9\xb5\x2c\xee\x59\xc7\x11\x41\x8b\xdd\xe5\xd0\x98\xea\x69\x2d\x0d\xcd\x0d\xbb\x8c\x6f\xbd\xc6\x8b\xdf\x51\x85\xdc\x68\x8b\x41\xbc\x00\x6d\x85\xe9\x06\x58\x02\x52\x00\x88\x88\xb4\x32\x5c\x2d\x0c\x18\x67\x32\x8e\xe0\x9c\x1b\xba\x0d\xf0\x6b\x4c\x5c\x1c\x6d\xc3\x27\x3e\x0e\xb6\x2f\x24\xbb\x97\x8b\xb6\xc7\xbc\x20\x00\xd8\x58\xd6\xac\xc5\x7a\xd4\x9e\xac\x3d\xbc\x38\x4d\x8a\x5d\x3e\x6e\x55\x50\x56\x2c\x10\x84\x97\xf6\x8c\xc8\x9c\x7f\xb4\x65\xee\x49\xd9\xe6\x22\xed\x13\xb9\x0d\x30\x2a\xf2\xc5\xa8\xc8\x17\x1e\x5e\xdc\x22\xb7\xca\xc7\x45\x8e\xb2\x62\x81\x00\x5e\xc4\x50\x0a\x72\x27\xf0\x44\x7d\xae\x54\x43\x9c\xf8\xa8\x77\xc1\x60\x64\xcb\xf9\x1f\xaa\x99\x63\xde\x8f\xe8\xfc\xa5\xeb\xa0\x7f\x70\x4a\x12\x75\x60\x7e\x65\x0a\xc7\x9c\xe0\xe4\xa7\x37\x27\x2a\xe2\xb4\xa6\x25\x7d\xe9\x40\xeb\xf9\xdf\x4a\x00\xf0\xe4\x84\x81\x58\x37\xf4\x39\xaf\x2e\x2d\x44\x56\xdf\x4c\x02\x30\xef\x82\x80\x35\xad\xbd\xfe\xcd\x68\xb2\xd3\xc6\x6b\x65\xaa\xd6\xb7\x18\x66\xc9\xe6\x70\x5c\xcf\xd0\x02\xad\xff\xa7\x73\x7a\x8e\xa6\xeb\xfe\x3f\x0b\x7a\x36\x4c\xc0\x66\xf5\xbb\x47\x33\x29\xe5\x66\x2c\x29\x25\x7c\xb0\xd1\xd2\xf5\xc0\x94\x9a\x7b\xd2\x52\xf5\x06\xbb\xae\x61\xd3\xf9\x8a\x9e\x45\x1b\x09\x6f\xa4\x94\xb5\xfc\xd3\x19\x29\x1b\xcd\x36\x25\xd2\x81\x6b\x22\xdc\xd1\x73\xdd\xbd\xea\x82\xb4\xde\x1e\x19\x84\x8d\xbb\xf1\xea\x7a\xb9\x46\x7a\xec\x78\x0d\x58\xd6\x68\xf0\x3f\x9e\x1a\x7a\x18\xd6\xb4\x58\x99\x37\xab\x15\x3f\x05\xa3\x93\xae\x9b\xfc\x4c\x9a\x57\x17\x8a\xee\xf5\x68\x28\x28\x37\x7a\x99\x97\x9b\xf9\xc3\x3a\x19\xde\x1e\xe4\xe8\xed\x25\x4d\x69\xdb\x3a\x1b\x90\xee\x1f\x56\x29\x8a\x82\x72\xa3\x97\x79\xb9\x59\x2e\xb7\xd9\xb0\x04\xe7\xe8\x79\x79\xa8\x9c\xac\xec\xd3\x24\xa3\x36\x3c\xca\x07\x28\xf0\x32\xb1\x98\xed\x93\x6c\xa5\x13\xfd\x4a\x9a\x52\xbe\x13\x8e\x8d\xfc\x84\x64\x4b\x8a\xa2\xa0\xac\xe8\x65\xfe\x24\x68\xe9\x76\x33\x3b\x18\x9a\x48\xca\xa3\x1b\x23\xdb\xae\x16\x4b\x14\x03\x57\x5d\x58\xe4\x65\x25\xdd\x2e\x92\xb9\xea\xf8\x3d\xc9\x8e\xd4\x3f\xd1\xc1\xf7\xa0\xcd\xeb\x89\x8b\xfa\x25\xda\x38\x53\xd5\xfe\x9d\xad\x1e\x6a\x0d\xb0\x19\x17\x9c\xbf\x64\xf2\x08\xb2\x57\x83\xe4\x02\xed\xd5\xf0\xec\xc4\x4b\xfb\x04\x68\x88\x67\x32\x5e\x5a\x48\x73\x38\x9f\x3b\x38\xf6\xda\x3b\x48\x44\xb0\xaa\x0c\x37\xff\xf3\x7e\x86\xbb\x77\xa9\x38\xbb\x79\x47\xcf\x72\x9d\xa8\x58\x1e\x72\x15\xa9\xb5\xe9\x13\xe0\x1f\x59\x03\xfa\xa7\x5a\xbd\x3a\x48\x0a\x73\x40\x70\xf0\x4f\x00\x4b\x3f\x98\xb9\xc2\x53\x33\xe9\x3c\x6b\x01\x13\xe0\xa2\xfe\xf5\x72\xde\x57\x5d\x63\xe6\xa1\x5e\x20\x37\x96\x64\x10\x51\x26\x6e\x17\x2d\xcd\xcb\x13\x6d\x72\xd7\x3a\x19\x78\x64\x43\x55\xd3\xd3\x6c\x12\x81\xbf\x4f\x33\x28\x57\x41\xd0\x46\xab\xb1\xe3\xd5\xc8\xfd\xe1\xf9\x0c\x19\xa2\xf3\x24\xb1\x28\x3e\x9d\x1a\xd3\xdd\x57\x26\x6a\xd5\xff\xb3\x72\x0b\x00\xae\xed\xfb\xf7\x91\x21\x4d\x77\xae\x69\x20\x8a\x81\xf4\x2f\xce\xd7\xb6\xc4\x16\x5d\x9b\x36\x94\x96\x11\xcb\xbb\x30\x18\x2e\x78\x94\x58\xaf\x7f\xe8\xce\xe5\x83\xb8\x3b\xf5\xef\x5a\x66\x81\xab\x5a\x63\xe6\xa9\x90\xcf\xe7\x1b\x6b\x9b\x35\xb8\x53\x38\xda\xe3\xb0\xd7\xd6\x0b\xfd\x36\x5d\x77\xba\x9c\xf7\x25\xc9\x0d\x27\xd5\x5e\xa3\xe0\x67\xc6\xe7\xd8\x2d\x55\x23\xb3\xe4\xdb\x17\x34\xc6\x43\xf9\x6c\xe7\x45\xd8\x4b\x0e\x19\x4d\xe7\x6d\x44\x49\x4b\xe3\xbc\x8c\xab\x0b\xbf\x5e\x57\x05\x02\x8e\x43\xd9\xc2\x62\xd9\x3f\x27\xd1\xf0\x05\x64\x03\x85\x56\x43\x5e\xf6\xd0\x0c\x03\x48\x2e\x43\x06\x0a\xea\xe1\x5a\xf0\x6d\xb0\xcd\xc3\x27\x67\x62\x4d\xdd\x3b\x1c\x78\x9d\xa6\xa4\x56\xa1\x78\x78\x37\xfd\x11\x3f\xf1\x44\x0a\xda\x74\x46\x44\xc8\xbf\xd1\xf1\x86\x1b\xe6\xbc\xb2\xd3\x12\xbf\x59\x82\xdb\x2a\x8e\xc3\xff\x67\xd8\xec\x32\x5d\x05\x0d\xfa\xa9\x9e\x08\x84\xa7\x4b\x81\xde\x1f\x31\xc0\x3f\xd5\x16\x47\x2b\x83\xeb\x38\xcb\xdb\x73\xde\xb2\x65\xa3\xa4\x2e\xbf\xb1\x6c\x39\xbf\xd8\xf9\x96\x16\x3e\x22\xd1\x34\x2d\xaa\x16\xa7\xc5\x8b\x46\x9d\x05\xe1\x36\xc9\x8b\x08\xd2\x46\x7b\xe4\xa8\x79\xf9\x4a\x1b\xd2\xcd\x7a\xe1\x5a\xde\x66\x87\x43\x92\x61\xf7\x0d\xb2\x35\xdd\xa6\x6b\x9c\xba\x7b\x0e\x48\xb7\x74\xbe\x5f\xe0\x58\x66\x1f\xab\xd5\xca\x7e\xb5\x1c\x3c\x50\x0e\xa4\xd6\x07\x83\xff\xbe\x49\x1e\x5c\x87\x33\xb2\x2d\xcd\x0e\x58\x64\x79\x9f\xd2\x87\xc3\x0c\x21\xed\x6e\x01\x59\xd3\x19\xc5\xb8\x71\xb2\xbf\x5c\xcd\xd7\x5b\x1d\x01\xae\x2c\xd4\x51\x6d\xb2\xce\x16\x7b\x97\x11\x4d\x0f\x0f\x74\x81\xb4\xe0\x40\xe8\x3e\x4d\x71\xea\xee\x46\x1c\x36\x74\xb6\x5f\xe1\x58\xae\x76\xac\xd7\xab\x99\xd9\x0d\x60\x4d\xa2\xe4\xb3\x5d\x2e\x97\x73\x57\x33\xe6\x19\xcd\xb0\xad\x8f\xbe\x11\xd9\x0c\x25\xee\x6e\x05\x5d\xee\xb7\x69\x82\x22\xb9\x1a\xf1\xb0\x5c\xac\x16\x72\xad\xf9\xcf\xdf\x7e\x23\x67\x99\x2f\xf4\xf5\xd0\x90\x33\x6d\xa3\xba\xa9\x8e\x0d\x6d\xdb\x78\xcf\xd2\xe2\x34\x79\x4d\xf9\x70\x39\x34\xd5\x39\xfa\x05\x34\x6a\x18\x9a\xcb\x84\xfb\x02\x8c\x6a\x67\x2d\x5c\x07\xc0\x21\xc5\xcb\xbf\xf3\xea\xab\xbf\x57\xcd\x7f\x8f\x6a\xa7\xb2\x2a\x06\x0f\x33\x26\x78\xa6\x9b\xc0\xb4\xdd\xbe\x7d\xf5\xc7\x80\xfb\xf7\x73\xe4\x3d\x5d\xef\xbd\x7a\x14\x41\x05\x2c\x81\x4c\xcd\xa0\xe6\xe3\x90\x12\x85\x4d\x7b\xca\x91\x12\x09\xa2\xc7\x5e\xa3\x9a\xeb\x6b\x05\xff\x3a\xd8\xbb\xcd\xe6\x93\x49\x0c\x72\x07\x80\x16\xba\x1f\x25\xf6\x22\x60\xce\x1c\x3f\x17\x37\x5d\x73\xe7\x0b\x71\xe2\x6c\x00\x77\x29\x26\x78\xa1\xcc\xd9\x24\x1a\x3e\x8b\x4f\x91\xdd\x43\x76\x32\x0d\xc9\x74\x2f\x7d\xd2\xc4\xc7\x5e\xa3\x68\xd9\x7d\x58\xae\x32\x7a\x9c\x38\xd2\x2a\xac\x3e\xf6\x3e\xf8\x7c\xf5\xbb\x09\x74\x8b\x22\xeb\xc3\x2a\xf9\x9d\x9b\x04\x2b\x75\xa7\x65\x58\x7d\x8c\x36\x26\x3d\xf3\xc3\xc7\x47\xbc\x4d\xd5\xb5\xcd\x61\xac\xb3\xdb\xda\xff\x80\xcd\xf9\xbf\xb7\x2d\x6a\xec\x0d\x6d\xe2\x63\x9e\x99\xd6\x65\x62\xed\x0f\x19\xa5\x98\xc2\xab\x45\x85\xfa\x2a\x4f\xee\xd8\xea\x2e\xeb\x27\x65\x7e\x16\x11\x1e\x74\x22\x98\xb7\x42\xc8\x51\x5e\x1e\xf2\x32\xef\xe4\x48\xbd\x0d\xf1\x7a\x2c\x7c\x64\x5f\x13\xac\xf6\x0f\x7e\x17\xad\xff\x34\x02\xff\x98\x03\xe7\x3f\x8a\x11\x40\xf5\x3a\x7c\xdb\x63\x44\xa9\x31\x42\xff\xa9\xd1\xff\x78\x5a\xf0\x1f\x5e\xa3\xaf\xda\x43\x1b\x51\x6a\x07\xad\xff\xd4\xeb\x7f\x3c\x5d\xf8\x0f\xaf\xd7\xd7\xec\xc6\x8e\xa8\x35\x4e\xea\x3f\xb5\xfa\x1f\x4f\x13\xfe\x23\x6a\x35\xdf\x07\x33\xc3\xdf\xf0\x54\x19\x83\xb0\x1e\xec\x44\x1f\x62\x65\xa0\x93\x88\xff\x6f\xbc\xaf\x32\xbe\x2b\x8e\xc5\x70\x7e\xae\xd8\x56\xa3\x86\x39\x60\x0c\x1b\x76\x49\x62\x70\x12\x57\xfb\xbf\xd2\xb4\x43\xb6\xb0\x74\x30\x16\x16\x97\xbc\x3c\x4d\xeb\x4b\x51\x80\x4c\x3c\xc6\x1b\x08\x56\x25\xfd\x77\x03\x59\x65\x13\x32\x9f\x55\xb0\x90\xfb\x66\x28\x29\x40\x4a\x80\x01\xc7\x93\x2f\xe6\x09\x85\xae\xaa\x75\xda\x3c\xa5\x1c\x23\xe1\x7f\x16\x59\xb2\xa2\x52\x52\x5b\x87\x1f\x58\x91\x0e\x7e\xa2\x24\x93\x53\xac\xb5\x41\x83\x65\x58\xd3\x64\x96\xb7\x98\x70\xbd\xaf\x3b\x0e\x3b\xf3\xfe\x43\x9d\x5a\x5c\xd0\xb1\xad\xef\xd9\x30\x09\x79\xea\x11\xa9\x4c\x3d\x4f\x72\xe3\xa5\x0c\x83\x41\xd7\xab\xb7\xb7\xe4\x30\x73\x55\x61\x24\xb5\xf3\x64\x4e\x73\xdd\x99\x18\x39\x18\xbc\x04\x67\x4a\xb0\x0e\x00\xf9\x36\x9c\x70\xe6\x07\x4d\xef\xec\x5d\x4a\x8b\x00\x38\x7f\x68\x14\x38\x33\xc2\x5c\x75\xe1\x86\x05\x93\x5d\x47\x5b\xe4\xe1\xd1\x89\xd5\x0c\x55\x04\x6e\x05\x38\x41\xee\x70\x29\x00\x9c\x04\x71\x55\xe3\x14\xf5\x28\xf7\x6e\xcc\x80\x66\x85\x74\xb0\xb1\x41\x19\xde\x82\xbe\x2b\x6f\x60\x9f\xa1\xdd\xc2\xbb\x2f\xf9\x18\x7e\xee\x09\xe1\x8e\x17\x0c\xc7\xf0\xf0\xe2\xe0\x2b\x35\xb7\xdf\x9f\xc1\x6b\xbe\x46\x4f\x46\x30\x9e\xa6\xed\x99\x14\x05\x2a\xea\x31\xd4\x31\xcc\x5b\x54\x33\x08\x73\x9c\xe9\x31\x02\xa3\xf8\xfe\x91\x71\x3b\x66\x00\xeb\x23\x04\x18\xfe\x15\x43\xd3\xd5\x8b\x8e\x81\xe9\x97\x9f\x73\x58\xfa\x79\xb7\x06\x65\xba\xc9\x32\xea\x3a\x20\x78\xeb\xc1\x07\xd7\x04\xe4\xa1\x37\x8a\x72\xbd\x6d\x74\xd2\x72\xce\x83\x0a\x00\x49\x77\xe4\x6d\x75\x02\x4e\x75\x38\xa9\x82\xd3\x4b\x7e\x88\x61\x1e\x1c\x85\xbc\x26\xd9\x06\x68\x82\x61\xe9\x60\x0f\x58\x35\xde\x72\x68\xc4\x29\x0a\x07\x31\x3f\xfc\x3d\xba\xbe\x27\xe4\xee\x77\x56\x8a\x74\xba\xaf\xa5\xe9\x92\x2e\x0e\x4e\x5f\x8b\x91\xf4\xf4\x38\x28\xf6\xb3\x85\xcd\x71\x01\x7d\x3d\x70\x6e\xf4\x35\x94\xb7\x55\xe1\x8d\x27\x6c\x9c\x42\x70\xd3\x1b\x45\xb9\x47\xa7\x0b\x5a\x6e\x01\x4b\x00\xbb\xeb\xfd\xad\x26\x87\xb9\x3a\x3e\xe4\xa4\xea\xe9\x7d\x1d\xc2\x37\xde\x0d\xc8\x6b\xc6\x3b\x68\x82\xae\x03\x5a\x0f\x58\x35\xde\x76\x3a\xc9\x29\x0c\x27\xb9\x31\x8c\x7b\x28\x00\x27\xe5\xee\x7f\x51\x6e\x4b\xd5\xdb\x62\xba\x4f\x53\x4f\xf7\x73\xa2\x9e\xde\xd7\x00\x7c\x9d\xaf\x03\x5e\xd3\xf7\x80\x7f\xbd\xef\x35\xd9\x7b\x45\x7c\x45\x20\xc3\xe9\x65\x60\xeb\x68\xe3\x1c\xf4\x62\xb8\xae\x58\x52\xf4\xdc\xe9\xdc\xde\xd6\x1f\x0d\x27\x8c\x1e\xae\x75\x9d\xe4\xe1\xc7\x94\x66\xf6\x31\xa5\xc4\x3e\xc4\xe3\x83\xd5\x5a\x35\x44\xe8\xb4\xe3\xc2\x3a\x0c\x94\x3d\x1e\x66\x09\x7d\x35\x25\xec\xfa\x32\x7a\xa7\x18\x65\x09\x7d\xd9\x19\xe4\x65\xc3\xdd\x5f\x4e\xa2\xcb\xbb\x82\x06\xe9\x53\x62\x1e\xe3\x5a\xfb\x0e\xe6\x02\xea\xd2\x93\x8f\x90\x8f\xe2\xd2\xeb\xf0\xd9\xfc\x7b\x58\x04\x58\x5f\xf5\x4c\x85\x68\xfd\x87\xaa\xea\xf4\x8b\xd5\x66\x97\x05\x9c\xb9\x33\x9e\xca\x31\x0e\xf8\xbb\xae\x76\x8f\xc4\x9b\xcc\xbe\x7c\x02\x83\x54\x8a\xe0\x49\xb4\x42\xa6\x9b\x7b\x32\xe3\x8a\xae\x03\xe0\x16\x45\xcb\x58\x07\x55\x61\x22\xc9\xe4\x7b\xf6\x1b\x7f\xc8\x18\x76\x33\xa3\xc5\x0b\x7d\xc1\xc4\x10\x26\x83\x89\xe9\xcc\x8f\xbf\xfc\x70\xed\x60\xd4\x98\x02\xe1\x4a\x4f\x28\x33\xa8\x7d\x61\xa4\xf4\xd6\x05\xc7\x45\xaf\xd7\x53\x69\x73\x3e\xf9\x14\xc5\x17\x11\x96\x87\x44\xed\xb9\xe9\x93\x3d\x68\x3d\x78\x0e\xc9\x75\xe2\x2a\x83\x28\xc6\xfe\x8c\x1b\xda\xd6\x55\xd9\xb2\x9b\x7c\xec\x8b\x7a\xe0\xd6\x3b\x9c\xd0\xaa\x22\x71\x33\xc5\xa8\xc3\xf1\xd9\xae\x5a\x02\x0a\x16\x82\xdf\xb6\x36\x78\x33\xa9\x6b\x79\x33\x78\x29\x3e\xb2\xac\x22\x6b\x9c\xbc\x75\x58\x5c\xc9\xda\x53\xd7\x4f\xc6\xfa\x97\x46\xe3\x5d\x4d\x06\x37\xd0\xee\xb5\xf7\x1a\xda\xd7\x71\xe6\x96\xea\x68\xcd\xff\xf0\x62\x8f\xba\xec\x6e\xbd\x30\x5a\xd5\xe9\xb7\xea\xf0\x7b\xb6\x6a\xb4\x2a\x7f\xab\xee\xda\x1b\x77\x95\xf7\x5d\x25\xfa\x16\x99\x8d\x0f\x92\xdf\x60\x10\x80\xf9\xfb\x57\x1e\x03\x77\xaa\x29\xa0\xc3\x7e\xab\x9a\xbc\x6d\xba\x67\x4f\xdc\x53\xd6\xf7\x94\xe6\x1b\xe4\x65\x2b\xff\xd5\x53\x00\xc8\x60\x25\xd8\xc1\x9c\x51\xb3\x04\xf3\x2d\xef\xb0\xde\xb9\x8a\x3b\xd1\x87\xf0\x43\x13\xaa\xb5\x7e\xba\xbd\xb7\x19\x4e\xf7\x0a\x96\x9c\xf2\x1c\xa9\xf3\xff\x02\x71\x5f\x33\x6b\xbe\xa9\x9a\x70\x3f\xe0\x0d\x9d\x7c\xbf\xd6\x8c\x54\x33\x32\xcb\xde\x4d\xfc\xf7\x93\xf0\xfd\x84\x78\xb3\x9c\xd0\xe1\xf0\x1b\xeb\xfa\x5d\x0c\xcd\x68\x47\xfc\xfa\xe6\xec\x6e\x6d\x19\xed\xc0\xbb\x98\xd0\xb1\xb9\xf4\x5e\xd2\xbd\x9b\x00\x6f\x95\x51\x14\x60\xf0\xd1\x60\x44\xdf\xea\x4f\x66\x90\xc3\x2a\x02\xfd\x6a\xcc\x4a\x9f\x00\xb0\x4f\x1d\x3e\x99\x71\x72\x77\x68\x14\x1b\x8a\x21\xde\x9c\xc1\x59\x88\xd3\x86\x85\xf4\x50\x4b\xc0\x21\xa8\x59\x87\x1d\x8d\x51\x90\xa0\x91\x63\x44\x39\xa7\x4f\x5d\xf3\x64\x98\xc0\x68\x14\x7e\x64\x7a\x1b\x30\x7a\x5d\xba\xa6\x06\x05\x1f\x5c\x43\xef\x8a\x5e\x53\x83\x82\x0f\x9e\xa2\x83\xe5\x76\x1b\x8d\x37\xf0\xe1\x90\xee\x6d\x34\xde\xc0\x87\xa3\x0f\x6e\xa3\x71\x72\x05\x61\xd5\x23\xd7\xa1\x3a\xed\xf4\x69\xf1\x6e\xf0\x4d\x30\xa8\xcc\x43\xe8\x03\xf1\x86\xd1\x07\xb2\x0c\xa1\x0f\xc4\x16\x36\x41\xde\x28\xb1\x40\x55\xbe\x95\x87\x20\xa9\x06\xaa\xf1\xad\x3c\x04\x49\x3e\x50\x85\x5d\xab\xa2\xe1\xa5\xe1\x10\x25\xd6\x67\x91\x71\x2d\x36\x16\xe9\x01\x6a\x16\x5c\x03\x0a\x8f\xd4\x10\xa0\x27\x66\x9d\x6f\xa7\x71\x25\x1f\x8e\xb6\xbf\x9d\xc6\xc9\xf6\x87\xc2\xfb\x1a\x7a\x5c\x01\x5d\x0d\xc1\xbd\x3d\x2d\x46\x46\x28\x7d\x0c\xfc\xc6\x7e\xf6\xd6\x78\x2d\x81\x2b\x79\x08\x6a\xf5\xb5\x04\x4e\x8e\xdd\xca\x91\x55\xdc\xc8\xcd\x0f\x93\x80\x7b\x9f\x1c\x5e\xb6\x81\xa0\xfc\x8f\xb1\x0b\x26\xe8\x3b\x1c\x26\x91\x4f\x36\x2d\x33\x01\x9b\x8d\xa4\x1d\x31\xf1\x0a\x07\x45\xfb\xe4\xd9\x46\x56\xa7\x2a\xc2\x10\x07\x6f\x1f\xf1\xb1\x3d\xfe\xbe\x4e\x1e\xdd\xc8\xf5\x37\x85\xa3\x98\x0c\x45\x8e\xe5\x87\x7d\xd2\xc6\xe6\x48\x4b\x8d\xed\x79\x67\x02\xc0\x3e\x21\xdd\x01\xae\xef\x84\x9e\x1b\xb9\xb2\x1a\x5f\x2f\x38\x93\x8f\x06\xb6\x00\xc9\x49\x0b\xd8\xf5\x3e\xa6\x88\xd2\xc5\xbb\xc9\xc5\xb1\x58\xd2\x3a\x99\xd6\x52\x86\xfb\x2e\x79\x68\xe0\xbe\x5e\x7a\xf3\x75\x12\x5f\x4d\xb7\x74\xd4\x15\xed\x78\x43\xfe\x60\x94\xee\x9b\xfa\x0a\xe3\x5b\x4b\x2d\xe3\x4b\x9f\xa8\x81\x7b\x07\xd5\x1d\x72\x35\xfa\x2a\xbb\x69\x68\x85\x37\x05\xe9\x31\xc0\xb4\xeb\xa0\xbf\x97\xf4\xdb\x06\x18\xc2\xfa\x90\x3a\xc5\x97\x2b\x72\x80\xf5\x76\xd7\x1d\xb2\x52\x3a\x6b\xba\xa5\xaf\x42\x1b\x81\x75\xd4\xc0\xae\xeb\x94\xbe\x9b\xee\x9b\x7a\x09\x63\x5a\xcb\x05\xe2\x4b\x89\xa9\x81\xfb\xfa\xea\x1e\xf9\x37\x7d\x95\xdd\xd2\x5d\x57\x34\x05\x9b\xb8\x06\xa6\x5d\x67\xea\xbd\xa4\xdf\xd4\x69\x18\xeb\x30\xd3\x85\x2f\xff\x27\x84\xf6\x75\xd9\x3d\x72\x8d\x7a\xea\xba\xa5\xc7\xc2\x1b\x82\x75\xd8\xc0\xb2\xeb\x20\xbc\x8f\xf2\x9b\xfa\x4b\x67\x9c\x9e\xf7\x34\x33\x57\x14\xa1\x57\xeb\xe5\x91\x78\xfd\x3d\x82\x04\xcb\xe6\xe9\xac\xcf\xfa\x22\x0f\xe3\x5a\x90\xec\x03\x5b\xab\x59\x45\x39\x4b\x71\x8a\x21\xf1\x1c\x12\x58\xc9\x73\x9e\xd1\x4a\x9e\x31\x54\x0d\x26\xfb\xb6\x2a\x2e\xdd\x90\x7c\x59\xac\x73\xe0\x6d\x80\x21\x65\x01\x48\x37\x8f\x65\xf8\xb4\x56\x61\x56\x5b\x67\xeb\xfd\xeb\x56\x4b\x88\xa0\xee\x2a\xac\xa7\xf3\xd5\xef\x9c\x88\xcb\xfd\xeb\x02\xc5\xdb\x0c\x48\x5f\xa9\xb8\xec\x79\xce\x4b\x2b\xab\xe8\x70\xf8\x7b\xeb\xcf\x02\x3e\xee\xd6\x6b\xab\x0d\xba\xe8\xff\xdd\x9e\x9f\x35\xec\x1e\xc3\x38\x86\x26\x04\xa6\xb1\x7f\xbb\x54\x1d\xfa\x2a\xbb\x7e\x7a\x5d\x7c\xb5\xf3\x9b\x42\x8a\x71\x61\xdc\x7a\x98\xeb\xf9\x14\x90\x77\x0b\x18\x5a\x7b\xd6\xd1\xb6\x28\x16\xd8\xdb\x1a\x12\x84\xc3\xe7\x2e\x1e\x03\x1e\x6d\x18\x7d\x57\x25\x49\x86\x97\xd3\xf4\xfb\x21\x89\x5a\x2e\x1c\xf2\xa2\xeb\x3b\x98\x14\xf5\x89\x7c\xa8\x6a\x92\xe6\xdd\x6b\xf4\x43\x34\x4f\x58\x97\x88\x0f\xbb\x68\x3a\xd7\x18\x56\xb7\xdf\xf9\x5f\xf6\x35\x20\x58\x77\xc0\xe3\x23\x3e\x56\x56\x26\x2b\x32\x9f\xc3\xfe\xd2\x75\x55\x09\x24\xa8\x52\x61\xd6\x35\x25\x0d\x29\x53\xf0\x82\xaf\x6e\xbd\x90\xea\x87\x71\xc0\x92\x1d\xa3\xc3\xfb\x5c\x65\xa4\x88\xd9\x7b\xd4\x58\x36\x1c\x0d\xcc\x30\xb4\x87\xfc\x85\x67\x7f\x18\x8c\x4e\x03\x8c\xab\xcb\x00\xa9\xd4\x01\xb3\x64\x95\x3c\x9a\xef\xd2\x60\x86\x18\x8e\x41\x59\x16\xb7\x69\x53\x15\x05\x6b\x7f\x57\x5d\xd2\x13\x43\xbc\x74\xbd\xee\x98\xcd\x9b\x1e\x48\x46\x23\xd1\xd4\x2c\x27\x45\x75\xd4\x84\x0b\x53\xf7\x6a\xdf\xd8\xfb\xff\xd3\x85\x78\x82\x01\x7f\xce\x41\xfe\x89\xc2\x42\x40\x0f\x45\xb3\x4e\x01\x5c\x90\x8e\xf6\xe3\x39\x9e\xaf\x7e\xc7\x13\xb3\x9e\xdb\x00\xa0\x6a\x1c\xc6\x0b\xa0\xcb\x2e\x2f\xc7\x24\x87\xd0\x49\x46\xd9\x4d\xc6\x78\x4d\xbc\x8c\x26\x1f\x11\x05\x06\x5a\xaa\xd4\xe4\x05\x2a\x91\xfa\xfa\xaa\xbd\x7d\x61\xb7\x0f\xf7\x26\xc4\xd4\xa9\x3f\xa5\x61\xe4\x58\x62\x94\xc4\xc3\xd5\x1e\x52\xee\x5b\x76\x48\xf2\xdd\xb4\xc8\xeb\x5d\x34\xcc\x9a\xd6\x24\x87\x96\xdb\xf3\xdc\x76\xbb\xc5\x4b\x8c\x89\x63\xfe\x11\x9f\x16\xf4\x21\xe6\xbe\xdb\xb7\xa8\x5f\xfa\x59\xc2\x24\x8b\x5d\xed\x73\x82\xea\x02\xed\x1b\x9b\x35\x55\x7d\x77\x0b\xb4\x4c\x1c\xbd\x91\x24\x09\xce\x02\x37\x26\xbf\x78\xac\xbb\x61\xdc\x5d\x74\xf2\xd2\x4b\xc5\x39\x47\x08\x3a\xbd\xab\x2e\x5f\x11\x02\xbe\xd2\x6c\x3d\x5d\x2e\x4c\x77\x69\xec\x66\xe3\x77\xec\x05\x40\xbc\x02\x30\x19\xc1\x10\x78\x3c\x37\x95\xde\xbc\x83\x88\x5f\x44\x95\x0f\xf2\x18\x42\x51\x37\x37\xd1\xd1\x82\xde\xe7\xe4\x98\xe8\xdd\x40\xd1\x5e\x98\x76\x5e\xf9\x20\x8e\x18\x38\x26\x01\x41\x7b\xba\xef\xca\x4f\xec\x91\x33\xd7\x9e\x82\xf6\xa8\x8e\x8b\xc5\xe1\xd1\x34\x9c\xe2\xf0\x60\xbb\x1b\x9d\x39\x85\x9f\x86\x9f\x36\xbe\xa1\x6d\x7c\x96\xdc\x93\x26\x3e\x53\xd2\x5e\x1a\x73\xb1\x64\xad\x1d\xe2\xed\x76\x2b\x3c\x3c\x61\xee\x56\xc2\xab\x96\x7d\xb8\xb2\x1e\x3f\xe0\x95\x88\x8a\xc5\xe3\x55\x1f\x22\xf5\x64\x55\xa4\xbd\x59\x65\xd9\x5a\x59\xcf\x3a\x91\x2f\x4c\x49\xfd\x61\xaf\x92\x71\x3b\xcd\x1f\x98\xb2\xad\xab\xc3\x02\xad\xc4\xe5\x50\xdc\x04\xbd\x0b\x05\xd6\xeb\x15\x8e\xb0\xe4\x77\x91\x24\xda\x0b\x56\x58\xc3\xb7\xdb\xb9\xd1\xf0\x42\x6f\xf4\xd6\x20\x32\xed\xaa\xaa\xe8\x72\xd3\xd0\xc1\x6e\x02\xd6\x6b\x93\xe0\x8b\x5c\xe6\x54\x1f\xc8\x39\x2f\x5e\x77\xd1\xfb\x7f\xa5\xc5\x33\xed\xf2\x94\x44\xff\x46\x2f\xf4\xfd\x24\x52\x1f\x26\xd1\xbf\x34\x39\x29\x26\x51\x4b\xca\x36\x6e\x69\x93\x1f\xcc\xeb\xc1\xd8\xf3\x87\x4b\xcc\x4d\x9f\x2e\x7d\x1e\xaf\xcb\x26\x8a\xe6\x8e\x19\xc3\xad\x69\x0c\xb7\x26\x81\xae\xaa\x75\x23\xb0\x92\x37\x5a\x35\xab\x05\x96\x29\x12\xd3\xca\xbb\x28\x74\xc2\x1a\xd8\x08\x2e\xc8\x60\xe8\xaf\x18\xc1\x35\x53\x36\xba\xaa\x45\x78\x8e\xf3\x12\x79\x41\x6e\x9e\x60\x4f\x5a\x3e\x5c\xf1\x22\xc7\x35\x79\xe8\xc4\x72\xc8\xbd\x9d\x2a\x79\x25\x4d\x53\x7d\xf5\xe8\x33\xf6\xde\x48\x62\x2f\x6e\xf1\xdb\xf7\x22\x6b\x23\x33\xe2\x98\x4a\x20\x5c\x20\x5e\xc1\x8a\xc7\x3e\x74\xb1\xeb\x93\xa6\x34\x86\xfc\xe1\x4a\xeb\xd2\x31\xe2\x36\x00\x36\x78\x7a\x4e\x84\x97\xe1\x49\x47\xcb\x5f\x31\xb3\x3d\xde\x93\x1d\xae\xf2\x81\xb2\xc1\x93\x4f\xde\x8b\x1d\x27\x2b\x7c\xa3\x9d\x77\x8c\x9d\x71\x93\x8f\x66\x2f\x13\x26\x23\xfc\x2c\xae\x87\x15\x57\x27\x41\x4e\xa0\x7b\x19\xc6\x4a\x22\x99\x79\xd4\x0f\xef\xf9\x38\x11\x66\xc5\xc5\xcb\x4d\x9a\x8b\xf1\x61\x84\x59\x9d\x9c\x38\xf5\xd7\xf2\xbb\x75\x6d\xf1\x88\xe6\x4d\xec\xf8\x95\xc6\xa9\xbc\x77\x63\xa7\xae\x6a\x15\x1e\x1a\x8b\xc3\xe2\xeb\x8e\x35\x1e\xf9\x80\xd6\x7c\xb3\x36\xdd\x78\x30\x15\xdf\x67\x72\x5f\x86\x4f\xee\xe0\x1d\x4d\x38\x77\xa8\x47\xa3\xf4\x37\x8d\x9b\x33\x29\xfe\x6e\xcb\xdc\x34\x4d\xdf\xbc\xcc\xf5\xb8\x95\x89\xed\x29\xce\x91\x95\xad\x1b\xd6\xd0\x22\xe5\xba\x68\x5a\x0a\x83\x0a\x12\x70\xf0\x54\xb4\xf1\x8e\x81\x02\xc7\x44\x4b\x9d\x8d\x80\x2a\x3f\xc4\x58\x87\xd8\xa0\x60\x89\xa7\x94\xf2\xa1\x6f\xa6\xf6\x24\x2b\x92\x63\x66\xe9\x8e\xcb\x6f\xfa\x7f\x23\x8b\xd3\x7d\xff\x0f\xe9\x2b\x65\xe5\x23\x73\x64\xea\x11\x18\x10\xb9\x66\xbc\x18\xc0\x4f\x53\x66\x40\x26\x91\xf1\x61\x47\x0e\x9d\x77\x90\xdb\x8e\xf7\xdd\x7d\x19\x9d\xa3\x08\x49\xdc\x32\x73\xb5\x07\xb0\x2f\xa4\xb1\x8b\xde\xbf\xb7\x4d\x1f\xa6\x13\x5d\x55\xeb\x55\xca\x94\xd3\xc2\x06\x79\x26\x1f\x09\x82\x4c\xff\x5a\xfc\x09\x96\x98\x43\x64\xf5\xd1\x36\xc3\x56\xe6\x10\x8b\x55\xd0\x60\xa0\x45\x08\x87\xea\x91\x3a\x29\x95\xe8\xbd\x83\x63\x2d\xf3\xd5\x18\x27\x6c\x78\x42\xb1\xd9\x2e\x8c\x92\x8e\x3e\xd6\x75\x91\xe9\x8e\x8a\x2e\x34\xad\xcc\x2b\x36\xe6\x63\x84\xb0\x8a\x88\x4d\x89\x48\x18\x18\xaf\xbc\x74\x76\x75\x89\x79\x99\xe0\xb5\x59\x02\xbb\x51\xc9\xe0\xd0\xc3\x27\x70\x5d\x92\x7a\xa1\x2d\x4a\x2f\xb7\x40\x66\x32\x90\x74\x93\x9e\x8d\x33\x0d\xcf\x85\x01\x83\xed\x52\x33\xf9\xde\x6e\xb8\x9e\x21\x2c\x68\xee\xa9\x2e\x35\x58\x34\x2e\x33\xc0\x29\x90\x98\xcc\x8a\xa3\x2f\x7a\xc6\xc4\x15\xc6\x2d\x10\x57\x4a\x9a\xea\xd2\x52\x73\xd7\x4a\xc6\x15\x4d\x30\xb0\xa6\xf6\x46\xff\xe5\x46\xb9\x6b\xa7\x4c\xa7\xf7\x34\x0d\x4d\xfe\x2f\x5d\x40\x6c\x53\x4a\xbe\x24\x29\x5e\x01\x57\x5e\x97\xb1\x15\xe5\x02\x1b\x83\xf1\xb1\xfe\x24\x1f\x18\x47\x0b\xe5\x5b\xe3\xba\xb7\xa8\x07\xc4\x48\x51\xf0\x37\xec\xd5\x5e\x4e\xbc\xc8\x3e\x46\x93\xe8\x83\xbd\xd9\x16\x2f\xb2\x48\x84\xcb\x9c\x72\x0c\xdd\xb6\x5b\x5b\xef\xab\xfb\xb7\xee\x10\x78\xc7\xf6\x1d\x46\x19\xb8\xb3\x07\x92\xd2\xf8\x39\x6f\xf3\x7d\x5e\xb0\x68\xd5\xb0\x01\xf5\x6e\xac\x5c\xd2\xa9\x69\xd3\xd6\x94\x67\xa4\x64\x2f\x8d\xb0\x52\xeb\xab\x7a\xe2\x1f\x11\x96\x48\x68\x39\x95\x6f\x8d\xa0\x30\xa5\xcc\x21\x09\xd7\x29\xde\xed\xbd\x45\xf6\xa1\x1f\x02\x7c\xd8\x7f\x1c\xc4\xe4\x05\x0b\xe1\x53\xbc\x45\x82\x82\xd4\x0d\x7d\xbe\x9a\xcd\x38\x90\xcf\xf8\x3a\x46\x7d\xa2\xe4\x8d\xe8\xeb\x72\xb7\x03\xb8\xf1\xd7\xb4\x26\x09\x68\x49\xa2\xb5\x02\x1f\xd4\xce\x46\x94\x3c\x41\xba\xf9\x59\x89\x1e\x7f\xcf\x06\x27\xcf\x8d\x82\xbe\x21\x71\x6d\x7d\x63\x0b\x6b\x60\x8f\x7d\x55\x00\x56\x7c\xa0\xaa\x5a\x35\x79\xfb\xc9\xba\xd4\xd5\xe8\xe1\x11\x19\x00\xd5\x0f\xad\x1c\x8e\xea\xb1\xb6\xf5\x53\x69\x53\x99\x33\xe0\x6d\xe7\xc5\x56\xe6\x03\xd0\x57\xbd\xf5\x8c\x9c\xd8\x41\x1e\xa9\x5e\x33\xed\xbe\x7e\x47\xd4\x6c\xf0\x20\xd0\xf0\x47\xcb\x78\x7f\x5a\x5b\x40\x51\x32\x3c\x66\x05\x0e\x6b\x25\xc9\xec\x23\x93\x79\xf8\x33\x62\x77\xae\x40\x34\x63\x20\xcf\xaa\x9b\xb0\x09\x3d\xea\xaa\x7a\xc2\xb7\x3c\xf9\xcf\x43\x53\x9d\x3f\x58\x55\x7f\xe4\x4f\x7d\x55\x66\x09\xab\xfc\x63\xe0\x8b\x62\x5d\x15\x89\x19\xe6\xb6\xa6\xc9\xde\xae\x9b\xea\x98\x67\xbb\xff\xf2\x3f\xff\xd8\xd7\xf3\x67\x69\xe0\xa6\x7f\xca\xd3\xa6\x6a\xab\x43\x37\x55\x55\xb6\x1d\x69\xba\x3f\xf4\x6a\xd7\x76\xcd\x0f\xdf\x7f\xf7\x90\xf0\xff\xfb\x9e\x55\x47\xcb\x0c\x94\x25\xaa\x2c\xfa\x6f\x02\xff\xcf\xaf\x35\xfd\x61\x66\x36\xaf\xa1\x35\x65\x87\xd5\xd8\xff\xc6\x2f\x4e\xdd\x1a\x46\x1e\x0c\x06\xf3\x11\x23\x8f\x86\xbc\x51\xed\xb8\x88\x50\xe9\xad\xee\xa2\x76\xb7\x57\xf0\x66\xb5\xe3\xca\xe5\xd0\xbc\xd5\xdb\xd5\x2e\xb0\x69\x77\x50\xbb\xc4\xa3\x76\x0f\xf7\x56\xbb\xe1\x78\xa2\x59\xe0\x4c\x58\xee\xdc\xcd\x1b\xdb\x65\xd5\x8e\xf8\x20\x7b\xae\xd6\xfc\x32\x3d\x16\xaf\xf5\x29\x4f\xab\x32\x4e\x4f\xf4\xb9\xa9\xca\xd8\x9c\x1e\x3d\xa0\xbc\x1f\x35\xaf\x4b\x41\x33\x40\xd3\x53\xd0\x4b\x43\x1c\x06\xb1\x3a\x56\x01\xf8\x95\xb6\xf4\xca\x4b\xb6\x7e\xc1\xfd\x9a\x5b\xda\xa8\xf8\x12\x67\xb5\x7d\x91\x0c\x10\x7d\x0b\x17\x96\xb3\xd2\x5e\x54\xa2\x52\xb9\x23\xa3\xd5\xaa\xe2\x03\xde\x6a\xaf\x91\xba\xda\x7c\xd6\x4f\x89\xc8\xbf\xad\xa0\xb6\xb5\x85\xa1\x76\x26\xd0\x45\xa4\xaf\xfe\xdd\x9e\x1e\xaa\x86\xea\x21\xce\xef\xff\x32\x4f\x16\xdb\xef\x03\x1a\xe7\x46\x27\x36\x7a\x5e\x66\x79\x4a\xba\xaa\x69\x3d\xba\xa6\xc2\x8e\x09\x12\xc1\x1a\x76\x7f\x56\xc0\xaf\x5a\xf3\x42\xf7\xdb\x82\xf2\x10\x00\x87\xc3\xbd\x2b\xd7\x03\x86\x18\xf7\x45\xae\x7b\xf3\x50\xf9\x35\xb7\x5a\xef\xcf\x59\xa2\xc7\xf8\x67\xe0\x88\x55\xdf\xae\x5e\x76\xb1\x3a\x3a\xe4\x3d\x8c\x0c\x77\xd4\xa2\xbf\x6c\xf1\x42\xdd\x74\x27\x1f\x1d\x7b\x3d\x7a\xb8\x51\x6e\x0c\xa0\xda\x0d\x64\x00\x57\x29\xb2\xbd\x73\xa3\xbd\x73\x64\x4f\xc3\x7f\x6f\x73\x50\x35\x9e\x0c\xda\xa3\x28\x2a\x31\xf4\xef\xa0\xda\xcc\xf5\xa8\xeb\xca\x50\x1b\x78\x65\x85\x0f\x28\xe3\x62\x84\x75\x11\xe2\xae\xae\xb9\xb3\x99\xea\x20\x9b\x46\x09\xe8\xa1\x08\x04\xb5\x69\x43\x69\xc9\x63\x41\xea\x8c\x94\x76\x36\xec\xd7\x9a\x58\xde\x3a\xb3\x0c\x47\xbe\xc4\x09\x35\xa9\x25\x0b\xfd\xc8\x9a\x34\x73\x62\x1f\x19\xae\x96\x16\xea\x9c\xd7\x1b\x9b\x09\xe7\x16\x66\xe7\xcd\x09\x65\x75\x5d\x45\x61\x13\x8a\x56\x93\x9a\x44\xd0\xaa\x80\xf2\x4b\x3d\x9f\x73\xe3\x25\x14\x5b\xfe\x65\x6a\x2d\x2a\x22\xc3\xee\xbe\xd3\xb3\x3f\x0c\x61\x0e\x75\xb8\x32\x96\x4f\xc9\x3e\x0d\xdf\x78\xf0\x79\x12\x8d\x40\xf1\xf9\x80\x79\x22\xfd\xc7\xae\xaa\x8a\x3d\x69\x34\x64\xf9\x4d\x80\x46\xd3\xb4\xa0\xa4\x39\xe4\x2f\x0a\x4a\x7d\x00\xd4\x7a\x91\x92\xbc\xa4\x4d\x7c\x28\x2e\x79\x36\xc0\x1a\xdf\x07\xaa\xb2\x40\x80\x6a\x44\x06\xb0\xac\x88\x4f\x55\x93\xff\xdc\x97\x14\x51\x36\x10\xb6\x0a\x00\x33\x2c\xce\x0a\x4a\xf9\x07\x5d\x4e\x3e\x18\x40\x0a\x1e\x50\x55\xb8\xda\x47\xc5\x6a\x49\x9e\x15\x44\xff\x1b\x50\x29\xc9\xf3\x9e\x34\xea\x4e\x20\x04\xd3\xbe\x43\x5a\x7d\x01\x3f\xa0\x0c\x24\xa4\x7f\x37\xc0\x0d\xb2\x43\x71\x4d\x8e\x1a\x15\xfe\x37\x28\x96\x17\x14\x15\x05\xf0\x49\x81\xa9\x2d\x0e\xf1\x9b\x17\x08\x57\x4c\x7f\x4f\xd9\xdc\xe4\xb8\x5e\x85\x4d\xcd\x34\x94\x30\x48\xe5\xdc\xba\x32\x10\x09\x51\x15\x54\x07\x86\xde\x0e\xe8\x60\xad\x1f\xad\xee\xb2\xbb\xc7\xea\x0f\x63\xb3\xbb\x17\x06\x7b\x41\xfa\xa4\xa6\x2c\x36\xd9\x81\x23\xd3\xf6\xce\xbd\x6e\xda\xf4\x2b\x1e\xf1\xb0\xb8\x57\x3b\x5c\xfa\x8b\xdd\xf0\xa2\x5b\xf4\x4f\xf9\xb9\xae\x9a\x8e\x94\x9d\x06\xad\x62\x52\x02\x98\xfd\x6d\xc3\x9e\x72\x71\xbd\x40\xdb\x19\x42\x00\xdb\x93\xd8\xff\xd3\x1b\x83\x40\xe6\x25\xdb\x6d\x90\x2f\x73\x5b\x3b\x0f\xea\x94\x55\x3f\x7f\xab\xfa\xfb\xc9\x6b\x17\x25\x9f\x93\x88\x00\x5f\xc2\x38\xba\x60\x4d\xf9\xb8\x9b\x84\x1e\x78\x00\x71\x51\xce\x47\x50\xb3\xc9\xe1\x90\xbf\x60\xf7\x40\xa4\xb3\xf1\xed\x37\xf1\xb9\x8d\x9f\x73\xfa\xb5\xc7\x84\x3e\x5e\x46\x9f\xf3\x94\x72\xbf\x43\x92\x13\x92\x89\x8b\xe3\x24\x52\x7f\x9c\x33\xf0\x47\x7b\x06\x7f\xbc\xb4\x41\x4c\x0e\x54\xb9\xd2\x01\x0a\xc5\x31\xe6\x2e\x37\xf6\x4d\x40\xf7\x7a\x3e\xf0\x62\x91\x38\x67\x36\x09\xf5\x0d\x21\xd1\x9e\x2d\x12\xed\xd9\x26\xa1\xbe\x21\x24\x5e\x5a\x8b\xc4\x4b\x6b\x93\x50\xdf\xb0\xb1\x86\xcb\x6a\x38\x36\x2f\xcf\xbe\x45\xbb\xcd\x7a\xa3\x7c\x42\x43\xf2\x3e\x6d\x67\xae\x03\x33\xb1\x6e\x2c\x56\x2c\x41\x9b\x11\xb8\xb8\xa9\xbe\x22\x35\x64\x00\x6d\x12\x75\xa7\x31\x2a\x29\x2d\x0a\x8b\xcc\x95\x8d\x07\x02\x1d\x13\xc1\xb5\x94\x79\x8f\x19\xa4\xc5\xc7\xfb\xd0\x46\x99\xd7\x8a\x46\xea\x31\xaf\x92\xf0\x35\x84\x3a\x2c\xb9\xdd\xce\xac\xca\xe5\x6d\x8d\xeb\xf4\xc5\xc2\x72\xe8\x0b\x0e\x37\xaa\x2f\xbd\x2d\x01\xfa\xe2\xa0\x12\xa2\x2f\x37\x49\xe4\x76\x25\xba\xad\xba\x37\x68\xd6\x5b\x2a\xbc\xa3\xba\xf1\x0b\x3c\x46\xe5\xb3\xd9\x76\x6b\xd5\x7e\xce\x6e\xd1\x37\x0b\xcb\xa1\x6f\x38\xdc\xa8\xbe\xf5\x13\x19\xd0\x37\x07\x95\xeb\xf4\xed\x1a\x91\xdc\x43\xe1\xae\xaa\xef\x2e\x1a\x77\x43\x8d\x77\x54\xb9\x19\xbb\xc7\x63\x54\x24\xaf\x8d\x5d\xa7\x5d\x16\x96\x43\xbb\x70\xb8\x51\xed\xea\x7d\x26\xa0\x5d\x0e\x2a\xd7\x69\x97\xa3\xf5\xf7\x50\x24\x17\xe9\xbb\xe8\x8c\x9f\xf8\x9b\xd5\x03\x9f\x68\xb9\xdb\x6c\xbb\x1d\x96\xa7\xf5\x36\x03\x2b\xaa\xb1\x66\xab\xeb\xaa\x19\x1f\x55\xa2\x1e\xcb\x4a\x5d\x57\x8f\xd6\x13\x82\xa4\xa5\x9a\x6e\x92\xaa\xf3\xea\x26\x17\x07\xc8\xc3\x3c\xd8\x01\x1e\x21\x71\xe5\xc0\xc5\x10\x1d\x63\xd7\x09\x3a\x3a\x7c\x19\xa6\x36\x82\xdd\xb4\xdc\x83\x58\x47\xbe\xda\xef\x77\x49\xed\xda\x01\x6f\x60\x83\x31\xfd\x46\x3e\xae\xb6\x0e\x28\xfe\xfd\xe4\x72\x0f\x83\x02\x88\x8b\x01\x82\xf5\x3c\x3e\x46\xfe\x4f\x00\x00\x00\xff\xff\x47\x37\xb0\x07\xc9\x28\x02\x00") - -func assetsCssBootstrapMinCssBytes() ([]byte, error) { - return bindataRead( - _assetsCssBootstrapMinCss, - "assets/css/bootstrap.min.css", - ) -} - -func assetsCssBootstrapMinCss() (*asset, error) { - bytes, err := assetsCssBootstrapMinCssBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "assets/css/bootstrap.min.css", size: 141513, mode: os.FileMode(511), modTime: time.Unix(1499700236, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _assetsFaviconIco = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00") - -func assetsFaviconIcoBytes() ([]byte, error) { - return bindataRead( - _assetsFaviconIco, - "assets/favicon.ico", - ) -} - -func assetsFaviconIco() (*asset, error) { - bytes, err := assetsFaviconIcoBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "assets/favicon.ico", size: 15086, mode: os.FileMode(511), modTime: time.Unix(1496572980, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _assetsJsJquery211Js = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xfd\x7b\x77\xdb\x46\x96\x28\x8a\xff\x2d\xaf\xe5\xef\x50\xa2\x73\x64\xd0\xe2\x43\xb2\x93\x74\x42\x99\xd6\xcf\xb1\x9d\x1e\x9d\x5f\xec\xb8\x23\x67\x32\xf7\x4a\xca\xa4\x48\x14\xc5\xb2\x41\x80\x41\x81\x92\xd8\xa1\xfa\xb3\xdf\xb5\x1f\xf5\x02\x40\xd9\xee\x4e\xcf\x39\x3d\x6b\x62\x11\x28\xd4\x63\xd7\xae\x5d\xfb\xbd\x87\x8f\x76\xef\xdf\x13\x8f\xc4\xfb\xbf\xad\x54\xb9\x16\xff\x5b\x5e\xc9\xd3\x69\xa9\x97\x95\xf8\x41\x4f\x4a\x59\xae\xc5\xd5\xe3\xc1\xe1\xe0\x10\x1b\xcd\xab\x6a\x39\x1a\x0e\xdf\xff\x0e\x6d\x07\xd3\x62\x31\x84\xc7\xf8\xea\x24\x9f\x66\xab\x54\x19\x71\xaa\xff\xfe\xf7\x4c\x0d\xde\x9b\xf0\x0b\x83\x0f\xdf\x9b\xf8\x9b\x17\xc5\x72\x5d\xea\xcb\x79\x25\x1e\x1f\x1c\x7c\xd5\x13\x8f\x0f\x0e\xbf\xb4\x13\xf9\xbe\x58\xe5\xa9\xac\x74\x91\xf7\xa0\xef\x81\x90\x79\x2a\x8a\x6a\xae\x4a\x31\x2d\xf2\xaa\xd4\x93\x55\x55\x94\x34\xc8\x4f\x2a\x53\xd2\xa8\x54\xac\xf2\x54\x95\xa2\x9a\x2b\xf1\xfa\xe4\x9d\xc8\xf4\x54\xe5\x46\xb5\xcc\xbc\x28\x2f\x87\xc1\x5b\x6c\xf1\x52\x56\x6a\x84\x53\xe8\x1f\x7c\xd5\x3f\x38\x7c\x77\xf8\x97\xd1\xe1\xe1\xff\x0b\xef\x86\xf7\xef\xdd\xbf\x97\xcc\x56\xf9\x14\xe6\x93\x88\xcb\xac\x98\xc8\xac\x27\x66\x72\x5a\x15\xe5\x5a\x74\xc5\x1f\xd0\x62\x47\xcf\x44\x22\xaa\xf5\x52\x15\x33\xb1\x28\xd2\x55\xa6\xc4\x78\x3c\x16\x9d\x62\xf2\x5e\x4d\xab\x8e\xd8\xdb\x8b\xdf\x0e\xd4\xcd\xb2\x28\x2b\x13\xb7\xc2\xde\x76\x76\x86\x43\xf1\x7d\x51\x8a\x17\xc5\x62\x51\xe4\xff\xfb\x14\xd7\x6f\x7f\xf4\x33\xfd\x41\x09\x95\x5f\xe9\xb2\xc8\x17\x2a\xaf\x8c\xb8\x9e\xab\x52\x09\x29\x96\x65\xb1\x54\xa5\xb8\xd6\x79\x5a\x5c\x0b\x6d\xc4\xb2\x54\x46\xe5\x55\x8f\xfb\x54\x37\x6a\xba\xaa\x14\x02\xc9\xce\x1f\xba\xbe\x54\x15\x83\x3e\x18\x3c\x1a\xa1\x9a\xcb\x4a\xa4\x85\xc8\x8b\x4a\xe8\x1c\x86\xcb\xab\x6c\x2d\x96\x85\x31\xca\x08\x69\x87\xbc\xd6\xd5\x5c\x48\x91\x16\xd3\x15\x7c\xc7\xbd\x25\x66\x35\x9d\x0b\x69\xc4\x9b\x22\x05\xe4\xe8\xf6\x04\x2c\xde\xc0\x94\x69\xd8\xfe\x42\x7e\xd0\xf9\xa5\x9f\x94\xa9\x41\x89\x7b\x7a\x37\xd7\x46\xc8\xe9\x54\xe5\xd5\x4a\x56\xca\xe0\x4a\x72\xa5\x52\x31\x2b\x68\xef\xa7\xa5\x42\xc4\x11\xc5\x4c\x48\x51\x2a\x99\xf1\xdc\x2c\x08\x06\x97\x03\x71\x25\x4b\x8b\x6a\x63\x51\xaa\xdf\x57\xba\x54\x49\x87\xf0\xa3\xd3\x4d\xe8\x83\xee\x11\x7f\x72\xaa\x94\xa8\xf4\xf4\x83\xaa\xc4\x83\xc3\x2f\xbf\xfa\xf2\x5b\x1c\x6c\x51\x94\x4a\xe8\x7c\x56\x40\xab\xfa\x96\x32\x96\x0c\x2c\x20\xc4\x31\xb4\xda\xe1\xe5\x79\x24\xaa\xca\x95\x12\x5d\x31\xa2\xb7\x0e\xc7\xae\x2d\x1e\xec\x10\x5a\xed\x5e\xfb\x9e\xdc\x9b\x9d\x6a\x5e\x16\xd7\x22\x57\xd7\xe2\x55\x59\x16\x65\x22\x3a\xbc\x26\x5e\xd1\xf6\x7d\xe9\x08\x5a\xdc\xce\xce\x2d\xfd\x53\xaa\x6a\x55\xe6\xc2\xcd\xef\xda\x36\xb8\x85\x7f\x6e\x85\xca\x8c\xa2\x71\x6b\x4b\xa0\x76\xb7\x70\x02\x86\x43\xf1\x56\x1a\xd8\x12\x6d\x84\x9e\x05\x58\x08\x48\x93\xaa\x99\xce\x55\x2a\xd6\xaa\xba\x7f\xef\x36\xe1\xa3\xc0\x6d\x76\xe1\x08\xc0\xf9\xc5\x36\x1d\x71\x6c\x5f\x8c\xb0\xb7\x9e\x08\x40\x83\x2f\x7a\x22\x2f\xfe\xca\x13\xa0\xf3\x37\x1c\x8a\x17\x32\x7f\x88\x48\x8a\x33\x98\xa8\xa9\x5c\x19\x25\x8c\xba\x52\xa5\xcc\x84\x5c\x2e\x8d\xd0\x48\xa8\x00\xd3\x9e\x9f\xbe\x1d\xbc\x79\xf5\x4e\x54\xa5\x9c\x2a\xfc\x1c\xb0\xc7\x54\x72\xfa\x41\x5c\x69\x29\x64\x79\x89\xa0\x32\x83\xa9\xcc\x32\x55\xd2\x3f\x0a\x8f\xcb\xf7\xba\x54\xb3\xe2\x46\xa4\x5a\xc1\x4a\xf1\xeb\x75\xb1\x12\x55\xb9\x16\x55\x41\x5d\x0a\xd8\x9d\xd5\xe5\x5c\x74\x70\x12\x55\xa9\xe1\x78\x43\x27\x62\x3a\x97\x3a\x37\x03\x91\x3c\x38\x7c\xf2\xe4\xc9\x57\x5d\xfc\xfe\x74\xb5\x04\xdc\x19\xb9\xce\x0f\xbf\xd9\x87\x17\xb0\x36\x40\x57\x59\x96\x62\x2c\xce\x2e\x8e\xec\x03\x03\x34\x4c\x8c\xe1\xc5\x00\xff\x76\x6f\xa6\x45\x3e\x95\x15\xbf\xa2\x1f\xee\xdd\x72\x65\xe6\xfc\x06\xfe\x74\xcf\x75\x9e\xaa\x9b\x1f\x67\xfc\x8a\x7f\xf9\x1e\x33\x69\xcc\x63\xd8\x33\x31\x16\x7f\xdc\xba\xe7\x55\x71\x5a\x95\x00\xcd\x71\xd0\x64\x60\x9f\xba\x66\x73\x69\x7e\xbc\xce\xe3\x46\xf4\xec\x2d\x12\xac\x6a\xed\x57\x45\x60\xf0\xc3\xf0\x8b\xfb\xf7\xe0\x24\xfe\x6c\x88\x76\x4d\x8b\xb2\x54\xd3\xca\xe1\x33\x90\x84\xa2\x84\x7d\xcd\xd6\x84\xeb\x8c\x3f\x76\x17\x45\x62\x64\x9e\x4e\x8a\x9b\xee\xfd\x7b\x3b\xee\xab\x31\x37\x73\x87\xab\x87\x94\xfc\x4a\x95\x06\x28\xc8\x58\x74\xf0\xf6\xeb\xd0\xe3\xe1\x50\xbc\x44\x04\x15\x52\x64\xc5\x54\x66\x62\x5a\x2c\xd7\x40\x67\x1c\xe9\x74\x34\xc5\xe3\xab\x51\x99\x82\x13\xd3\xc3\x9b\x4b\xdd\x54\x01\x89\x7f\x37\x57\x96\x0c\x11\xfd\x17\x48\xdd\xaa\x95\xcc\xb2\xb5\x78\xbf\x32\x15\xae\x56\xe7\xba\x82\xaf\x4d\x55\xae\xa0\x2b\xf1\x50\xe5\x73\x99\x4f\x55\xfa\x90\x3b\x7a\x03\x14\x10\x9b\x69\x3b\x1b\xe8\x0a\x51\x36\x15\x09\xf6\x24\xb3\xac\xb8\x16\x0a\x28\x05\x20\xe9\x84\x30\xf4\x3a\x87\x4f\x88\xaa\xe3\x1d\x9e\x02\x84\x2c\x3d\x00\xda\x42\xdd\x0d\x66\xf9\x00\x06\x68\x5d\x10\x92\x00\x07\x24\x87\xc9\xcf\xf3\xb4\x2c\x74\xfa\xf4\x4b\x60\x20\xe0\xcd\x6b\xf9\x41\x09\xb3\x2a\x95\xb8\x56\xa2\x2a\xf5\x42\x7c\xf7\xe3\x6b\x3c\x51\x6f\xbe\x3b\x7d\x7b\xff\xde\x4e\x89\x0f\xc7\x62\xf8\xeb\xd9\xb9\x39\x5f\x7d\xff\xea\xfb\xef\xcf\x6f\x9e\x1f\x5c\xec\x6f\x6a\xbf\xbf\x18\x5e\xba\xf1\x5e\xcb\x6a\x3a\x57\x46\xa4\xd2\xcc\x55\x8a\x47\x0d\x6e\x92\xa2\x14\x53\xb9\x50\x99\xfe\xbb\xce\x2f\xa1\xef\x85\x79\x5b\xaa\x99\xbe\xc1\xfe\xfb\x0b\xd3\x1f\xc2\xb5\x58\xc2\x67\xcf\xb3\xe5\x5c\xc2\xf3\x7e\x72\x76\x9e\xca\xfe\xdf\x2f\xba\xc3\x4b\xed\x46\xf8\x19\xd8\x8b\xc9\xda\x82\x02\xbb\x7d\x21\xe1\xfa\x22\x18\x4f\x80\x68\x54\x85\x28\xd5\x32\x93\x53\x95\x00\x08\x67\xbe\x55\x88\x0e\x32\xcb\x7a\x22\x53\x55\xa5\x4a\x8b\x08\x0c\x6b\x7a\x38\xa8\x8a\x9f\x97\x4b\x55\xc2\x87\x09\x01\x16\x8f\x81\xdb\x05\x31\xb6\xd3\x58\x96\x45\x55\xd8\x33\x49\x13\x05\x84\x9a\xae\x4a\xb8\x9c\x85\xc5\x62\x87\x9f\x62\xa2\x00\x30\x2b\xa3\x52\x40\x55\xbc\xec\x46\xb6\x19\xad\x35\x40\xb2\x11\x7f\xe5\xb7\xb5\x92\x65\xc5\x17\x49\x2e\xd4\x62\x59\xad\x1d\x2e\xdc\xbf\xb7\x63\xff\x1c\x89\x8e\x3f\x2f\x30\x9f\x54\xcd\xe4\x2a\xab\x44\xa6\xf2\xcb\x6a\x4e\xd7\x72\x03\xe9\x0f\xee\xdf\xdb\xa1\x06\x23\x71\x40\x9f\x57\xc5\xf3\xb2\x94\xeb\x91\x07\x5e\x0c\x2f\xa4\x79\x48\x95\x13\x22\xf8\x35\x34\xfc\xab\xa2\xd3\xf3\xa6\x9a\x0b\x95\x29\x3c\xf0\x3a\xc7\x47\x0b\xc4\x98\xd4\x3d\x36\xaa\x12\x3f\xfe\x14\x7f\x76\x3d\x2f\xb2\xf6\x96\x12\xee\xd5\x69\xa6\x64\x0e\xb4\x52\xc2\xb9\xbf\x54\x55\x30\x4f\x91\xaf\x16\xb5\xcd\x85\x27\xbb\x63\x91\xaf\xb2\x0c\x58\x01\xbc\x5a\x87\x43\xf1\x13\xbd\x75\x27\xbd\xc8\x95\x1b\x6a\x56\x16\x0b\xba\x93\x14\xf2\x51\x3b\xd4\xef\x53\x71\x20\x8e\x71\xc1\x67\xf8\x7b\x1f\xff\x1e\x30\x74\x2f\xf8\xc6\xa4\x77\x17\xc4\x5a\xd4\x46\x83\x2b\x08\xfa\xe5\x81\xe0\x52\x6c\x2c\x68\x67\xe7\x63\xe0\x7d\x07\x67\xd9\x7e\x01\xbb\xea\xba\x83\xf3\x8c\xd7\x8c\xae\x44\x91\xc3\x7d\x68\x2f\x56\xfa\x32\x21\x98\x00\x2e\x12\xf7\x76\xdd\x06\x66\x38\x43\xd0\xcb\x29\x7c\x18\x02\x17\xda\x18\xc7\x75\x43\x87\xdf\xad\x74\x96\x0a\x19\x50\xab\xb6\x0e\xa1\x31\xdc\x30\xa5\xaa\xfc\x19\x5a\xa8\xf2\x52\xd1\x02\x07\x01\xf2\x27\xc0\xa1\xd2\x38\x47\x6e\x98\xe7\x69\x4a\x9b\x94\xa5\x16\x73\xe3\xe5\x89\x04\x51\xa3\x54\x33\x60\x8f\xa7\xca\x52\xd2\xc1\xb2\x54\x57\x3f\xd2\x17\x63\x1c\xeb\xc8\xbe\xb1\x24\x74\xec\xa6\x00\x3f\xfd\x98\xbc\x65\x0c\xa7\x6c\xdd\x9f\x15\xe5\xa2\xb9\x2e\xc6\xb2\x52\x55\xf1\x26\xbd\x62\x7e\x5f\x7a\x32\x05\x74\x11\x38\xa2\xf5\xb6\x43\x61\x54\x35\xe0\x8d\xfa\x7f\x8a\x95\x98\xca\x5c\x18\xb8\x5e\xa0\x8d\x63\x8a\x1c\x1d\x70\xdb\x2f\xcb\x4b\xd3\x13\x93\x55\xc5\xfc\x9f\xa1\x3e\x8a\x3c\x5b\x23\xc9\x11\x3a\xaf\x54\x99\xc3\xcd\x36\x00\xc0\x28\x39\x9d\x87\xdb\x6a\x27\xd8\xc3\x9e\x6a\xc7\x87\x77\x0b\xbe\x49\x98\x23\xac\xb7\x0f\x16\xbe\x90\xcb\xb6\x9e\x6b\x7d\x22\xc0\x1d\x86\x25\x0e\x23\xe4\x32\xa9\xf3\x9c\x00\xa9\x9e\xd0\x8e\xf5\xe6\x1e\x6c\xc7\x7c\x4a\xb8\x15\x61\x0e\xf3\xcf\xb7\xdd\x70\x62\x78\xa6\xb6\x12\xb4\xfa\x84\xe8\x04\xca\xe5\x32\x5b\xdb\x45\x7b\xf8\x77\xa3\x15\xcf\x74\x69\xaa\xbb\x3b\x56\xbf\x27\xe2\x20\xfa\x28\x93\x9f\xf2\x4d\xff\x30\xfa\x48\xfd\x1e\x82\xd6\x81\x04\x0e\x56\xa6\x72\x8b\xc7\x44\x8d\x50\xea\xdc\x79\x2f\xc6\x62\x5f\x8b\x7d\x01\xcd\x89\x7a\x41\xcb\x91\x9d\xcd\xd6\xfd\x10\xcf\xc6\xe2\x00\xc4\xe6\xf7\xe2\x29\x7e\x72\x2c\xce\x88\xb8\xbd\xbf\x40\x42\x77\x76\x11\x4f\x2d\x4f\x3f\x02\x5b\x7f\x0c\x37\x9b\xe6\x99\x07\xe2\x5c\x23\x72\x20\x06\x5b\xbc\x05\x2c\x46\x74\xe6\xd3\xf1\x9d\x9a\xcb\x2b\x65\x04\x4a\xe3\x32\x17\x78\x5b\x3d\x34\x62\xa1\xaa\x79\x91\xf6\x90\xa7\xa2\x77\x8e\x28\xe1\x9b\x01\x13\xb6\x11\x12\x49\x80\x91\x41\x6e\x09\xf9\xf8\xa2\x44\x59\xdd\x2c\x09\x53\xf0\x19\xfe\x7d\xff\x5e\xc4\x07\xa8\x9b\x4a\xe5\xa9\xa7\x63\xb3\xdc\x3f\xaa\x81\x00\xb6\xa6\x58\xc2\x03\xd3\x13\xb9\x5c\xa8\x9e\x30\xe5\xb4\x87\xcc\x2b\xfd\xf7\xc4\xe0\xdc\x7b\x62\x9a\x15\xb9\xc2\x5d\xab\x64\x79\xa9\x48\x84\x60\x8c\x3b\x3b\xb8\x00\xa8\xfd\x71\x8b\xef\xb5\x18\x8b\x43\xfc\x8b\x2f\x9e\xa0\x65\xb8\xfb\xa9\x52\x4b\x98\x92\xcc\x0c\xc9\x27\x00\xb9\xff\x90\x79\x9a\x01\x5c\xf0\x2d\x32\xd1\x46\x83\x3c\xaf\x8b\xbc\xa6\x48\xb1\xf3\x00\xf9\x70\x52\x14\x70\x47\x39\x1d\x09\xf7\x4d\x4d\x3c\xc9\x34\x1f\xf4\x12\x89\x15\xb7\xc7\xfb\x08\x7e\x53\xc3\x2d\xab\x13\x5a\xf0\xfa\x10\x27\xf5\xfe\xbe\x93\x6b\x83\x29\x4f\x81\x9d\xbb\x9e\xab\xdc\x4e\x0c\xf8\x75\xcb\x71\x16\xa5\x30\x05\xec\x31\xfc\x48\x96\x85\x31\x7a\x92\x01\xf7\xee\xd7\xd9\x6d\x5f\xde\x6e\x4d\x4f\xb4\xcb\xbb\xaa\xcd\xf7\x76\x2f\xa9\x65\xd7\xae\xdd\xad\x80\xe6\xeb\xe6\xc9\x48\x60\x45\x80\xca\xa8\x6c\x06\x0c\x3e\x92\x61\xe0\x2e\x9c\x40\xa4\x8d\x58\x4a\x43\xbc\x20\x4e\x49\x23\x94\x79\x3b\xeb\xc3\xb8\x4b\x4b\xf7\xfb\x7e\x40\xb8\x4b\x12\x71\x84\xe7\x9a\x3e\x3c\x12\x7a\x7f\x3f\x90\x70\x7e\x84\x71\x53\x52\xc2\x54\x73\x91\x17\x79\x1f\x8e\xd9\xd0\xc9\xfa\xe2\x4a\x66\x2b\x85\xea\x1d\x9c\x45\xc2\xa8\xda\xd8\x9c\xae\xe3\x9f\x2c\x15\xc6\xfb\x0d\x97\x8b\xbb\x0d\x5b\x43\x30\x24\x65\x0a\xce\x0d\xf0\x1d\x76\xc0\xf6\xea\x94\x27\xa6\x9c\x3a\xdc\x39\xa3\x66\x17\xac\x12\x41\x84\x1c\xdb\x4f\x82\x97\xf4\x7a\x38\x14\x6f\x4b\x75\x05\x30\xcc\xe1\x22\xed\xab\x1c\x15\x0a\x59\x51\x2c\x03\x95\x4d\x80\xb9\xd8\xa1\x57\xdb\xc0\x25\xaf\xf3\x95\xf2\x1a\x18\xd7\xf1\x4f\x6a\xba\x2a\x8d\x42\xed\x89\x7a\x58\x2a\x01\xfc\x09\x74\xbe\xcc\x24\xac\x02\x97\x67\x00\xd3\xf0\xde\x35\xc1\x78\x88\x63\x7b\x7b\x34\xd8\xde\x9e\x70\x17\x9a\x36\x6f\xe1\x63\x22\x7c\x09\x62\x21\x20\x7a\x12\x9c\x7c\x4f\x47\x34\x3d\xa0\x66\x80\x6d\x7e\xda\x38\x4a\xf8\x91\x7f\xb5\x13\xf7\x65\x4f\x3b\xbf\x03\xa2\x22\xc6\x40\x74\x90\x98\xc7\x03\x99\x72\xda\x15\xc7\xf8\x72\x64\xb5\x1b\xf8\x59\xa8\x73\xba\xab\x9b\x70\x71\x51\x67\x7c\x92\x43\x08\x93\xa8\x7c\xa5\x4a\xb1\x28\xae\x94\x28\x4a\x7d\xa9\x81\xb2\x33\x5c\x99\x00\x02\x3a\x2d\xac\x8a\x2d\x42\x10\x0f\x27\x3a\x67\x04\x75\x4b\x37\x79\x9f\x43\x44\x79\x59\xe4\x0f\x2b\x31\x41\xf2\xa0\x73\xd1\x86\xf5\x6e\xa5\x0e\xbe\x48\x0e\x7c\xd3\x40\xdf\x57\x9f\x0c\xb4\x8e\xf4\x78\xf8\xdf\xdb\x90\x20\x04\x0c\xe4\xa2\x48\xf5\x4c\xab\xd4\x9f\x12\x7b\x39\x5a\x0a\xda\x72\xc5\x24\x2c\x59\xfe\x9c\xeb\xdf\x57\x8a\xb8\x47\x39\x9d\xd7\x54\x1f\xa2\xa0\x21\x96\xf2\x52\xc1\x4d\x7c\xb3\x94\x79\x5a\x8c\xac\x42\xb2\x83\xb7\xbf\x15\x48\xf7\x41\x62\x9f\x0f\x4a\x68\xb2\x48\xba\xa2\x3b\xb0\x72\xb3\x18\x9e\xbf\x1c\x5e\xf6\x44\xa7\x23\xba\xee\x0e\x7e\x6e\xcc\x6a\xa1\x02\xad\x46\xa9\x64\x4a\x5a\x9e\x62\x45\x62\x13\x3d\x21\x1d\x2c\x90\x33\xf3\x13\x3c\x18\xa1\x76\x95\x79\x83\xb2\x04\xd1\xd4\x73\x2e\x0b\x73\xe9\x88\x5c\x5d\x8d\x8a\xef\x02\x46\x20\x2f\x8a\x65\xcc\x59\x04\xca\x0e\xa5\x44\xa5\x4c\x35\x5c\xe5\xba\x1a\x4e\x8b\x52\x0d\xde\x1b\x04\x53\xaa\x2a\xa9\x33\x83\xda\x38\x45\xe2\x8e\xa7\xe7\xcc\x43\x9c\xea\x7c\xaa\x1c\x60\x0e\x07\x4f\x7a\xe2\xe5\x8f\xaf\x99\x51\x20\x49\xca\x0e\x6b\x19\x8d\x4c\x95\x15\x7d\x2c\x4b\x05\xd8\xc5\x1a\x33\x95\x0e\x40\xdc\x5e\x0b\xa7\xca\xcd\x90\x5f\x11\x27\xaf\x44\xf2\xe0\xf1\xb7\x5f\x7f\xd3\x1d\x20\x6c\xec\x14\x42\x68\x14\x93\xf7\xed\x1c\x37\xdc\x53\x49\x31\x79\xdf\xa5\x2b\xd8\x7e\xd1\x09\xa0\xc3\x27\x79\x44\x0c\x90\x3d\xd8\xf6\xdd\x2f\xa8\x60\xbb\x7b\x2c\x78\x62\x89\xfb\xde\x1e\xfe\x84\xd1\x8a\xc9\xfb\x01\xe9\xe7\xa2\xd1\xde\xac\x16\xaa\xd4\xd3\x2d\x5d\x0e\x87\x62\x29\x4b\xa3\xbe\xcf\x0a\x59\x89\x37\xf2\x8d\x01\x49\x18\x3e\xe8\x4f\xa5\xa9\x18\x2c\xcb\xc2\xe8\x4a\x03\xf7\x86\x5c\xdf\x06\x10\x65\x83\xaf\x36\x9d\x4e\x97\xfb\x19\x0c\x06\x20\xce\x2c\xb4\x41\x16\x70\x59\xaa\xca\x88\x4c\x49\xa0\xf6\xfd\x7c\xb5\x98\xa8\x92\xaf\x7e\xd3\x83\x41\x2b\x3d\x5d\x65\xb2\xcc\xd6\x62\xae\x6e\x44\xa6\x2b\x55\xca\xcc\x88\xa4\x73\x70\x33\x18\x0c\x5c\xb7\x66\x35\xa9\x4a\x89\x33\x07\x3c\x99\x2a\x10\xc0\x67\x3a\xd7\x95\x56\x46\x54\x05\x4c\x3a\x00\xce\x6e\x8d\x60\xf2\x62\x19\x4e\xfd\x60\xb5\xf6\x15\xb0\xcd\x11\xc4\x02\x12\xb9\x1d\x6a\x6f\x8a\x2a\xbe\x65\x46\xfc\xa2\x2f\x9e\xe7\x4e\x55\x53\x94\x44\xba\xc4\xf5\xbc\x00\x9a\x65\x79\xe3\xb3\xb3\x17\x99\x34\xe6\xe2\x82\x4d\x50\xd5\xda\xea\xfd\x3b\x67\xfc\x29\x4d\xe0\xa2\xe3\xba\x05\x4c\xcf\x8b\x54\x19\xf7\xc4\x1b\x6a\x90\x18\x86\x38\xc8\xb3\x8d\x38\xa5\xcd\x06\x71\x04\xfa\x78\xb7\x5e\x2a\xf8\xed\x80\x45\x78\x67\x3f\xab\x09\x6e\xfe\x82\xe2\xab\x01\x87\x83\xbe\x42\x2d\xeb\xde\x1e\x91\xd6\x5d\x52\x55\xb3\x94\x57\x6b\xe5\xb5\x70\x3d\xd1\xd1\xe6\xad\xfd\xf5\xe3\xac\xf3\x09\xe3\x0e\x87\xe2\x64\x46\xd6\x38\xde\x16\x31\x97\x06\x4e\x35\x7d\xa1\x52\x21\x33\xa4\x6e\x3d\x66\x08\xa6\x45\x3e\xd3\x29\x30\x1f\xd5\x5c\x5a\xfb\xda\xa6\x98\xbc\xdf\x10\x2f\x1a\x6e\x61\x8f\x8c\x61\xa4\xbb\xfc\xe3\x16\x36\xcf\xcd\x5c\xa5\xcc\x91\xa9\x6b\xde\x99\x50\x5a\x2a\x89\x3b\x71\x18\xf4\x6a\xb1\xac\xd6\x77\x62\x10\x48\x19\x70\x2f\xe1\xea\x6a\xbc\x97\x6f\xd5\x0a\x88\x6d\xc3\x02\x18\xb7\x8c\x66\xf7\x4b\x8c\x6b\x3c\x61\x40\x51\xf6\x45\xa7\xe3\x87\x68\xd1\x4b\x8b\xa7\xe2\xcb\xc1\x41\x4f\xe8\x1f\x4f\xc5\x53\xf1\xb5\x70\x36\x5e\x6d\xe6\xe2\x27\x75\xf9\xea\x66\x19\xea\xc2\x99\x65\xb7\xd4\x29\xc4\xc2\xfa\x2b\x47\x26\xd9\xec\xe7\xcd\x1e\x67\xce\x64\x42\xe8\x84\xa4\x15\x05\x0f\xd7\x1f\xd9\x02\x7d\x97\x35\x8d\x0e\x1c\x3f\xb4\x7c\x4a\x61\xc8\x54\x8f\xea\x3b\xb6\xc6\xb1\x02\xe9\xfe\xbd\x1d\x7a\x00\xcd\x23\x5d\x48\x91\xaa\x70\xcb\xa8\x0b\x12\xd4\x75\x9e\xea\x92\x74\x54\xea\x4a\x66\xcc\xc7\xe0\x17\x8e\xef\xa9\x4a\xbd\xb0\xbd\x1c\x05\x67\x27\xec\x37\xc0\x6a\x7c\xac\xad\x73\x80\x04\xda\xa1\xd3\x1e\xd0\x88\xac\xb8\x5c\x59\x3a\x8c\x52\x1f\xd1\x46\x34\x93\xc1\x4d\xae\xc4\xb2\x94\x97\x0b\xd9\x73\x36\x6b\xec\x6b\xb2\x16\x3a\x07\x38\xc1\x75\x2a\xdd\x67\x04\x88\x4a\x02\x97\xc5\x1a\x39\x6b\xd2\x19\xd0\xda\xec\x24\xad\x69\x2b\x09\xcd\x72\x74\xbb\x1d\x06\xd2\x01\x75\x38\xf6\xbd\xd0\x49\x7a\x45\x2a\xb3\xa4\x43\x0d\x3a\xd6\x8a\x4a\x3f\x07\xac\xca\x83\x71\xf8\x85\xfb\x7e\xae\x64\x3a\x90\xcb\xa5\xca\xd3\x17\x73\x9d\xa5\x89\x9d\x74\x77\xb0\x84\x8b\xbc\x42\xd3\x78\xa9\x80\x31\xad\x35\x60\x43\x6c\xc8\x0f\x83\x64\x55\xcd\x55\x79\xad\x8d\xea\x09\x79\x05\xd8\x0c\x8b\xb6\x24\xd5\x59\xc1\x7b\x42\xe7\x46\x95\x21\x8c\x81\xa9\xc0\x71\x64\x06\xe0\x5c\x19\x04\x65\x2e\xdc\xf6\x33\x2a\x01\x0e\xb0\x7c\xc1\x6f\x82\x8d\x8f\x78\x4d\x87\x9c\x2f\x8a\xfc\x4a\x95\x95\xb5\xc4\x54\x85\x70\x46\x90\x23\x52\x02\x4e\xd6\x84\x17\x86\x98\x9b\x54\x56\x92\xf9\x36\xd6\x17\xbe\xd6\xd3\xb2\x30\xc5\xac\x82\xbb\xf1\xb2\xa8\xa0\x93\xf9\x6a\x81\x12\xbd\x2e\xc5\x95\xca\xd3\xa2\x14\x4b\x32\xe4\x24\x0f\xbe\xfd\xea\x2f\x8f\xe1\x90\xba\x71\x42\x64\x67\xb9\xbc\x66\x36\xa0\xd3\xe7\x58\x4e\x67\x16\xea\x89\xce\xc2\xf4\x3b\x21\x3b\xea\x6d\x43\x3d\x11\xd8\x73\x62\xde\x30\x55\x6f\xe4\x42\xd5\x35\xd4\xa4\x6a\xa9\x8d\x0d\x2f\x06\xf6\x0b\xb8\xc2\xa3\x07\x83\xaa\xf8\xa1\xb8\xb6\xa6\x1f\x44\xc9\xbc\xf1\x38\xa6\x06\xa8\xfa\xd4\xc4\x6f\x06\x7a\x2a\x79\x49\x9a\xaa\x16\x35\x6b\x31\x79\xdf\xd4\x9d\x7a\x7a\x80\x97\x3b\x93\x03\x31\x46\x53\xcc\x4e\xa0\xe3\x81\xcb\x2f\xd4\xed\x69\x27\xf3\xf1\x5f\xc0\xa3\x32\xa5\x0e\xc9\x43\x38\x0c\x6b\x1b\xea\x42\xe4\x47\x74\x09\x3b\x30\x3f\x60\x3c\xc6\x5e\xed\xca\xaa\xd1\x62\xf2\x1e\x35\x04\x81\x26\x38\x14\x59\xf9\xb3\x31\xcb\xa5\xa1\xd8\x3a\x29\x95\xfc\x10\x48\x89\x81\x20\x15\x49\x9f\x34\x37\x5d\xbf\xcc\xfe\x87\xa7\xe4\x0d\x11\xc2\x2c\xd5\x54\x93\x13\x92\x81\x6b\x1e\xb0\xd2\x3a\xc0\x2c\x0a\x53\x89\x29\xfa\x0a\x91\xca\x72\x86\x12\x1b\x9e\xd6\x70\x55\x7f\xda\x36\x38\xbe\x88\x97\xac\x7b\xee\xc7\xff\xd9\xcd\xf8\xf7\x4f\x2c\x60\xe5\x3c\xe7\xf1\x49\xd6\x70\xb8\x48\xc3\x73\x19\x7a\x06\x58\x86\x03\x6f\x13\x6f\x34\xdc\xd9\xd9\xe9\x58\xf6\x80\x3f\xd8\x47\x51\x39\x20\x58\xd0\x2d\xc9\xcf\xf1\x2c\x4a\x65\x56\x59\xf5\x11\x5a\xb1\x90\x1f\x54\xdd\xe6\x2a\x64\x59\xf6\xdc\xe7\x01\xa5\x20\x33\x9a\x7d\xb1\xd9\x78\xe5\x0d\x9f\xf8\xb2\xa1\xb0\x0b\x31\x8e\x08\x05\xeb\x6d\x64\x59\x46\xba\xa6\xd8\x38\x57\x2a\x66\x50\x1c\x57\x84\xbe\x30\xc0\x68\x11\x31\xb7\x6c\xd6\xce\xce\x19\xbe\xba\x10\xa8\x39\xa7\x67\x6d\xd7\x27\xea\xdf\x19\x3d\xa0\x77\xfc\xaa\x76\xad\xdd\xdf\x66\x56\xd3\x79\x03\x46\x44\xf0\x11\x52\xba\xb6\x89\x34\x55\xde\x43\xd1\x3f\x14\x23\xeb\x6a\xc3\xe3\xe3\x57\xce\xc0\x14\x5a\xb1\x60\xf5\xe1\x28\x68\xe4\xe9\x09\xa3\xa6\x45\x9e\x36\x0d\x2f\xfb\xf4\xa2\x61\x7b\x39\xf0\xe4\x1c\x7b\xe0\x06\xbc\x59\xf6\xbc\xb3\x8d\xe5\x48\xbc\x0f\x0e\x3b\xb6\x3f\xc3\xf3\x7f\x21\xc6\x3c\xf2\x99\x78\xcf\xaa\x52\x86\x52\xd8\x2b\xdc\x04\x47\x11\xf0\xf0\x6d\xb0\xac\xcb\x52\x2d\x1b\xe6\xdc\xf0\x4a\xd2\xc4\x43\x04\xeb\xb3\xef\x4e\xe0\x8d\xe1\xeb\x69\xc1\x5e\x1f\x63\x71\x76\xb1\xfd\xc2\xc2\xde\x23\x90\xd8\xce\x5e\xdd\x2c\x89\xd7\xdd\xa5\x01\xbd\x01\xe1\xaf\x85\xf3\xdd\x22\x9b\x27\xda\x46\x50\x83\x6e\xe4\x95\x35\x5b\xeb\x4a\x2d\xac\xe4\x8a\xce\x91\x4b\xf2\x7d\x53\xc4\xe4\x4a\x90\x20\xed\x2a\x43\x40\x6f\x23\xac\xb5\x45\xc2\xc4\xec\x23\x06\x92\xa5\x62\x16\x53\x89\xa7\xad\x7d\x06\x02\x72\x6d\x89\xee\x58\x31\xc8\xd0\xc8\x16\xf6\x79\x07\xea\xf3\x27\x0d\xae\xe3\x63\x84\xe4\xee\x2d\x86\x0e\x3e\x9d\xe9\x68\xee\xe1\x16\xb6\x83\x2d\xf6\x3d\x2b\x09\x7a\x7f\xb9\x3b\xf6\xb5\x2a\x65\x6e\x32\x89\x02\x05\x6a\x36\x8b\x99\xdf\x5f\x41\xc2\x84\x2e\x51\x4e\xae\x99\x2a\xea\x77\xe7\x47\xaf\xce\xfa\x05\x55\xdb\x57\x86\x8b\xbb\x98\x82\x7b\xa9\x4e\x49\xd9\xad\x00\xf7\x91\x5a\x74\xeb\x7a\xe0\xe6\xa2\xc9\xea\xff\x41\x39\x6d\x2d\x6b\x09\x1a\x9c\x41\x70\xc3\x06\xce\x16\xff\xe3\x2b\x08\x97\xf1\x7d\x26\xab\x4a\xe5\x42\xe6\x6b\x91\x2b\x53\xa9\x34\xb0\x80\x58\x73\x3c\x7a\x3a\x5a\x16\xec\xec\xa2\x87\x77\x54\xed\x22\x7c\x6e\xc5\x9b\xbf\xfe\x7c\xf2\x52\x4c\x8b\x15\x20\x30\xa2\x32\xab\xbd\x80\x44\xad\x74\x3a\x42\xf3\x26\x5b\x7a\x75\x9e\x0a\xe9\x55\x34\x55\x21\xa4\x95\xb4\x7b\x6c\x27\x42\x8f\x3d\x54\x02\xe2\x5f\x38\x09\x12\xac\xd6\xee\xd0\xb0\x79\xf4\xfe\xbd\x9d\x65\x59\xdc\x44\x37\xc8\x2c\x6f\xf8\x07\xa2\x7f\xe5\x62\xd9\x63\xcf\x0a\xfc\x24\xbc\x61\xf9\x2e\x74\x1e\x24\xe1\x7d\x68\xa1\x5c\x2d\xd0\xfa\x9a\x9f\xb9\x66\x6c\xe4\xf2\x7e\x27\xb3\x9c\x9e\xa0\x67\x59\xb5\x58\xd6\xd4\x53\x7f\x5b\xe9\xe9\x07\x31\x9d\x2b\xf2\x70\x4b\x55\xa5\xca\x85\xce\xd1\x5c\xe1\x6d\xa0\x80\x0f\x72\x92\xa9\x9e\x75\x26\x01\x06\xd5\x11\x47\x6d\xc8\xd5\xd0\x08\x29\xde\xad\x97\x0a\xd5\xec\xe4\x2b\x72\xad\xc4\xb5\xce\x32\xf2\x80\xe2\x7d\x74\xa6\x8f\x81\x5b\x6b\x8b\x41\x54\xcc\xf2\xa6\x82\xcd\x7d\x5a\x5b\xc5\xa9\x5e\xac\x32\xd2\x84\xe9\x3c\x85\x87\xc8\x97\x8f\x23\x27\x32\xb7\x43\x3d\xf1\x98\xb1\x11\x81\xde\x34\xa9\xfb\xcb\x2d\xb7\xe8\x66\x01\xca\x8e\x05\xb4\x6b\xec\x7c\x9b\xb4\x0f\x83\xd3\x67\x37\x11\x4f\xa5\x4e\xd9\xff\x0c\x90\x10\x68\xd1\x8a\x0c\x2f\x73\x34\x40\x97\xc2\xfa\x1b\x81\x00\x59\xcc\xbc\x09\x8b\xdf\xf7\x84\x29\x84\xae\xd0\x6b\x67\xa2\x48\xce\x47\x13\x2f\x2d\x65\x80\xbd\xc2\xa6\xd7\xff\xf2\xba\x53\xf8\x89\xd6\xef\xe0\x68\x59\xe4\xf3\x52\xef\xf5\x08\x63\x26\x06\x79\x71\xed\xce\x09\x77\x60\x5d\x78\x59\x01\xcc\xce\x3f\xe2\x45\x51\x2a\xdc\x73\x8a\xe3\x58\x96\x05\x19\x33\x65\x55\x01\xd9\x45\x32\x4b\xfd\xb0\x0a\x99\xd5\xe1\xba\xe2\x35\xe5\x4a\xa5\xf8\x44\xdd\x68\x83\x7a\x1d\x63\x79\x6b\xfe\xe3\xfe\xbd\x5b\x22\x3e\xc3\xa1\x78\x5b\x2c\x71\xcb\x49\xdf\xe0\xfd\x97\x17\x72\xe9\x4d\x5c\x72\x3a\x4f\x3a\xdf\xb1\x9f\xc0\x1b\x52\xe9\xb3\x47\xb3\x45\x34\x32\x6b\xe0\x62\x59\x29\xc8\x5c\x2b\x59\x8b\x3a\xe8\x9f\x51\x25\x1d\xd1\xe9\x06\x2e\x43\x9a\xe4\x7f\x42\x97\x50\xfd\xe7\xd4\xe1\x1d\xb1\x4f\x2a\x82\x7d\xd1\xb9\xe8\x20\x7f\xd5\x2a\xed\xf3\x8a\x1c\xf1\x69\x0a\xda\xce\xcb\x63\x9b\x98\xce\x3e\xa2\x4d\x75\xfa\x51\x1c\xb8\x52\x57\x5e\x7e\x54\x9f\x5e\xd7\xe6\xde\xfa\xfe\x22\xc5\x3c\x69\xd7\xf6\xf6\x6a\xde\x05\x75\xb5\x2f\x7e\x1d\x68\x5b\x69\x3e\x48\xe7\x71\x32\x76\x7d\xe3\xb1\x38\x10\x9b\x8d\x5d\x5a\x31\x0b\xdf\x74\xc8\x32\xd3\x09\x86\x7b\x46\x6e\x44\x89\xfd\xdd\x47\x55\x9f\xb6\xc2\xda\x2d\x79\x9e\x53\xe8\x92\x18\xdf\xbf\x67\xa3\xa2\xf8\xc9\x8b\xd3\x53\x71\xca\xde\xad\xe2\x55\x7e\x09\xd4\xef\xea\x70\x70\x78\x30\x38\xfc\xf6\xf3\xc2\x9c\x0e\x9f\xfc\x5f\x11\xe0\xf4\x65\xff\xf0\x1b\x8e\x6c\x4a\xea\x81\x15\xd6\xb1\x12\x63\x02\x7a\xfe\x8c\xc1\x9f\xaf\x6e\x96\x65\x8f\xbc\x5d\xdf\xc1\xd5\x87\xa6\x81\xff\x7a\xfd\x43\x0f\xbd\x75\x3f\xa8\x5c\xff\x1d\xd9\xb8\x69\xb1\x58\xea\x0c\xff\x24\xaf\x60\xf8\xab\x58\xc1\xcd\x51\x98\xea\x05\x5f\x9c\xec\xf8\x74\x92\x2f\x57\xf8\x63\x2e\xcd\xcb\xd5\x32\xd3\x53\x59\x29\x47\x52\x7e\x40\x3f\x7b\xe7\xb0\x7f\x25\x01\x26\x3b\x46\x55\x2f\xbd\xc7\xfe\x4e\x1a\xff\xfd\x0a\x84\xa9\xe0\xf1\x89\xf9\x8f\x77\x34\xc9\x72\xb2\xba\xbc\x5c\xff\xed\xf4\xb9\xff\xc1\xce\xe3\x3d\xe4\x5a\xdd\x9f\xb0\x07\x52\xe7\xc6\xcd\xe3\x24\x37\x95\xcc\xa7\xaa\x8f\x9a\x97\x99\x9e\xa2\xea\xd2\x9b\xba\x05\x5c\xbe\xb8\xff\x70\xae\xfb\x09\xb0\x8b\x00\xf2\xa4\x8b\xec\xe8\x12\x7d\x42\x4b\x95\xbe\x2c\xa6\xad\x51\x07\x3b\xa9\x2e\xcb\x15\xba\xbd\x1c\xd0\xdc\xd1\xd9\x01\xff\x46\xf2\xf1\x42\x4e\xe7\xc8\x79\xa1\x1e\x1a\x7f\x25\x5d\x07\xf8\xad\x6f\x79\x2b\xca\xad\x0d\x60\x0b\x7e\x2c\x01\xaf\x22\x2f\xf5\x9e\x98\x44\xb6\x16\x89\x67\xcb\x3d\x8b\x36\x0b\xf8\x06\x3e\xc2\x91\x39\xe7\xa0\xee\x8f\x9d\xab\x52\x66\xfd\xe5\xaa\xc4\xd0\x2f\x34\x45\xc9\x1c\x39\x2e\x53\x95\xde\xe1\x61\x6c\x59\x1b\xf7\x08\x26\xfa\xfa\xf9\x7f\xfd\xf7\x9b\x57\x7f\x7d\xfe\xee\xe4\x3f\x5f\x09\x20\x27\x4f\x9f\x8a\x27\x87\x8d\x0d\xb2\xb6\x73\x42\x28\x8a\x3a\x49\xfe\xb8\xed\xd6\xe2\x4d\xa0\x47\x1b\x51\x83\x1b\x54\x2c\x6d\x54\x4c\xb1\xec\xb1\x87\xde\x7f\xe7\xb2\xd2\x57\x2a\x08\x97\xb1\x6f\x6a\x8f\x1a\xa1\x38\x3d\x1f\xae\x42\xee\x61\xcb\xa5\x4a\xfb\x29\x46\x5b\x70\xa0\x0d\xba\xf8\xc0\x3d\xfd\x10\xaf\x48\x21\x05\x8f\x56\xe4\xe8\xc3\xd0\x16\x8f\x03\x44\x30\x16\xab\x42\x66\x31\x96\x9d\x62\x57\xcc\xa3\x16\x11\x34\x96\x4e\xe8\x16\x98\x6b\x73\xa6\x2f\x70\xb3\xc3\xee\xdd\x9e\xea\x9a\xee\xdf\x3e\xef\x1f\x06\x9b\xcd\x8e\x77\x80\xcc\x1d\xe4\x1c\x55\xba\x21\x42\xa0\xd2\x8d\x34\xeb\x7c\xba\x91\xab\xaa\x98\x15\xd3\x95\xc1\xbf\x96\x99\x5c\x6f\x90\xee\x15\x99\xd9\xa4\x70\x56\x36\xa9\x36\xc0\x51\xa6\x9b\xb9\x4e\x53\x95\x6f\xb4\x59\xc8\xe5\x26\x2b\x8a\xe5\x66\xb1\xca\x2a\xbd\xcc\xd4\xa6\x58\xaa\x7c\x53\x2a\x99\x82\xdc\xb9\xe1\xa8\xb7\x74\x63\xa6\xc5\x52\xa5\x3e\x0a\xe1\x27\x75\xb9\xca\x64\x29\xd4\xcd\xb2\x54\xc6\xe8\x22\x37\xf6\xd5\x2f\x73\x5d\x29\xb3\x94\x53\x25\xa6\x73\x59\xca\x69\xa5\x4a\x63\xc9\xe9\xf5\xf5\xf5\xe0\xfa\x09\x92\xd3\x77\x3f\x0d\xa7\xc6\x3c\xe9\xdb\x28\x07\x33\x7c\x70\xed\x3e\xbd\x7f\x6f\xc7\xff\x80\x45\x9f\x9d\x9f\xdf\x3c\x3e\x38\x3f\xaf\xce\xcf\xcb\xf3\xf3\xfc\xfc\x7c\x76\xd1\x61\x94\xb8\xa3\xeb\x75\x5e\xc9\x9b\xe1\x03\x3f\x0f\x38\xbf\xf6\xc7\xab\x7c\x5a\xa4\x14\x69\xd5\x49\x8e\x47\xe7\xe7\xe7\xe7\x83\xcd\xd9\xf9\xf9\x75\xff\x62\x73\xf6\xeb\xf9\xf9\xcd\xc1\x41\xff\xfc\xfc\x46\x1e\x5c\x74\xf7\x3b\x01\xf9\x2c\x8c\xca\xd0\x35\x46\x65\x2a\x05\xc1\x0f\x6e\x33\x34\x20\xeb\x99\x86\xdb\x26\x1c\x0d\xe4\x23\x60\xa2\x7f\x5f\x15\x95\x75\x52\x12\x66\x5e\xac\xb2\x14\xb8\x49\x59\xff\xf8\x93\xe0\x24\x2b\xba\xce\x94\x7f\x48\x43\xd1\x59\x14\xb4\xee\x51\x7b\x67\x2f\x4e\x4f\x1f\x1f\x0e\xcd\x1a\x2e\x4b\x39\x98\x57\x8b\xec\x01\xce\xaa\x9f\xaa\x59\xdf\xcf\x04\x0e\x8c\x9f\xd6\x58\x34\xc0\xe6\x55\xa4\x9d\xeb\x4e\x4f\x74\xae\x1f\x44\x2e\x46\x76\x8a\x2e\xa0\xc5\x6c\x99\xcf\x47\xd7\xe5\x9e\x22\xf6\x9f\x9f\x9f\xc1\x7d\x10\x60\xc7\xbe\xe8\x3c\x4a\xe0\x59\x73\x67\xf7\x45\xa7\x9b\x1c\x8f\xea\x1f\xb0\x5c\xf0\xe3\x52\x95\xa8\x54\x4a\xa6\x72\x59\xad\x4a\x25\xd0\xf0\xb5\xd3\x79\x94\x9c\x3d\xfa\xf5\x8b\xcd\xee\x3f\x2e\x8e\xc7\xdd\x2d\x1f\x77\xfc\x0a\x49\x89\x21\x16\x20\x70\x4d\x54\x6d\x47\x8d\x38\xb3\xbd\x7f\x75\x81\x0e\xad\xe4\xdf\xe2\x1f\x3f\x41\x2f\x02\xfe\xf1\x25\x79\x73\x74\x1e\x25\xc7\xa3\x87\x89\x47\xcb\x5f\xe1\xdf\x87\x17\xdd\x47\xdd\x87\x9b\xf3\x4e\xfd\xc5\x79\x07\xde\x9c\x77\x36\x08\x87\x60\xdf\x00\x00\xdd\x4d\xeb\x1a\x3a\x8f\xce\xcf\x2f\x18\xaf\x97\x46\xad\xd2\x02\xe1\x3b\xba\x1b\x94\xe7\xe7\x09\x34\x60\x20\xbc\x2b\x44\xa9\xd2\xd5\x94\x44\x02\x76\xe0\x29\x66\x7e\xcf\x51\xc2\x40\xfd\x1e\x33\x33\x56\x9a\x5d\x96\xea\x7b\x9d\x55\x20\x5e\xd1\x4d\xee\x85\x38\xeb\x25\x73\x38\x10\x7c\x6a\xdc\xfe\x3c\x39\xf2\x80\x0a\xa1\xf6\x15\xed\x5b\xf2\xf9\x10\xeb\x6e\xfc\x6a\x1e\x0f\x84\xd1\x8b\x65\xa6\xfc\x80\x5f\x73\xc7\xb5\xaf\x93\xee\xd9\xf9\xf9\xc5\x05\x7c\x2b\x02\xf4\x04\x18\x3d\x0a\x7b\x7c\x02\x5c\xe8\x9a\xdc\x97\x51\x1b\x54\xc7\xb4\xc1\x23\x6e\xdc\xe9\x9e\x9f\xc3\x46\x79\x3a\x43\x5e\x51\xc8\xc5\xe6\x45\xde\x57\x66\x2a\x97\x2a\x15\x55\x29\x75\x06\x2f\xfc\x7e\xf6\x18\x0e\xf0\xd4\x14\x0b\x85\xed\xaf\x5b\xc9\xf0\xb2\x54\x53\xde\x90\xb9\x12\xa8\x01\x2a\x83\x20\x41\xe0\xb1\x48\x22\x4b\x44\xe7\xd7\xe6\x39\xdb\xdf\x00\x24\x7e\x65\x28\x5c\x74\x2d\x58\xba\x8f\x1a\x28\x26\x3a\xfb\x5f\x00\x59\xb8\x74\x54\xa1\x9c\x16\x8b\x85\xfc\x84\x51\x1e\xf5\x5a\x9e\x51\x37\xd8\xc9\x44\xe7\x12\x91\xeb\x13\xba\x4a\xce\x9e\xed\xff\x83\x36\x2a\x7e\xd3\x32\xe1\x47\x7e\xaa\x6e\x53\xff\x06\x18\xd8\x18\x69\xdc\x3a\xd2\xaf\xe7\xe7\x17\x0f\xcf\x3b\x17\x8f\x8e\xdb\x3a\xc7\xd3\x16\xc1\x83\x4e\x5d\xad\x6f\x7b\x14\x69\xb5\x11\x09\x6e\x2e\x36\x3e\xe9\x5f\xb8\xae\x91\xef\x06\xd9\x82\xe3\x18\x77\x3a\x27\x2f\x3b\xa3\x5a\x07\x0f\xee\x38\xe9\x0c\xed\x9d\xce\x8b\x1f\x9e\x9f\x9e\x36\x3e\x3d\x3f\x1f\x7c\xca\xc7\xef\x9e\xff\xb5\xf1\x69\xfb\x77\x8d\xcb\x04\xf6\x22\xee\xec\xf9\xbb\x77\x3f\x35\x7a\xab\x1d\x40\x6e\xfa\xf6\xf4\xd5\xcf\x2f\x7f\x6c\x6d\x1c\x81\x77\xa7\xf3\xe2\x3f\x4e\x7e\x68\x42\x66\x94\x20\xf7\x83\x76\x96\x4d\x26\x4d\xb5\xc9\xab\x39\xfc\x7f\x1f\x7e\x74\xfb\xc9\x74\xae\xb3\x74\x53\xcc\xfa\xc0\x56\x33\x59\x6c\xa3\xb1\x40\xc7\xd5\x95\xca\x37\x45\x9a\x6e\x92\xe4\x6c\xbf\x7f\xb1\xe9\x26\xe7\xe7\xe9\xa3\x6e\xde\xa4\xca\x02\xa9\x3e\xb7\xda\xd6\xdd\xf9\x79\xba\xdf\xdd\x74\xdb\x31\x0c\x29\x88\xe8\x68\x07\x34\xe0\x1b\x9b\x5b\x40\x37\xa2\xe3\x29\x01\xcc\x5f\x44\xdf\x71\x9c\xce\x0a\xfd\x11\x45\x86\x89\x4b\x30\x30\x1f\xa8\x23\x10\x69\xd8\xea\x81\x36\x89\xf5\xc0\xfc\x45\x61\x63\x54\x4c\x02\x4f\xfc\xf6\xc7\x53\x32\x74\xb0\x9b\xf6\x6f\x74\x23\xfc\x86\x93\x42\xad\x13\xcb\xac\xad\x9b\x54\x5b\x17\x1d\xe1\x91\x87\xa4\xfa\x7d\x73\x59\x6d\x32\xda\x16\xbf\x4b\x7e\x23\x10\x58\x75\xd0\x26\xc7\xa3\xfe\xf9\x79\xda\x3d\x46\xf8\x6f\x83\x5f\x72\x3c\x3e\xfb\xb5\x7f\xb1\xf9\xc2\x41\xd2\x73\xe1\xa5\x06\xc9\xda\x60\xb4\x73\x72\x3c\xc2\x5f\xcc\x86\x6f\x60\x31\xb2\x54\x72\x33\x59\x55\x55\x91\x77\xbf\x18\xa2\xac\x5f\xce\x95\x24\x51\x70\xf8\xeb\xfc\x3c\xa5\xa7\xf0\xdc\x09\x42\xc3\x5f\xcf\x7e\xfd\xe3\x62\xff\xfc\x8f\x73\xf3\xe8\xfc\x8c\x1f\x9f\x5f\x0f\xbd\x7f\x9a\x34\x3a\x5b\xf7\xd1\x2b\x15\xf8\xf7\x61\xa9\xaa\x52\xab\x2b\xf8\x5b\x9c\xbc\x84\x7b\xf0\xdd\xf3\xbf\xc2\x3f\x78\x58\x45\xc8\x3b\x95\xbf\xaf\x34\x5a\xad\x4a\x3b\xe9\x07\xc9\x19\x70\xb8\xfb\xdd\x4d\x72\x7e\xbd\xdf\xdd\x9c\x0f\xec\x83\xee\x17\x3c\x66\x69\xf4\x24\x23\xc6\x78\x78\xb6\xff\x8f\x0b\x0a\xea\xa6\x0b\x08\x9e\x3d\xdc\x9c\x9f\x07\xc1\xe2\xc0\xef\xd0\xcb\x2d\x6c\x7e\x0b\xc7\xc9\xb7\x59\x3f\xe2\x95\xcb\x55\xee\x06\x89\x90\x02\xaf\xdc\xb3\xf3\xf3\x54\xf6\x67\x17\x7f\x1c\xf6\xbe\xbe\x6d\xee\xde\xf1\xa6\x71\x02\x45\xa7\xbb\x19\xd0\x36\x32\xd5\xdd\x99\x05\x43\x78\xb1\xef\xbf\x7b\xbc\x80\xd4\xfd\x11\x48\x31\x81\x3c\x38\xd7\x97\x20\xa8\x76\x0e\x6e\x60\x2c\x7b\x25\xf7\xc5\xc1\xcd\xe1\xc1\xc1\xc1\x81\xcd\x6e\xf2\x46\xbe\x11\x0b\x3c\x5a\x70\x13\x4f\x8b\x54\x2d\x0b\xed\x52\xb7\xd4\xd3\x52\x3c\x7d\xfc\xa5\x3d\x45\x45\xf9\x41\x96\xc5\x2a\x4f\x31\xa9\x40\xae\x8a\x95\xf3\xb5\x16\xce\x63\xda\xe5\x62\xd9\x87\x79\x04\x12\x23\xce\x6e\x77\x3c\xa6\x3f\x36\x9b\x96\xb5\x90\x55\xdf\x4e\x9c\x1c\x1f\xb0\x35\x46\x11\xde\xb7\x41\x16\xdf\xbd\x7e\x2b\xa2\x69\xef\xec\xb0\x8b\xe5\xac\x2c\x16\x2f\xe6\xb2\x7c\x51\xa4\x2a\xa1\x81\xf6\xed\xf2\x5d\xd6\x15\xbb\x4a\xa2\x15\x32\x13\x6f\x33\x99\x2b\xdf\xa3\x48\xcc\xaa\x2c\x8b\x4b\x59\x29\xb1\x94\xba\xec\x7e\x6c\x88\x67\xcf\xc4\xe1\x81\xd8\x88\x83\x9b\x97\xdf\x1c\x1c\xf4\xe8\xe1\x9e\x38\xb8\x79\xf2\xfd\xf7\xf4\xf8\xc5\x81\x8d\xc4\xb4\xda\xea\x1f\x97\x95\x5e\x00\xc7\x09\xf4\x08\xbd\x13\xd8\xae\xf0\xdf\x3d\x4c\x9a\xf3\x83\x36\x15\x1c\xee\xaa\x5c\xe3\x06\x07\x4d\x60\x3a\x09\xe9\x32\x42\x33\x43\xa8\x72\x1a\xe0\x15\x00\xfd\x18\x41\x0a\xa9\x9d\x2d\xaf\xef\xdf\x23\x87\x89\x76\xc7\x95\x03\x9b\x05\xa3\x52\xd3\x4a\x18\x9d\x51\x12\xa0\x19\x33\x79\x7e\x52\xa4\x5d\x39\xdb\x36\x09\x17\xad\xee\x54\xc4\x47\xf7\xef\xdd\x8a\x29\xd0\x60\x91\x08\x8b\xc5\xac\x69\xf9\x83\xac\x69\x14\x0d\xc9\x5f\x1e\x3b\x7b\xc9\x0f\x98\xde\xe5\x52\x71\x3e\x14\x3d\x13\x36\xf2\x0e\x55\x1e\xde\xc1\x06\x8d\x55\x3d\xe0\x6c\x9d\x56\x23\x50\xf2\xb8\x38\x5b\x6e\x16\x80\x52\x65\xc6\xd9\x69\x6c\x38\x7d\x08\x9f\x93\x57\x4f\xbf\xb5\x42\x9a\x75\xca\x14\xe4\xea\x29\xc8\x71\x12\x01\xf2\x91\xb9\x60\x4a\x22\x17\x92\x16\x99\xbb\xc9\x2a\x4e\x9a\x17\x97\xe6\xa6\x2a\x41\x82\xb3\xb8\xc1\xed\xed\x55\x02\x52\x81\xe0\x98\xc1\xb3\xf7\xfb\xfb\x17\x68\x46\x37\x67\x7a\x7f\xff\x02\xb5\xf7\x64\x64\x8d\xc6\x12\x63\xf1\x5e\xf4\xc5\xa1\xd3\xe3\xdd\x92\x6e\x3c\xb0\x3d\x90\x42\xbc\x25\x05\x88\xf3\x10\xea\x51\xac\xb8\xb7\x49\xe0\xbd\x6a\x1d\x5c\x16\x3d\x61\x37\xdc\xde\xdc\x7f\x3b\x7d\x6e\xb5\xba\x3b\xba\x27\x2e\xcb\x62\xb5\x34\x3d\x51\x64\x69\x4f\xe4\x1a\xfe\xa3\xae\xad\xc6\x18\xfe\xb6\x8a\xf8\xc0\x74\xe1\x8d\x6f\xc7\xf6\xaf\x41\x71\x9d\xab\xd2\xea\x88\x81\xba\xd8\x26\xa3\x08\x27\x39\xa2\xa0\x9e\x5b\x29\xd0\x2f\x27\xb5\x2c\x27\x36\x4d\x86\x73\xf5\x75\x66\x3f\xdb\xc9\x11\xdd\x3f\xe8\x16\xd5\xea\x20\x45\x16\x4d\x0b\xc3\xc0\x7f\xdc\x3d\xda\x6d\xb1\xe5\x3a\x5f\x24\xec\xaf\x66\x6d\x49\xbc\xa9\xc5\x81\xc0\x3e\xa2\x25\xa2\xf9\xc5\xb5\x82\x27\xdf\xd6\x7a\xc6\xe9\x85\x9d\xc6\xfa\x73\x8c\x4b\xf5\x9b\x6b\x0f\xc1\xbc\x28\xab\xe9\xaa\x0a\x02\x38\x71\xc7\x61\xe5\xee\x36\x1f\xa8\x1b\x35\xf5\x58\x23\xba\xdd\xd0\x55\xfc\x74\xa9\x54\xda\x5f\x2d\x47\x16\xbd\x3a\x0f\x4e\x5e\x52\xb4\x8c\xed\x51\x8c\x09\x8f\xce\x0e\x2f\xba\xb5\xcc\x58\x91\x8d\xe9\xdb\xc0\xbd\x00\xd5\x97\x1e\x1a\x97\xaa\x62\xe7\xed\xef\xd6\x27\x69\x22\x16\xce\xdf\x00\x8f\x14\xda\xb7\xbd\x23\x36\xb9\x2e\xc3\x3a\x30\xd8\xf7\xbb\x4c\x4e\x3f\x4c\x54\x59\xae\xc5\x97\x83\xaf\xd9\x4e\x6d\xfc\xe7\x18\xc5\x42\x5e\x40\xb2\x04\x89\x56\x64\x45\x7e\xa9\x4a\xab\x3f\x70\xf8\x95\xb0\xf9\xe7\xc1\xd7\xdf\x7e\xfd\x84\x2f\x12\x5a\x07\x4e\xd7\x7a\x04\x07\x13\x09\xfc\x10\x7d\x18\x32\x9a\x34\x39\x14\xb9\x54\xe2\xe4\x55\x8f\xd4\x43\x3d\x14\xc0\x7f\x51\x93\x0f\xda\x59\xd3\x9d\x9f\x12\x77\x31\x59\xdb\xc0\x0c\x53\x29\x89\x26\xe6\x93\x97\xf6\xbd\x9b\xca\x40\xa7\x08\xd1\x45\x38\x01\x8b\xd6\x81\x03\x91\x87\x62\x1b\x86\x86\x1e\x93\x8d\x80\xce\xf6\xe6\xd6\xbf\x32\x6e\x4c\xbe\xe5\x78\xd2\xd8\xaa\x1c\xe7\x98\xf3\x1e\xfe\x6d\xc7\x7f\x6f\x4f\x24\x35\x74\x88\x1a\xb4\x21\x47\xd7\x85\xff\xec\x38\x6b\x50\xe2\xc9\x1d\x2b\xc7\xed\x86\xb5\x41\xeb\x4e\x60\xdd\xbd\x78\x9f\xb2\xa5\x79\x38\x40\x4c\x25\xcc\x09\xe3\x46\xe9\x78\x3c\xbe\xf0\x13\x08\x99\x08\x47\x9c\x9b\xa7\xc1\x7c\xb7\x7e\x27\x2f\xdf\xc8\x85\x0a\x0f\xa8\x9b\x69\x63\x9e\xdb\x27\x36\x20\xe9\xbb\x39\xb7\xe0\xfc\x3e\xb9\x40\x98\xb1\x4d\x31\x9e\x06\x06\x90\x59\xc7\xf8\xd6\x89\xfa\x16\xff\xc4\x2a\xdd\xc7\xb8\xbd\xdb\x17\xd8\xf4\x3d\x82\x2b\x6a\x29\xe9\x72\xc5\x05\xd9\xe9\xff\x6e\x24\xe2\xd6\xae\xb3\x2b\x02\x31\xf7\xbf\x06\x95\x32\x55\x3b\xdd\xcb\xd1\xf9\xa2\xc8\xe0\xbf\x6c\x42\xa4\xb1\xfd\x75\xe7\xb1\xd5\xbd\x71\x56\xe8\x71\x9d\xee\x01\x50\xa3\x9b\x11\x67\xfe\xfb\xe9\x73\x71\x5d\x94\x1f\x8c\x30\x55\x29\xf3\x4b\x85\x49\x00\x04\x03\xa5\x5f\x16\xa8\xb0\xfc\x7d\xa5\x40\x5e\xb6\x1f\xfd\x82\x56\x29\xfc\x4e\x30\x7f\x4f\xf9\xf4\xd6\xe4\x76\x3e\x63\xbf\x26\xa1\x6e\xaa\x52\xa2\x4c\x47\x54\x0e\xba\xb3\x9d\x00\x1d\x82\x1e\x30\xe1\xd4\xd2\xe5\x32\x2a\x95\x48\xde\xcd\x65\xfe\x01\xfd\x38\x80\xb1\x54\xd7\xe2\xe5\x6a\x59\xe4\x95\xf3\x5f\xaf\xd4\x74\x8e\x3e\x2f\x5d\xdb\xd9\xc9\x2b\xf1\x8d\x48\x0b\x85\x81\x71\x38\xaf\xc2\x86\xb8\xb9\xac\x43\xfe\xba\x68\x7a\x1d\x84\x37\x62\x4b\xa0\xc5\x6e\x4b\xfe\xcd\x9d\x1d\xe2\x44\x80\x21\x63\x65\x70\xb8\x91\xb1\x87\x5b\x42\xfb\x18\xa0\x9d\x53\xb7\x27\x1d\x9d\x76\xba\x61\x18\xbd\xdb\xf9\xc0\x6b\x9b\x44\x9c\x1e\xc8\x8e\x5f\xec\x05\xb9\x19\x63\x22\x68\xfb\x37\x61\xff\x02\x06\x40\x56\xa9\x9e\xd2\x91\x06\xea\x9c\xe9\x74\xfc\x10\x9d\x4d\x74\x0a\x52\xe6\xc3\x0b\xd1\xf1\xd3\x17\x63\x66\xb9\x42\x3b\xa1\x67\x21\x75\xbf\x1f\x4c\x9d\x5a\xa2\x7d\x90\x7b\xab\x0a\x8b\x92\x89\xf0\x6f\xeb\x13\x09\x51\xda\x8a\xeb\x8d\xb3\x81\xf9\x51\x95\x73\x0f\xf0\xb4\x3c\xba\x0c\x3d\x27\x77\xe4\x3a\x0f\x4e\x05\xaf\xe5\x7d\xa1\xf3\xa4\xd3\xeb\x78\xbf\xd6\x00\x3d\x82\x0f\xdc\xd2\xac\x58\xb5\x8d\xa4\x58\xb2\xed\x97\x32\x40\x57\x0b\xdb\xd3\x73\x90\xb8\xa2\x9e\xf9\x0b\x47\xf1\x5b\x09\x3e\x8b\x3c\xc9\xef\x46\xa2\x33\x91\x9b\xcf\xad\x98\x69\x72\x29\x8c\xb2\x2f\xec\x02\xa2\x45\x69\x17\x68\x2e\xe4\xe6\x55\x43\xba\x3b\x23\x16\x7c\x82\x80\xe7\x59\x46\x8e\x27\xc6\x3b\xdf\xd0\xae\xf8\xdd\x69\x06\x18\x7c\x71\xd8\x11\xdd\xed\xec\xbf\x95\x1c\x86\x8f\xd8\x09\x06\xdd\x0e\xc4\x07\xb5\xee\x93\x51\x71\x2a\xd1\x79\xbb\x98\x89\x4c\x2f\x34\x50\x21\xa3\xff\x4e\xbe\x2c\xff\x3f\x66\xaf\xc4\x1f\xce\xd7\x8f\x58\xe1\x1e\x3b\x5e\x75\x6f\x39\xab\x01\xb9\x5b\xb3\x37\x16\x86\x92\xc9\x59\x85\x41\xd9\x05\x65\x5c\xa8\x80\x50\x70\x12\x94\x6b\x0d\x14\x5c\x3c\xda\x71\x01\xca\xc8\x06\x41\x0f\x09\xaa\x1b\xfa\x66\x35\x9b\xe9\x1b\x95\x76\x6d\xe0\x18\x10\xb1\x44\x73\x24\x23\x3a\x50\x68\x23\x32\x90\x99\x80\x52\xc9\x5c\x20\x73\x8b\x6f\x7e\xc0\xd3\xd3\xc5\x01\x52\x95\xa9\xca\x5a\x2d\x8a\x2c\x55\xa6\x12\x2a\xaf\xca\x35\xfb\xdc\x38\x71\x2a\x72\xc6\x70\x12\xd3\x07\xb5\x36\x81\xe7\xb2\x6f\x8d\xed\xe0\x75\xcf\x7a\xcc\xba\xe0\xed\x9f\x8d\x12\xc9\x07\xb5\x86\x03\x2e\x3a\x5d\xf4\x50\xc5\xa0\xc0\x69\x91\x65\x1a\x93\x0b\x50\xb4\x2f\x29\xec\x7c\xe6\xc0\xc0\xd5\x2e\x31\x4a\x89\x13\x63\x56\x4a\x3c\x38\xfc\xea\x2f\x5d\x77\xdd\xc1\x84\x98\x8b\x71\x43\x88\xae\x78\xd6\x58\x7e\xc8\xd5\x63\xe2\x97\x0f\x4a\x2d\x7d\x4c\x52\xa9\xa6\xc0\x8d\x01\x28\xec\x75\x83\xa0\x62\xe0\x9e\xd1\x40\x66\xae\x67\x55\xd2\xf5\x21\x06\xee\xec\x24\xbe\x19\x4f\x02\x08\x11\x82\xc2\xca\x66\x3e\x33\xd7\x74\xae\xea\x48\xf8\x5a\xc2\x8d\xe6\xdd\x78\xe1\xc2\xe1\x40\x2a\xd4\x07\x4f\xd6\xcc\xcb\x10\x1a\x2e\x65\x29\x17\x1e\x09\x6f\xc5\x2c\xc7\x7c\x86\xa1\x1b\xf0\x42\x96\x1f\xea\xbb\x0a\xcf\x6a\x5e\xaa\x00\x95\x59\x7e\x66\x6f\x7a\x9c\xb7\x75\x99\x71\x9e\xa4\xf5\xe9\xb2\x7e\x01\x89\x22\xe5\x6d\xb4\xf7\x2e\x5d\x79\xdb\x67\xf9\x16\xf3\xfa\xf8\x6c\xc8\x2a\x15\xa9\xbe\x42\x74\x56\x18\x12\x60\x84\x74\xd9\x91\xe8\xe4\xd6\x17\x01\x3d\x94\x55\x30\x7d\xc0\x4c\xe8\x64\x7b\x48\x6c\xaa\xaf\x3a\x7c\x31\x3a\x72\x6a\x73\x18\xec\xce\xf2\x04\x3f\xa7\x8d\xb2\x9a\x1e\xb5\xcd\x8f\x30\x26\x7f\xe8\xc2\x81\x19\x5b\x90\x8f\xd0\x95\x61\x51\x0d\xb6\x8c\xd3\x4b\x3a\x6c\x4d\xf5\x55\x9b\xfc\x14\x3f\x8e\x03\x6d\xdd\xc4\x5c\xa8\x78\x49\x2e\x77\x62\xa1\x16\x45\xb9\x06\x31\xee\xe4\x15\xbc\x22\x08\xe4\xab\x2c\x63\x84\x8b\x76\xec\x79\x9a\x1a\xef\x9d\x6b\x3d\x76\x01\xcd\x24\x10\xd9\x99\xf3\x8c\xa6\x34\x2c\xb2\xaa\xd8\xc3\xcf\xee\x22\xe9\x14\x6f\xe9\x8d\x78\xab\x97\xaa\x6f\x14\xbc\x83\x2d\xcc\xb4\xa9\x30\xd1\x9e\xb3\x20\x6d\xc1\x00\x3b\x30\x20\x2b\x79\x43\x91\x68\x8a\x8e\xd6\x13\x54\x4d\x65\x5a\xa5\x8d\x2d\x4f\x53\x12\x2f\x13\x1a\xbf\xe7\x3a\xf2\x18\x40\x6a\x46\x7c\x6d\xfd\x5e\x37\x9d\xae\xcb\x08\x46\x2f\xc2\xf8\xa2\x16\x46\x02\xa9\x06\xb4\xa4\xd1\x30\x64\x0b\xb8\x06\x38\x14\x3c\x62\x1b\x70\x51\x44\x37\x5e\x94\x2e\xd0\x69\x0d\x80\x7a\x5d\x08\x66\x2a\x62\x88\x30\x66\xde\x0a\xd9\xfe\x78\x52\xbb\x6e\xc8\xff\xd7\x5f\x2e\x99\xc2\x80\x1e\x99\x8b\x03\x10\x64\x24\xdb\xa3\x95\x11\x93\x9e\xb8\x44\xe4\x2f\xa3\xf7\xb3\x22\xcb\x8a\x6b\x43\x1d\x87\xa0\xe5\xe9\xe1\x12\x22\xe7\x3a\x8c\x6e\x5a\x01\x4c\x27\xc0\xff\x48\xca\x99\xa6\x67\x33\x60\x27\x57\x25\x3e\x6b\x71\xa3\x9d\x34\x9f\x21\x92\x27\xe2\x1f\x93\x81\x29\x56\xe5\x54\x9d\xe4\xa9\xba\x01\x76\x29\xf2\x9b\xeb\x8a\xbe\x6d\x28\xef\x6e\xe8\x92\xb5\xc1\xd5\x72\xf2\x4a\x84\x8d\x61\xb1\x57\x52\xa3\xc7\x3f\xdc\xb0\x93\x02\x53\x7b\x91\xfa\x98\x0f\xe1\x6c\x56\x53\x2f\xc1\xa3\x28\x55\x19\xe9\x5c\xf4\x4c\x4c\x1c\xe0\xa4\xfd\x1e\xd6\xce\x9f\x3b\x6d\x26\xc1\x69\xba\x2a\x07\xb9\xba\xa9\x4e\x09\xa4\xdd\xd8\x7f\x0d\xdb\x44\x8e\x8a\xb1\x83\x5a\x83\x01\xb2\x51\x7a\xe2\x58\x1c\x8a\x11\xb5\x8a\xd0\xce\x22\x43\x1c\xfe\xc1\xb6\x46\x6b\x9f\xa5\x48\xa8\xe5\xaa\x42\x4d\x5e\xfb\x99\x86\x37\xed\x0c\x00\x7a\xc0\xbe\xc5\xae\xd8\x0f\x9b\x26\x6f\xa9\xe2\x56\x87\x3f\x64\x60\xc6\x77\x05\x91\x87\xf9\x15\xa9\x35\xc8\x3a\x38\xd5\x8e\x53\x5e\x38\x57\xeb\x8a\x14\xf1\x5e\xf1\xfb\xd9\x40\x20\x73\xe2\xe7\x02\xe0\x3b\xfc\xea\xdf\x0f\x81\xa4\x01\x82\xcd\x26\x00\x0b\x4d\xbe\xd3\xfd\x77\x00\xc6\x26\xba\x90\xd9\x36\xaa\x3d\xcb\xdb\x81\xf3\xd6\x7d\x69\x01\xe4\xee\x64\x17\xa3\x17\x30\x1c\x61\xe0\xee\x65\xa4\xd4\x76\xbf\xc7\x62\xdf\xfe\x1d\x42\x67\x4b\x37\xc0\xd0\xf7\x6c\x1c\x60\x6c\xad\x60\xb1\x08\xdf\x21\x65\x40\xdf\x13\xb8\xea\xcf\x2e\x48\x12\xb0\x66\x8c\x60\x32\x81\x49\x23\xfc\x30\x8e\x4a\x75\x69\xbd\x7d\x56\xe1\x19\x6a\x22\x64\x55\xbb\x44\x35\x7d\x1e\x19\x3e\x22\xa9\x95\x34\x36\x4a\xa5\x67\x22\x79\x5f\x1b\xf4\x4c\x5f\x74\x45\xa0\x33\xdb\xc1\x76\xef\xe1\x26\xda\x4d\x78\xc9\xf4\x93\x5f\xb4\xc5\xa8\x11\x4b\xd3\x14\x79\xe8\xbe\x92\x94\x8f\x63\x46\x89\x93\x74\xaa\xab\x35\x25\x90\xe6\xe0\x02\x97\xb0\xa5\x79\x43\x6d\x48\xb2\x19\xdf\xc6\x8d\xdc\x7d\x15\x37\xdb\x70\x18\xcb\x2d\xde\xfb\x44\x8d\x70\x68\xa0\xd6\xd3\xa9\x5a\x56\x14\xa0\x55\x78\x13\x15\x32\x5c\x6b\xe2\xa0\xeb\xc8\xd7\x26\x8a\xc7\x68\x67\x1f\xfa\xba\x26\x77\x69\x17\x51\xcb\x12\xb9\x79\x7b\xc5\x8c\x03\xdd\x10\x44\x8a\xc2\x28\x57\x05\xe0\x4a\x96\x74\x7e\xa6\x45\x7e\xa5\x72\xad\xf2\xa9\xba\x7f\xcf\xd7\x08\xe0\x72\x33\x8d\xa2\x01\x76\x13\xc8\x52\x69\xc4\x7f\xbd\xfe\xc1\x5e\x50\x5b\xe1\x7c\x4b\xd4\xe5\xb9\x63\xb0\x31\xcd\x62\xa0\x66\x8e\x80\xef\xa1\x5d\xae\x00\xc6\x94\xff\x9a\x72\x30\xe5\x45\xde\x47\x93\x89\x1d\x96\x81\x8b\xc1\x12\x7e\xd6\xf6\x67\x2b\x79\x1b\x0e\xdd\xc8\xaf\x6c\x9e\x66\x23\xae\x54\x49\x68\x4f\xd9\xed\x8d\xb2\xa5\x5f\x74\xe5\x14\x64\x6b\x55\x51\x84\x14\x27\x71\xb6\xb5\x57\xb2\x82\x7c\xf4\xf4\xac\x94\x0b\x4c\x3a\x06\xf7\x7a\x5f\x3c\xf8\xf2\x9b\x27\x68\x8b\x40\x16\xbf\x36\xe6\xd8\x19\x26\x50\x83\xde\xb4\xab\xc1\xd3\xee\xa0\xf6\x59\x20\xd7\xd4\x3b\x3c\xae\x3f\xf1\xf9\x50\x50\x0f\x07\x70\xeb\x88\x91\x93\x05\xe2\xfd\x3c\x55\x95\x67\x01\xfb\xa5\xa2\x98\xbe\x2b\x59\x6a\x40\x6e\x23\x8a\x7c\x4a\x99\x40\x53\xab\x94\xb4\xd9\xf0\xe3\x6d\xdc\x82\x00\x67\x69\x31\xbd\xa8\x61\x80\x67\x38\x49\xcf\xc0\xf4\xbd\x2a\x30\x17\x7c\x68\xdd\xa9\x61\x88\xed\x34\xd4\x55\xb4\xcd\x66\x78\xff\x5e\x60\x6f\x0c\x90\x3a\x7a\x18\x24\x97\xf7\x62\x0d\xd7\xd6\x78\x51\x2c\x40\xb4\x21\xe6\x11\x03\x4c\xb0\xcd\x31\xfe\xd3\xdc\x32\x7c\x19\xdb\x41\xc9\x25\x80\x64\x2a\x94\xf0\x06\x2c\x56\xfd\xa7\x56\xd7\x8e\x15\x3c\x99\x89\xbc\x08\x6a\x6e\xe4\x69\x1b\x8e\x3a\xd6\xb0\xc7\x26\xa8\xc0\x9e\x88\xb7\x69\x1a\xcc\x05\x86\xaa\x59\x25\x37\x1b\xb1\x8b\x33\xa8\x75\x5d\x63\x27\x03\x6b\xeb\xad\x4f\xc6\x58\x89\x62\x55\x86\xa6\xa1\xa0\xd6\x47\x5a\x4c\x8f\x7c\x84\x90\x5d\x67\x03\x73\x23\xef\x07\xa4\x83\xa6\x11\x4c\x84\x69\x03\xe0\xf8\xd2\xaa\xba\xf5\xcf\x46\xe2\xe4\xd5\xb3\x6f\x1c\xd4\xe8\xc8\xf9\x85\x03\x94\x8c\xd1\x97\x39\x25\x49\xea\xf8\xb2\x3c\x16\x95\x11\xb8\xda\x7d\x39\x97\x46\x4c\x94\x02\x69\x1d\x8e\x31\x45\xc4\x90\x66\x1c\xa5\x3a\x4a\x61\xd9\x59\xaa\x72\xa1\x31\xc0\x41\xa4\x40\x2d\xd3\x0e\xd7\xfb\x40\x2b\x26\xdc\x02\x06\x95\x08\x2d\x03\xe2\x7d\x6d\xa3\xd3\x1e\x1c\x3e\xf9\xf6\xc9\xd7\x76\x88\xaf\xfb\xdf\xd8\xca\x4f\x96\xd0\x56\xbe\xae\x03\x60\x88\x4f\xfa\x67\x0a\x2b\x9a\x5b\x69\xd3\x11\x7c\x8b\x06\xfc\x7e\x6f\xcf\xfe\x05\xdb\x4e\x7f\x0e\xaa\x62\x19\x68\xb5\x4e\x5e\x1d\x1e\x22\x59\xc3\xb1\xe7\xf2\x4a\x71\xb0\xe8\xab\x2b\x95\x57\x18\xea\x0a\x82\x35\xba\xb2\x9b\xd5\x6c\x86\xde\xc1\xe1\x20\x03\x99\xa6\xd8\xf6\x07\x6d\x2a\x95\xfb\x92\x1b\x3b\x5b\xde\x27\xa2\xb3\xca\x01\xc2\x9d\x5e\x33\xe6\x37\x72\x0b\xb0\xaa\xe5\x9e\xcd\x17\xc3\xfe\x21\xde\xec\x65\x87\xf0\x33\x6e\x8c\xee\x5f\x25\xa2\x53\xe4\x9f\x39\xb4\x57\x59\xf0\x01\x78\xe4\x03\x19\x00\x65\xfb\x7f\xca\xff\xb8\x00\x5a\xdd\xe3\x85\x91\xfb\x3f\xe1\x42\x5a\x93\x7e\x21\xb4\x7b\x60\xe1\xad\xcc\x26\x23\x35\xa1\xdb\x2b\xf9\x88\x57\x91\xea\x51\xdd\x00\x83\x02\xa8\x79\xf2\xea\x1b\xe7\xeb\xd9\xf5\xe1\x87\x83\x28\xae\x82\xb5\x53\x9e\x26\xa2\x06\x87\x60\x95\xea\xab\xc1\xd4\x19\x0a\x81\xd5\xef\x84\x5c\xee\x2e\xbc\x8f\x2d\x34\xae\x75\xc7\xb3\x72\x04\x4e\xcf\xc8\x24\xa6\xfb\xdd\xfa\xd1\xbf\x03\xa8\x4e\x0c\x6e\xb5\xc9\x76\x1e\x75\xba\x0e\x88\x98\x82\x24\x30\x78\xb5\x9a\x51\x2d\xbf\xf5\x71\x28\x45\xd9\xe8\x80\x16\xb2\x3e\xba\x58\x90\x42\xaf\xd3\x8d\x13\xf4\x5b\xd0\xb5\xcf\x32\x30\x20\xdd\x7a\x7a\xd8\xbe\x3a\x6f\xc8\xe5\x38\x75\x74\x66\x42\x12\xf1\x11\xd3\xf0\x58\xb0\x2f\x2a\xdb\x8f\x60\xda\x5b\x6d\xc4\x7b\x7b\x1f\x85\x81\xce\x73\x55\x32\x45\xef\x3c\x85\x97\x88\x0d\xe3\x87\xf2\xe1\xb3\xa7\xc3\x54\x5f\x3d\x8b\x1e\x0a\x6d\x1f\x77\x8e\x9a\x8e\x60\xa7\x72\x26\x4b\xfd\xd4\x3a\x48\xbe\x40\x01\x06\x3f\x15\xc5\x95\x2a\xfb\x53\x89\x2e\xc6\x76\x6c\xf4\x05\x46\xf0\xb7\x22\x6c\xd8\x33\x7a\x77\x3c\x3d\x3c\x88\x7a\xbe\x7c\xf5\xdd\x8b\x37\xe8\x7c\xb7\x2a\x91\x21\x99\x69\x0e\xbf\xe0\x24\xb5\x34\xb6\x32\x91\x16\xe6\x6a\x9b\x59\xbc\xa3\xdd\x26\xe2\x35\xfd\xb8\xb6\x95\xe1\xe9\x3f\x3c\xd8\xba\xbd\xdf\xad\x4f\x52\x87\xb1\x4e\x7a\x63\xaf\x13\x5f\x15\x68\x52\x16\x1f\x54\x5e\xff\xce\x26\x3e\x4e\x31\x6f\xf6\x52\x4f\x3f\x88\xd5\x12\x28\xc5\x65\x29\x17\xb2\xd2\x53\x20\x2a\x7d\x60\xbc\xa0\x37\xc3\xb7\xa0\x29\x38\x82\x12\xad\xd5\x72\x52\xac\xaa\x18\xdf\x10\xb2\x80\x30\x31\x82\xe1\x90\x1f\x39\x27\xc4\x2c\xd4\xce\x0a\xbc\x47\x9f\x8f\xc8\x76\xef\x8e\x49\x1d\x27\x71\x78\xcb\xd6\x34\xde\x24\xce\x2c\xb0\xe5\x0c\x9d\xbc\xa4\x9d\xc5\x6c\xd0\x18\x86\x64\xaf\xd2\xfa\x5a\x42\x0d\x2b\x7c\x72\xd6\x39\x79\xd9\xb9\x88\xb8\x47\x9d\x36\x12\x8d\xb4\xa5\x13\xa9\xb9\xc4\xb4\x4a\x6f\x35\x96\x28\x48\x12\x53\x8a\xbb\x5c\xaf\x02\x53\xf5\xbf\xe6\x7a\xf5\x39\x9e\x57\xe8\x71\x15\x69\x04\x51\xaa\x89\x7c\xad\x8e\xc5\x99\x58\x70\x65\x91\x50\x5b\x78\x14\x00\x15\xc0\xdf\x0a\xd6\x48\x35\x02\xb7\x15\xe2\x96\x0e\xcd\xfc\xd6\x9d\x1b\x2f\x78\xf6\xec\x66\x48\xdc\xa9\xe9\x8a\xf3\x47\x36\xdd\x0b\xf0\xb8\xd2\x90\x3c\x6d\x97\x54\x24\xf2\x21\x88\x0f\xf1\xd7\xc3\xbf\xf0\xc3\xda\x5e\xb3\x87\x55\xa9\x32\x66\x45\x51\xbf\x05\x18\x68\xd8\xdb\x0f\x4f\x06\x99\xee\x6a\xb8\xc6\x54\xb1\x0d\x58\xff\x73\xd0\x42\xcd\x20\xa5\xad\x65\xac\x6e\x00\x0e\xf7\xbb\x0d\xa9\x5b\x5b\x46\x06\x75\xab\x4e\x85\x1e\xd8\xa7\x72\xe0\xb3\x07\x6e\xdb\x06\x7b\x98\xdf\xc9\x4b\xce\xa4\xc0\x50\x7b\xf7\xfc\xaf\x08\x9e\x3b\x2f\x73\x74\x76\x0f\xfd\x87\x2f\x3f\xf7\x14\xdf\xa5\x89\xa9\xa3\xd9\xdd\x5e\x62\x95\xbc\x8c\x13\x86\x91\x1f\xfd\x47\x66\x07\x7b\xa2\x38\x31\x83\x4b\x4c\x64\x33\xb7\x85\x69\xbf\x02\xdf\xd9\x4f\x9b\x87\xd5\x17\x52\x84\xa6\x00\xe2\xef\x6a\xaf\x4c\x89\x97\x09\xbc\x83\xe0\x2b\xd4\xf6\x3e\x0a\x7c\x7d\x9c\x8d\x81\xbd\x04\x79\x0a\xde\x5d\xfa\x7e\xcd\x53\xb3\x6e\x7f\x09\x7c\x32\xaa\xc5\xb2\xd5\xe5\xaf\xe6\xdb\xe7\xf2\x9c\x70\xc6\x25\x7e\xdf\xe2\x26\x72\xeb\x99\x29\xb8\xab\x63\xec\x21\x9f\xbb\xad\xf8\x13\xf9\xd4\x05\x59\xa0\xed\xe3\xc6\x3e\x7d\x14\x89\x7c\x8f\x9f\x71\x25\xdc\x85\x57\x81\x5f\x9e\xe7\x82\xba\x91\x13\x3a\x31\xe3\x7f\x3b\x7d\x3e\x64\x9d\xec\xa9\x2f\x3b\xf8\xa7\xf3\xe3\x7f\x3b\x7d\x8e\x37\x6d\x6d\x28\x9f\x62\x88\x9a\xd5\x5e\x27\x23\x39\x05\xb6\x14\x98\x75\x2a\x01\x4c\x62\x21\xd5\x0a\x2a\x57\x4a\x24\x27\xaf\xbe\x1d\x22\x1f\x27\x0e\x0f\x07\x18\x03\x1c\x65\x20\x09\x5c\x3e\xd0\x73\x4f\x26\x23\x4c\x90\x70\x47\x8f\x2f\xe6\x65\xb1\x50\xe2\xf1\x61\x97\x93\x19\x28\x2e\xf2\x19\xd5\xbf\xc5\x82\x8b\x93\xd5\x25\x29\xfc\xbe\x19\x7e\x4b\xd7\xa5\xcd\xc8\x95\x93\x8a\x80\x7a\x80\xce\xb1\x3e\xca\x6f\xce\xca\x4f\xeb\xe2\xfd\xfa\x4d\x70\xf9\x65\xc3\x2a\x36\x99\xb3\x8a\x82\x79\xc4\xa2\x27\xae\xed\x2c\x68\xfe\x70\x9f\x73\x6a\x44\x4a\x43\x87\x00\xe6\x12\x84\x95\x5e\x28\xef\xac\x02\x4f\x4e\x5e\x85\xf3\x39\x55\xca\x46\x69\x4d\x56\x97\x66\x10\xd4\x1e\xa7\x82\xcc\xc3\xc3\x27\x4f\xfe\xf2\x4d\x98\xda\x25\x80\x23\x39\xe7\x85\xde\x9a\x6d\xe2\x43\xdd\x91\x2b\x70\xd3\x74\xb5\x05\xa1\xdf\x52\x5d\xaa\x1b\xe7\x8e\x70\xa9\x6e\xd0\xa9\xb2\x52\x97\x6b\x21\xd3\x62\x59\xa9\x94\xdc\x13\x5e\x6a\x75\x59\x88\xb7\xaa\xd4\xb9\x46\xbb\xcb\x1d\xec\x25\xad\x31\xe3\x22\x98\xa8\x50\x2c\x6c\x69\x4d\x2e\x2a\x95\x0b\x4e\x98\x62\xdb\xbf\xa3\xf2\x7a\x98\x09\x4c\x99\x4a\x9c\xbc\x7a\x68\x44\x05\xa2\x1b\xa9\x29\xa9\x9a\xab\xba\x59\x66\x7a\xaa\x39\xf4\x04\xb9\x64\x55\x51\xd6\x74\xe7\xfa\x81\xe7\x31\xaf\xbc\x70\xde\x73\x6d\xb1\x2e\x09\x3a\x5a\x60\x01\xf1\x69\x98\x06\x42\xe5\xb0\x8f\xb6\xe9\x47\xb6\xe7\xf1\x93\xaf\xbe\x75\x0e\x18\xb1\xb4\x45\xde\x65\x62\x61\x10\x5d\xa6\x99\x5e\x8e\x1f\x3e\x7c\xf6\x94\xf2\xe9\x09\x9b\x30\x04\x9f\x0d\xe9\xe1\xb3\xa7\x9c\x80\xc1\x89\x5f\x35\x9e\xe6\x1b\x76\x84\x17\x87\x87\xfd\xc3\xc7\x83\xc3\xaf\x6d\x9b\x37\x05\xc5\xb5\xfb\x55\xd8\xfe\xe9\x40\x85\x30\x37\x6c\x8f\x16\xbf\x8e\x45\x51\x8a\x2f\xf0\xbf\x8f\xc6\x1e\xfe\x24\x4b\x78\xb0\xb9\x64\x0a\xab\xfc\x43\x4e\x39\x5e\x78\x1a\x93\x55\x25\x3a\x46\xce\x54\x07\x35\xf6\xbf\xe8\xfc\xa7\x77\x35\xc0\x2d\x4c\x9a\x0f\x16\x36\xeb\x39\xc2\x4e\xe5\xfd\x95\x19\x52\x20\xeb\x7a\xa8\xd5\x70\x3e\xff\xf2\xeb\xaf\x9e\x7c\xf3\xcd\x40\x9a\xe5\x8d\x4f\x3c\xf1\xdf\x46\xb9\xf4\xa2\xde\xf9\xa5\xe1\x98\xd8\x39\x0b\x40\xfc\xeb\xf8\xe1\xc3\x0b\x2f\xe8\xf9\xab\xdf\x39\x2d\xd3\xe5\xd5\x39\x7b\xf4\xeb\x17\x17\xad\xa1\xe3\xc7\xa3\x87\x0f\x37\xe7\x9d\x73\x0c\x77\x8e\x3d\x2c\x6b\xbb\x61\x9f\xd9\x0c\x6b\x35\x2d\x50\x07\xd9\xa6\x0e\x73\xee\x15\x21\xb1\x4a\x6d\x75\x67\x46\x5d\xf2\x7c\xdc\xb2\x32\xbb\x8b\x9f\xb4\xa4\x2d\xd9\x38\x8e\x47\x38\x8f\x4d\x23\xcc\xb8\x6d\x79\x14\x5c\xc1\x84\xbc\x2f\x46\x9c\xdf\xc6\x22\x56\xe4\x40\x09\x24\x92\x90\x39\xf2\x52\xde\x96\x05\xe6\xf1\xc1\xe1\xe1\xf0\xa7\x57\x2f\xfa\x71\x06\x95\x3e\x3c\x3f\xf8\xf6\xf1\xb7\xc3\x07\x3c\xd8\x7d\xe7\x17\xfd\x8d\x25\xe3\xa4\xe6\x45\x53\x10\xba\x5e\xeb\x2c\x23\x85\xad\xc2\xc4\x09\xaa\x74\x8a\xec\xbb\x01\x6a\xd7\xf3\x71\x70\x06\x4d\x8f\x6a\xd6\xd0\x4f\xa2\x7a\x16\x4d\x28\xb1\x9c\x11\xdf\x88\x37\xe4\x9c\xf8\x7c\xb9\x34\xd1\x59\x03\x36\x0b\x95\x86\xc0\x19\x84\x28\x54\x2a\x60\x94\xb0\x84\x83\x4a\x45\x4a\x39\x25\x02\x22\x43\x3a\x76\x17\x23\x42\x65\xce\x97\x2b\x6b\xe2\xa8\xf9\xaf\x91\x4b\x80\xcd\xad\x0b\x3f\xea\x9e\xd6\x30\x93\x4e\x4f\x74\x28\x23\x91\xc3\x8e\x86\x2e\x8d\x06\xe9\xd6\x3f\x87\xf9\xc3\xe7\x2f\x3b\x11\xdf\xda\x76\x60\x5e\xe5\x58\x19\x08\x4d\x7c\x7d\xa3\x72\xac\x56\xa4\x2b\xac\xb8\x15\x83\xe1\xa3\x67\x1f\x9a\x8f\x3f\xed\x7c\xe0\x04\x5b\x22\xda\x5d\x7a\x99\xb6\x03\xf1\xfd\xf7\xe2\xc9\xe0\x2b\x38\x0a\x2a\xc7\x84\x4d\xc3\x91\x4d\xdd\x84\xbb\x46\xc0\xf2\x9a\xa0\xa4\xfe\x00\xb6\xd1\x54\x80\xb0\xdc\x41\xf7\xdf\x89\xdf\x3c\xc6\xa7\x80\xc3\xb5\xed\x89\x8e\x5b\x53\x1b\x08\xf8\xca\x39\xe8\x87\xe6\x0a\x32\xc9\xc0\xf5\x5d\x98\xaa\x4f\xd9\x44\x74\x8e\x3e\x00\xd6\x33\xc4\x61\x4f\x73\x9e\x8f\x7a\xa3\x1b\x8b\x8b\xf5\x83\xd7\x1b\x3c\x1a\x75\x6c\x79\xd9\x7a\x20\xa0\xe5\x76\xea\xec\x6b\x9d\xf3\x49\x7c\xfe\x6c\xab\xe3\xb2\x4f\x28\xb3\xa2\x7d\x7a\x8d\x04\xef\x75\xad\xbb\xb8\xcd\xa2\xf8\xfb\xdd\x0d\x8a\x8f\x7c\x6f\x6a\xef\xbb\x8e\x09\xfb\x14\x5a\xf2\xc2\x66\xa7\x05\x6c\xd0\x33\xa1\xab\x87\xc6\xcb\x80\x55\x21\xd2\xa2\xce\xaf\xdb\x4f\x81\x85\x15\xa9\x36\xd3\x22\xcf\x89\x62\xa3\x5c\x9f\x9c\xbc\x12\xdf\x12\x1e\x5a\x80\x86\x8d\x5e\x73\x88\xa3\x4d\xa8\x4d\x11\xd7\xa9\xbe\xea\x09\x74\x83\x8d\xce\x37\xf2\x6b\x7c\x3d\xcc\xa4\xce\x7c\x09\x75\x32\x7a\xf8\xca\x2c\x7f\x55\xd3\x0f\x85\xc7\x20\x45\x69\x72\xad\x2e\x95\xd8\x7f\x0e\xdb\xc3\x4f\xda\x86\x3f\x33\xbb\x70\xc3\x8f\x6e\x1c\xa2\x46\x52\x86\xc5\xed\xdd\x71\xa7\xe7\xd3\x8b\x34\x70\x29\xe4\xa6\x3d\xfa\xf1\x89\xd9\xdb\x8b\x12\x1e\xf8\xf7\x14\x76\xb1\xb1\x76\x83\xba\x78\x13\x4f\xe4\xae\xce\x6c\x9b\xb8\x43\x12\x03\x5f\x70\x30\xde\x9f\x2b\xfb\xed\x78\x33\x7a\x9b\x90\x80\x58\x3a\xa5\xf7\xd6\x0e\x67\x1d\xb3\x02\xeb\xaf\x35\x55\xdb\x80\x41\x21\x73\x74\xb7\xe1\x7c\x67\xc4\xc7\xcf\x56\x59\xb6\xf6\xbb\xec\xb2\x94\x50\x9d\x24\x03\x57\x60\xaa\xcc\x54\xe5\x29\x5d\x5c\x58\x02\x51\xe8\xbc\x17\xf8\x7e\xfb\xcf\x79\x28\x8e\x72\x08\x52\x57\xa2\x37\xad\x5b\xd3\x66\xb3\x75\x51\xdc\xbc\x5b\x57\x32\x85\x39\x20\x49\x4d\x87\xf9\x0b\xc7\x75\x8f\xd4\x6f\xc5\xb1\x90\x0d\x6b\xfd\x88\x9d\x59\x77\x76\x26\xab\xa5\xf5\x6f\x9d\x04\xda\xd6\x48\x93\xc7\xe9\x25\x57\x4b\x54\x93\xef\x26\xf8\x27\x7c\xb0\x5a\xb6\xb8\xbf\x26\xd4\x31\xce\xc7\x2f\xc0\xd6\x80\x88\x1f\x53\x57\x2e\xd7\xc3\x8e\xdc\xba\x8d\xe8\x6b\xbb\xe5\xa5\xed\x65\x4f\xb0\x48\xd1\x0d\xf2\x01\x6c\x05\x1a\x52\xe4\x49\x8b\x9a\x69\x02\x00\x09\x60\xd1\xd0\x31\x4d\x48\x97\x18\x87\x93\x46\xc9\x72\xdb\x23\x7b\x5a\xea\xab\xb9\x83\x73\x5a\x94\x15\x59\x9f\xfe\xc4\x73\xc3\x09\x21\x62\xa7\x6c\xe3\x46\x0a\xb3\x8b\x06\xd8\x78\x1c\xc4\xb5\x84\x30\xbb\xef\x92\xbd\x5f\x52\x09\x4d\x97\x62\x94\x0b\x56\xdd\xff\xdc\x7c\xa4\x51\x2e\xd2\x30\x21\x78\x51\x62\x70\x10\xfb\xc7\xa3\xbf\x14\x8a\xb9\x61\xad\x64\xe2\xe3\xe6\xd2\x88\x2d\x68\x71\xdf\x16\xa8\x70\x94\x63\x77\x3b\x7e\xf5\xc5\xee\x64\xdb\xcb\xa3\xfb\xbe\x90\x1a\x75\xd5\x50\x9d\xe1\xe3\xda\x2a\x5e\xc8\x6c\x4a\x49\xae\xad\x7f\x29\xfa\x53\x17\xd5\x5c\x70\xf2\x9f\x89\xca\x0a\x4c\x68\xe7\xe3\x12\xc2\xb8\x69\x3f\xf1\x44\xc8\xa6\xa7\x10\x20\x20\xc0\x39\x11\x93\xe6\xcb\x89\x25\x19\xdb\xcf\x14\x61\xff\x28\xe0\x94\x9c\xf3\xe1\xb5\x12\x20\x2b\xc3\xb4\xd6\xc8\x02\x86\xf7\x2b\x36\x3f\xf4\x16\xd6\x97\xf5\x0b\xda\x34\xe0\xb5\x27\x0e\x99\xa9\xd8\x49\x76\xed\x9d\x0d\xe8\xf7\x52\x55\x72\x3a\x27\xf5\xe4\x56\xf8\x27\x6e\xa9\xdc\x20\xe0\x3e\x88\xc3\x28\x0a\x43\xc1\x62\x68\xb5\x75\x74\x18\x55\x69\x58\x93\x96\x5c\xd1\xaa\x02\x1d\x90\x9c\x6f\x55\x1c\xa5\x1e\xa0\x6e\x5a\x4c\x11\xc2\x35\xb8\xc2\xab\x28\x41\x05\x7b\x49\x22\x29\x8b\x3c\xb6\x84\xec\xde\xed\xe4\x1e\x52\x12\x1e\xad\xbe\x8b\x9f\x31\xda\xa4\x39\xda\x61\x83\x11\x7e\x2d\x35\xdd\x46\xbe\xb2\x32\x1c\xfe\x10\x91\x5d\xca\x67\x4b\xaf\x93\x5a\x3d\x1c\x9f\x13\x1a\xf7\xa4\xbf\xfd\xf5\x04\x13\x91\x33\x61\x8f\x0e\x78\x7c\x68\xc4\x9e\xf8\xd2\xd6\xde\xa1\x34\xb5\xf8\x51\x3b\xd1\x46\x1f\x54\x5d\x09\x85\x85\x5c\x39\xf8\x8f\xac\x8c\xd0\x15\xe5\xb0\x9b\xfe\x59\x94\x88\xe3\x3f\x1a\xb5\x4f\x24\xde\x99\x32\xb8\x22\xe8\x39\xdf\xa5\x8d\xe7\x12\xad\x29\x42\x0a\x36\xa8\x4c\xe8\xf7\x44\x04\xe5\x4f\xde\xe2\x37\x18\xd4\xe2\xd7\xa3\x34\xe6\x1c\xb7\x58\x8a\xa5\xc5\xeb\x27\x91\xe4\x29\xc9\x97\x33\x5d\x84\x7f\x34\x6f\x6f\xc0\x31\x82\x32\xdf\xfb\xc1\x53\xf7\x10\x7a\x89\x1a\xe1\x6f\xf7\xf3\xdf\x89\x1d\xf7\xa3\x7a\xab\x1e\x04\x36\x76\xa8\xc7\xf9\x98\x41\x5a\x90\xe2\x77\x5f\xf7\xe2\x7e\xcd\xb1\x0b\x37\x87\xd9\x95\x1a\x24\xda\x02\x7d\x6a\x34\x3b\x22\x81\xb9\x52\xa9\x00\x86\x10\xa3\xbb\x0c\xc7\x88\xe9\x52\xc8\x7c\xaa\x0c\xa6\x8d\x24\xef\x67\x40\x64\x6d\xe8\xc6\xa1\x40\x18\x89\xfd\xb6\x44\xc7\xb4\xb1\x15\x72\x39\x58\xe5\x14\x59\x49\xb1\x35\x3e\xda\x8d\xc3\x8f\x3e\xa7\xb7\xc9\xb6\xde\x78\x89\xbf\xc8\xec\x83\x40\x66\x11\x75\xfc\x25\xc8\xe8\x45\x81\xb9\x00\x66\xe4\x53\xad\xcd\xb4\x54\x4b\x99\x4f\xd7\xe1\xb0\x72\x69\x73\x4f\x4f\xf0\x2f\xc7\x47\x61\x39\x8a\xfa\xe9\xd6\x8c\x23\xc8\x7f\x08\x69\x61\xcf\xb5\x4a\xa2\x93\x4b\xae\x83\xb6\x28\x9e\x85\x2d\x89\x77\xf1\x8e\xc1\xb8\x3d\x37\x7c\xeb\xcd\x45\x5d\x02\x91\x0b\x3c\x4d\x11\xf3\xe8\x6e\x60\x80\xdb\xa5\x44\xf4\x35\x40\xfd\xc9\xb6\x16\xb6\xc1\x81\x4f\x10\x16\x38\xbd\x3a\x97\x68\xf6\x12\xf6\x62\x7c\x60\x0d\xbf\x59\x72\x4d\x31\x2e\x33\x12\x78\xed\xdb\x14\x4e\xd4\x26\x5f\x65\x99\xfd\xaf\x6f\xbf\x65\x8c\x40\x97\x50\x2f\x7d\x06\xbd\x79\xc7\xf5\x53\x55\xc5\x29\xfb\x61\x37\x00\xd5\xbd\x13\x28\x9b\x51\x5b\xdd\xc9\x3f\x25\x29\x93\xb7\xad\x3a\xcb\xfa\x6b\xf9\x41\x09\x83\xae\x50\xe8\x0e\xd2\xcc\xe9\x8c\xc7\x9d\xb2\xf4\x52\xe6\xfe\x92\x3c\x78\xc2\xf8\xf6\x5a\x2e\xd5\x9e\xe8\x8c\x1f\x7e\x71\xf8\xf0\xa2\x13\x55\xcb\xd8\xa6\x65\x69\x9a\x40\x29\x32\x2f\xb1\x59\x41\x5e\x3b\x1d\x4b\xed\x09\x8b\x65\x0c\xc8\x6e\xfd\x3b\x10\xc5\xe1\x7f\x6d\xf9\x45\xdc\x37\x8e\x65\xf1\xe9\x0c\x7c\xa5\xbe\x58\x59\x10\x6e\x5b\xa0\xab\x38\x79\x25\xbe\x7d\x68\x1a\xb6\xcf\x58\x05\x51\xe4\x4d\x8d\x49\xa0\x79\x83\xe1\x36\x1b\xb1\x5d\x6f\xc2\x6c\xda\x0e\x4b\xb6\xd7\x0a\xb0\xaf\xd9\x23\x11\x67\xa9\x91\xa9\x9a\x28\x2a\x73\x5c\x4b\xfa\x33\x1c\x8a\x59\x29\x2f\x59\x7c\xc6\xe9\xf3\x1b\x44\xaf\x34\xc8\x00\x14\x3d\x88\x7d\xce\x0f\x0f\x1b\xbc\x0d\x97\xfc\x73\x2e\x0e\x94\xa7\x41\x71\xe6\xb4\x28\x76\x30\x3e\x51\xae\xa6\x03\x9f\xaa\x33\x42\xd5\x0b\xe7\xdc\x25\x9e\x21\x0b\x10\x1d\xb0\x40\x66\x0f\x4b\x35\xc7\xb9\x86\x3e\xe7\x70\x7d\x34\x0d\xda\x3f\x91\xf7\x2c\xb4\xe2\xb7\x66\x43\xaa\xaf\x0a\x8e\x52\x0b\xad\x08\xea\xe2\xfe\x9f\xa1\x15\x70\x26\xb0\xda\x55\x23\x12\xb9\x59\x80\x87\x19\x2a\xbc\x63\xf2\x87\xe8\x56\x28\x66\x45\x91\x51\x29\x63\x0a\xf1\x18\xb4\xa7\x53\xf0\xbe\xf4\xdf\x1c\x50\x36\x85\x2b\x99\x61\x7c\x1c\xa0\x63\x54\x53\xbe\x36\x91\x5e\xdb\x44\xac\xb0\x35\x8b\x00\xd9\x43\xa7\xc2\xd8\xe7\x82\xae\x8f\xb0\x14\x96\xdf\x3c\x98\x02\x00\xcc\x7b\x6d\x1c\xdb\x99\xe1\x67\x2d\xee\xd6\xec\xb8\x18\x8e\xc1\x89\x39\x1b\xde\x68\x76\x6f\xb9\x46\x29\xad\xb7\xdd\xa3\x0a\xab\x23\xa1\x8b\xee\x95\xcc\x06\x3e\x9e\x8f\xf9\x3e\x78\x48\x4e\x55\xcc\xc1\x71\xcc\x7d\x84\x60\x64\x14\x08\x31\x6c\x61\x6c\x61\x41\x52\xbf\xe7\xea\x9a\xca\x34\x25\xa2\x73\x8a\x75\x06\xac\x56\x75\x95\x97\x6a\x5a\x5c\xe6\xfa\xef\x2a\x0d\x0a\x43\x8c\xb0\x2e\x13\x76\xd3\x08\x3e\x7a\x19\xde\xf5\x36\x3f\x08\x2a\x26\xe0\x87\xd3\x55\xc4\x31\x66\x58\xac\xe9\x07\xfd\x41\xdd\x5a\xa7\x1e\x8e\xf9\xe1\x35\x50\x79\xaf\x53\x8a\x5e\xf3\x0b\x89\x0b\xae\x46\xce\x53\x7e\x20\xef\x41\xe5\xeb\x7c\xda\x54\x91\x1c\xbc\x9d\x23\xbf\x7f\xad\xc4\x23\x90\xb6\x1f\x39\x16\x97\x32\x78\xfa\xae\x7a\x42\x1a\xb3\xa2\x7c\x28\xba\x74\x56\xff\x5a\x59\x1e\x31\x16\x4e\xb6\xa6\x2e\xdc\x2b\xf4\x55\xf2\xec\x7b\xd0\x10\x1e\x9e\x62\xf0\x21\xec\xb6\xcd\x8a\x86\xf9\x35\x13\xc1\x79\x50\xdd\xd3\xa2\xac\x88\x8b\x27\xad\x51\x78\xe7\x46\x13\xa9\x07\x87\xdf\xe9\xb8\xe5\x13\xec\x01\xbb\x65\xdb\x50\xe5\x4b\x4b\xf7\x01\x82\x1e\x1c\xac\x26\xd7\x8d\x5a\xe7\x6e\xc4\xf7\x41\x8c\xa9\x9b\xfd\x92\x16\xe5\xfb\xc1\x5a\xa9\x3d\x71\x28\x1a\xb1\x1a\x43\xf1\x22\x53\xce\x20\xc9\x79\x6b\x18\xaf\xaa\xc2\x25\xa0\xf0\x45\x09\x03\x6f\x18\x33\x1a\x0e\x2f\x75\x35\x5f\xa1\x3e\x83\xab\x3e\x71\xf9\xa9\xe1\x72\x95\x65\xc3\xc7\x8f\xbf\xaa\x6d\x07\x9f\x1f\x4f\x09\xbc\x8b\x59\x8c\xe5\x3f\x57\x3a\xd3\xd5\x3a\x4e\x93\xc2\x49\x9c\x6d\x52\x1b\xbc\x17\xe8\x78\x16\x33\x21\x73\xaa\xc5\x08\x7f\xdb\x02\xf4\x2d\x87\x60\xe3\x12\x2f\xc0\x56\xf0\x29\xe0\x52\x52\x3e\xea\xcd\x3f\x68\xf5\xee\xb4\xae\x9d\x3d\x16\x04\xc4\x58\x74\x3a\x1e\xf1\xf1\xaf\x20\x17\x66\xe4\xab\x17\x66\xdf\x74\x6d\x82\x68\x23\x8c\x6e\x73\xf9\x49\xc9\x89\x4a\x1b\x4e\x99\xa2\x2c\x1b\x62\x57\x1b\xa1\x1f\x7b\x9b\xc2\x70\x35\xdc\x23\xe9\x84\xbc\x1b\x24\x95\x68\x65\xa7\xc4\x80\x6f\x82\x85\xec\x8f\x05\xaf\xdd\x86\xf8\x79\x94\x09\x84\xcf\x9a\x36\x9c\xc3\xf9\x02\x65\x7c\xfd\x89\x67\x6e\x38\x99\x03\x6c\xde\x0b\xf6\xfc\x81\xbd\x0d\x7d\x13\x86\x43\x81\xe6\x73\xdc\x02\x2a\xe9\xca\x25\x04\x6d\x14\xae\x21\x45\x29\x59\xa2\xd5\xb5\xc8\x74\x1e\x5d\x76\x87\x87\x5f\x3d\xf1\xa9\x83\x42\xf7\xdb\x70\xdc\xd6\x62\x95\xa1\x93\x73\xd0\x38\x0c\xac\x72\x30\x7d\x67\x81\xa9\x2b\x23\x30\xb1\x70\xa9\xc8\x8e\x46\x45\x8e\x98\x1e\x60\x5f\x3e\xce\xe2\x08\x1f\x1c\x45\x6f\x83\x64\x12\x11\x17\x18\x6d\x48\xe8\xca\x79\xfb\xd1\x6d\x79\xd2\xd8\x84\x2f\x6b\xd1\x8b\x0e\x2f\xff\x13\x0e\x91\x65\xb0\x3c\xae\xa0\x29\x28\xf5\xa8\x52\x60\xbd\x44\x1b\xbe\xa7\x73\x53\x95\x2b\x3a\x9d\x8c\x44\xe1\xb9\xae\xdc\x99\xe6\x54\xea\x2e\xa0\xd4\xca\x41\x63\x16\x14\x28\x99\x30\x62\x75\xfa\x1e\x23\x70\x80\xab\x81\x13\xbe\x32\xa8\xb6\x0b\x92\x3b\x8d\xc4\x57\x07\x94\x45\x9d\xf3\x12\xa0\xf1\x70\x14\xa5\x0d\x08\xea\x39\x8c\x84\x2b\xeb\x40\x4f\x3d\x7b\x33\x12\x7f\x70\x8a\xfa\x99\xce\x53\xff\x0b\x75\xa8\xfa\x0a\xde\x03\xa8\x3a\xcf\x3a\x23\xf1\x87\x48\x75\x39\x12\x1d\xaf\x86\xe8\xf4\x48\xcc\x1e\x91\x13\xe4\x2d\x95\x0e\x10\xed\x6d\xed\xeb\xfd\xf0\x75\xa9\xae\x74\xb1\x32\xbc\xe9\xed\xfd\xfd\xe3\x8e\x0f\xc4\xad\x4f\xb2\xef\x2a\xc3\xd8\x49\x73\xe1\x87\x80\x25\x41\x99\xc7\x62\x96\x4d\x63\x1b\x64\xb4\xfd\x04\x97\x77\xa7\x5f\x2d\xae\x48\x09\x7d\xa9\xaf\x54\xce\x14\xb8\x2a\x5c\x72\x4d\x71\x3d\x57\xa8\xcf\xe3\x52\x34\x45\xe9\x8a\x39\x05\xa3\x3f\xb9\x40\x7d\xbf\xfb\xb1\xd9\xf0\xdf\x5f\x06\x7f\x7f\x85\x7f\xd7\xaa\xcb\xdf\x39\xbf\x38\x0f\x29\x9e\xf0\x7f\x8c\x03\x27\xeb\x60\xf0\x0e\x71\x59\xf6\x01\x26\xf3\x8a\x95\xc9\x61\xf9\x69\xc7\x2b\xf4\xe0\x1c\x11\x39\x20\xe8\xfb\x92\x18\xdb\xe0\x3d\x7c\xe4\x52\x57\xa0\x73\xa6\x43\xca\x33\xfe\xf4\x82\x26\x77\x48\x6e\x46\x54\x4a\x23\xaf\xe6\x9b\xc1\x60\xc0\x39\xfc\x1e\x8b\xeb\xb9\xac\x44\xad\x8c\x06\xbd\x7b\xe2\x13\x5b\xf8\x82\x0f\xe7\xe9\x23\xf8\xff\x1c\x6b\x63\x9c\xa7\xfb\xdd\xe3\xa0\xb7\x2f\xc5\x4d\xde\x9f\x16\x8b\x65\x91\xb3\xb7\xe6\x4d\xbe\xbf\x0e\xba\x81\x8f\x8e\xe1\xf3\x0d\x7f\xf1\x95\x30\xfa\x32\xa7\x96\xfe\x4b\x7a\xf7\xb5\xb8\x69\x7f\xf1\x17\xf7\xd1\xba\xfe\xea\x1b\xb1\x6e\x7b\x8e\x56\xf0\x76\x04\xad\x27\x54\xa9\x6f\xf7\xe1\x45\xb0\x45\x4f\xd8\x90\xd2\xc9\xab\x79\xb0\xfb\xc3\xa1\xc8\xab\x79\xff\x91\xe0\x2a\x6d\xc6\x2d\x99\xde\xd3\xb5\xec\x50\xc2\x1b\x3e\x43\x5e\xdf\x0e\x78\x10\xe5\x98\xf4\x03\x70\xf1\x81\x1b\xe4\xcc\xb1\x1c\xb3\x5c\x28\x2c\x25\x04\xb7\x42\x10\x94\x32\xc0\xcd\x77\x1f\x96\x6a\xa1\xb0\x1a\x14\x6a\x8e\x50\xcb\x31\x44\x6a\x30\x95\x98\xb7\x0e\xc4\x13\xa0\x4c\xd9\x1a\x4e\xdb\xc1\xf0\x30\xc4\xe8\x2f\x01\x56\xfb\x89\x3f\x43\xc7\xfe\x08\xed\xb3\x9f\xcd\xd9\xd7\x78\x9c\x0e\xbb\x62\x24\x1e\x8b\x47\xe1\xe9\x43\x58\x01\xee\x74\xfc\xe1\xb3\x8f\x8b\x34\xed\x04\xb9\x6a\x5d\xb7\x38\x9e\xed\xe3\x2f\x17\xee\x2c\x7d\x73\x41\x29\x32\xdb\x7a\x09\xc8\x08\xd5\x19\xc5\x54\x45\x70\xad\xcc\xf5\x44\x57\xbe\xa2\x15\x9d\xc3\x46\x6e\xe1\x70\x53\xee\xde\x93\xb6\x33\x1c\x9f\x5a\x57\xf2\x66\xdb\xb1\x45\x81\xe7\x06\xee\x3b\x76\x22\x70\x35\xe9\xc6\x16\x49\xbe\xbe\xc0\xf8\x2d\xa6\x37\x4d\xac\x8c\x0e\x39\x6b\xca\xfc\x4c\x1b\x0a\x1f\x9b\xd3\x2d\xb2\x67\x3d\xc7\xbc\x29\x96\x9a\xfa\xc2\xcd\xd2\xf4\xb5\xa9\x9f\x82\x10\x40\x9e\x0c\xde\x41\x5a\x43\x1f\xc0\xaa\xd4\x4b\x5e\x71\x58\x01\x0b\x69\x96\x5b\xfb\xf6\x2d\x72\x4d\x40\xc2\x22\xb7\x1e\x5e\xb2\x7b\xe3\x13\x5a\xa3\xa7\x51\x65\x47\xa3\xd4\xbc\xb6\xe0\x59\x52\xaa\xe9\xaa\x34\x88\xeb\x4c\x7f\x12\x6e\x18\x66\xc2\xb5\xbd\xf6\xe8\xd2\xec\x46\x9d\xcb\xf4\x0a\x2b\x71\xb2\xd1\x19\x18\x2c\x31\xcd\x0a\x64\x5d\xe8\x6e\x9e\x2b\xc3\xf0\x0b\x7a\xb7\x7d\xda\x62\x97\x89\xe8\x74\x3b\x3d\xff\xd8\x15\xef\xe5\x2f\xba\xa2\x5f\x7f\x19\x5a\x6d\x61\x26\xdc\x92\x92\xb2\xa8\x4b\xf2\x2f\xc5\xee\xc3\x6d\x3a\xf0\xdb\x74\x10\x52\x32\x3b\xce\x51\x63\x4f\xdd\xb0\xdb\x1a\x07\x38\x44\xe9\x3f\xc8\xa9\x80\xeb\xa9\x19\x56\x70\x59\x66\x8b\x4b\x6b\x11\x69\xb2\x2e\x09\x89\xf3\x7b\xb5\xdb\xde\xbd\xeb\x66\x7c\x12\xca\x0b\x96\xbb\x72\x8c\xc9\x7d\x5f\xe0\x2a\x4e\x24\xf2\x46\x2e\x54\x23\x1d\xae\x15\xb2\x38\x20\xb9\xde\xee\x63\x0c\x41\x4b\x02\xae\x30\x68\x2e\x1a\xd2\x86\x62\xb1\xda\x27\x4c\x7c\x20\x42\x8f\x17\x71\x6b\x15\x41\xdb\x82\xfe\x1a\xac\xb5\x0d\x7b\xba\x23\x39\x18\x0e\x6f\x5f\xd9\x0b\xa5\xc6\x60\x70\x49\xb1\x96\xe0\xa9\x08\x5e\x4b\xac\x4e\x97\x8b\xb1\xf0\xe5\x7a\xcf\x82\xb6\x9c\xb0\xf4\x28\xa6\x8d\xf6\x2b\xab\x12\x4f\x7c\x37\x51\x4d\xa1\xe4\xd7\x6d\x45\xe1\xa2\x11\x5a\x8a\x0a\x6d\xbe\xe8\x76\xc2\xf3\xe9\x67\x17\x85\x81\x7d\x0c\xaa\x3c\x2f\x26\x2a\xa1\x58\x17\x84\xae\x87\x42\x9d\x05\xbc\x7f\xed\xeb\x5c\x34\x34\x82\x9f\x16\x89\xc9\x99\x1a\x3a\x5d\xcb\x99\xda\x1d\xab\xf1\x84\x0d\x16\x9c\x14\xa5\x05\x17\xd0\xec\xb1\x85\xb0\x26\x76\xde\x15\x4c\x4a\xba\x12\x2f\x49\x81\x2c\x13\xab\xb3\xe3\x84\xe0\xb6\x3d\xa9\x5d\x9a\xd0\xb4\x53\x21\x90\xed\x8e\x3b\x71\xc2\x6c\xce\xf5\x6c\x1b\x35\x3e\x0f\x7c\xc0\x82\x70\x42\x1c\x72\x7f\x1c\x5c\x2c\xed\xc3\x8d\x3b\xe2\xd8\xcf\x70\xcc\xd0\xb0\xfe\x71\x8d\xa9\xf9\xc6\xbb\x1f\x69\xfc\x2b\x36\xa6\x16\x4e\xd3\xe7\xa9\xb9\x85\x3a\x95\x6f\x6f\xef\xe2\xd1\xa7\x75\xf1\x2c\xf0\x20\xa8\xf5\xf0\x45\x6b\x0f\x4c\x27\xfb\xf8\xdc\x7b\x7e\x7f\x6c\xf9\xff\xc0\xce\x12\x96\x57\x2c\x88\x29\xff\xf1\x67\xcd\x6a\xd3\x0e\xf4\xcd\xa6\x36\xc1\x03\x46\x4e\x3b\xc5\x7d\x8c\x2d\xf5\x1f\xec\x8b\x4e\xbf\xe3\xc6\xf0\x5e\x7e\x0d\xaa\xd5\x10\x8b\x2a\xd4\x69\x81\x24\xe3\x93\xf1\xb1\xe4\xdb\x13\x19\xb0\xb9\x21\x35\xe3\xca\xa2\x14\x3f\x5d\x63\xee\x77\x2d\x73\xcf\xac\xd9\xac\x28\xaf\x65\x99\xd6\x1a\xf7\xbf\xb4\x4d\xa1\x73\xdb\xb6\x98\xb1\x62\x0e\x45\x2a\xe2\x4e\x49\xa0\xea\xd4\x28\x23\xb9\x59\x39\x97\x4f\x9c\x21\x61\xce\x71\x70\xc1\xdb\xf2\x33\xc8\xdf\x8f\x50\xc0\x48\xf2\xee\xa7\x5d\x14\xbb\xbb\xb5\x5a\x2b\x2e\x29\xbb\x35\xfb\xef\xd4\x4d\x57\xce\xe0\x75\xb3\x08\x4f\x35\x7a\xf1\x00\x49\xed\x09\xac\x72\xff\x82\xfe\x46\x3d\x25\xe6\x3d\xa5\xbf\x31\xe9\x60\x4f\x98\x4a\x52\x39\x7d\xfc\x5f\xaa\xb1\x70\x17\xc1\x1b\xe0\x65\xc1\x79\x2c\x3a\x81\x6a\xaa\x23\xda\x34\x17\xb6\x13\x97\xb9\xab\xb6\x22\x9f\xb7\x9e\x6e\x72\x06\xff\xdd\x97\xa2\xfb\x68\x65\x94\x2d\x1b\xbf\x0b\x0b\xde\xdb\x13\xbb\xd4\x83\x23\x30\x51\x46\xa7\x80\xf7\xc2\xcd\x19\x25\x41\x4d\x4a\xe0\x7f\x1a\xb5\x28\x6d\x63\xb2\xa9\x13\x0c\x02\x97\x57\xa7\x5f\x05\x20\x85\xcf\x77\x02\x7d\xeb\x91\x7f\x5a\x57\xc7\xc2\x3f\x67\xf8\x71\x14\xc5\xed\x46\x64\x70\x70\x9e\xb4\xbb\x58\x04\x00\xdf\xc8\x37\x6b\x8f\xfc\xde\x69\xf3\xbf\xe5\xff\xdd\xfa\xbf\x83\x3f\x91\x3d\x24\x3d\x26\x15\x0a\xb3\xfa\xf6\x11\x80\xab\xff\x08\xb3\xcf\x5f\x2b\xf4\x5f\xb1\xa9\xfd\xd2\x22\x57\xc2\x14\x5d\xdf\x0b\x22\x94\x18\x0b\x42\x25\x97\xb4\xb4\x03\x7d\x74\xa8\x6c\x13\xb6\xd8\xdb\x8b\x51\xca\xcf\xcf\x4f\xa9\xc5\xcb\xd8\xdf\x31\x7e\xa8\xb3\x00\x4d\x39\x99\x95\xd7\xb2\x8a\x91\x7d\x06\x3b\x4f\x8f\x2e\x8e\x22\xd4\xc8\x8b\xbc\x0f\x28\x85\x47\x16\x71\x22\x19\x0c\x06\x5d\xcc\xdc\xaf\x0c\x27\xdb\xc7\x8c\xfe\x45\x2e\x7e\xa3\xde\x7e\x8b\xb0\xc5\x8e\xbf\xb7\x27\x1c\x9e\x86\x7b\x41\xe6\x92\x0f\xe2\x37\xc0\x91\xdf\x48\xca\xc1\x0c\xce\x78\x82\xb2\x35\x26\xe3\xb1\xf9\x43\xdd\x57\xfe\xf8\x0a\x9b\x93\x2c\xcc\xda\xbe\xd9\x88\xa4\xf9\x74\x2c\xfe\xb8\x0d\xca\x20\x4d\xf9\x73\xdf\xd7\x19\x6d\xca\x85\x2b\x02\x16\x60\x31\x65\x54\x1e\x73\x0a\xfc\x03\x12\xd9\x53\x5d\x96\xab\xdc\xa0\x3b\x26\x3e\x3f\x0c\xbe\xb2\xe9\xa1\xef\xfc\xe0\x71\x6d\x18\x3e\x0d\x34\x9a\x4b\xbd\x16\x94\xe4\x3b\x0b\xde\x87\x9b\xd5\x38\x54\xfb\xfb\x51\x47\x61\x1a\x0c\x3e\x6b\xc8\xcd\x46\x48\xfe\xbd\xcc\xb2\x89\x74\x31\x3a\xe8\x09\x16\x6e\x0c\xfa\x26\x03\x6a\xf9\xaf\x12\x5e\x66\x08\xa3\x03\xe4\xfc\xb0\xe1\x60\x59\x2c\x93\x6e\x37\xa6\x39\xe4\x7c\x36\x57\x39\x25\x8b\xed\xd9\xa2\x0d\x9c\x9a\x36\x40\x25\x94\xab\x26\xa5\x92\x1f\xfc\xb7\x4e\x8f\xdf\x12\x71\xb0\xbf\x8f\xd3\xb1\xeb\x85\xe7\xb5\x4b\x25\xc6\x1e\xb7\xe3\x70\x54\x78\x73\xa2\x4b\x00\xbb\xbb\x08\x29\x04\xce\xe6\xa8\x8d\x4c\xdc\x46\x47\xe7\x67\xa3\x5a\xd0\x58\xb9\x18\x92\x7a\x82\x6e\x77\x8a\x43\x75\x81\x3d\x31\x7b\x7b\x5c\x55\x41\x8c\xc9\x86\x5a\xc7\xf6\xfa\x33\xc4\xf5\xae\x5d\x5e\xd7\x23\x5c\x0d\x11\x43\xc0\x44\x08\x7b\x58\xa3\x04\x6d\x54\xc0\xde\xe5\x40\x3e\x5a\x9e\x27\x54\xd8\xf8\xb8\xcf\xd7\x48\xe2\xb5\xab\xcd\x2a\x63\xce\xea\x65\xdd\xdf\xb3\xa2\x58\x62\x4a\x9b\x09\x2a\xd3\x09\x21\x3f\x82\x8d\xff\xe4\x19\xf8\xd7\x70\x99\x7d\x5f\xfe\x9c\x4b\xca\xe3\x70\x8c\xb2\x68\x01\x82\xfd\xaf\xec\x41\x11\x20\xa0\xc9\xe9\x5c\xa8\x7c\x5a\xac\xf2\x4a\x95\x1e\xbd\xea\x17\x68\x2b\xe5\x85\x05\x13\x24\x62\x54\xaa\x3f\x8b\x51\x29\x3e\x29\xcd\xe3\x71\x1b\x82\xc6\x9f\xd5\x6d\x47\xb1\x71\x9c\xda\x6f\xe0\xdb\x96\x3b\x6e\x38\x14\x27\xf9\xb4\x28\x97\x45\x29\x2b\x02\x4c\x31\x9b\x19\x55\xf5\xe0\xef\x9c\x39\x71\x79\x29\x75\x6e\x2a\x31\x5d\x4f\x33\xc5\xc5\x6b\x02\x74\xef\x8f\x91\x65\x75\x13\x08\x92\xe0\xe3\x94\x89\xbd\x05\xb0\xd0\xb3\xff\x15\x30\xbc\x07\xe8\x46\x08\x4f\x87\xfc\xf4\xd9\xd8\x3a\x4a\x04\x93\xbe\xfd\xa8\x4e\x95\xf4\x4a\xbd\x46\x26\x70\x58\x22\xbd\xeb\x53\x76\x3a\x4c\xa6\x86\xfe\x76\x18\x70\xac\x73\x1b\x72\xec\x92\x4e\xb4\x06\xac\x3b\x83\xe2\xf0\x41\xd8\x9d\x2f\x25\xf6\xb6\xd4\x45\xa9\x2b\xfd\x77\x2c\xae\x82\x15\x0b\xc3\x60\x66\x9d\xd3\xb3\xe9\xca\x54\xc5\xc2\x85\x23\xc2\x3c\x64\x9a\xaa\x94\x22\x25\x57\xcb\xa5\x2a\xb1\x5d\xa6\x2a\x2e\xbe\x6c\x6b\x82\x04\x5a\x7b\xa3\x2a\xb2\xc4\x19\xa1\xf3\xb9\x2a\x75\xc5\xba\xcd\x30\xd8\x96\x6a\x58\x5c\x5a\xad\xb2\xf7\x02\xe3\x46\x67\x56\x17\x87\x28\x8b\x6f\x7c\xbf\xf6\x65\xdd\x43\xcc\x9f\xf5\x58\x2f\xde\x59\xe5\xec\x03\xa3\x6c\xc8\x2f\xb9\x17\xf1\x18\x71\x90\x28\xd9\x5c\xc5\x42\xae\x31\x99\x5d\x68\x64\x05\x2a\xa5\xf3\x94\x3c\x5f\x60\xb1\xf6\xab\x40\x23\x5d\x2a\xab\x54\xac\x0a\xfe\x98\xc3\x55\x50\xa9\x68\x91\xc2\x7e\xf9\x7e\x65\x2a\xa0\x82\x9c\x85\x3c\x2d\x42\x0f\xce\xb8\x54\x4d\x5d\x53\x3e\x8b\x72\xcb\x37\xf4\x9d\xdf\xad\x2a\xb1\xb0\x71\x20\x36\x5f\x2c\xf0\xb4\x45\x96\xa2\x51\x4a\xa2\x0a\x34\x1c\xcd\x7b\x46\x06\xfc\x34\x6c\x13\x12\x05\x8b\xc5\xf6\xdf\x4e\x27\xc0\xe8\x8b\x38\x29\x57\x6d\xc7\x06\xe4\x65\xf7\x96\xb3\xd3\x26\xed\x1b\xd8\x75\xa1\x83\x9f\x95\x02\xdf\x66\x14\x48\x6f\x9c\xc4\xc4\x11\xb9\x29\x67\xc1\xa7\xef\x1a\xa9\xef\xc3\xec\xf7\x4e\x75\xed\x28\x45\x7b\xe9\xb5\x9d\x1d\x9d\xc2\xb5\x51\x0b\x77\x08\x26\x96\x86\x95\xd7\x6c\x2a\x7b\x98\x9d\xa0\x74\xf6\x76\xfe\xfe\x59\xeb\x77\xae\x5a\xa7\x0f\x99\xdc\x2a\x48\x87\x18\x41\x02\xf2\x01\x2e\xd7\x04\xb4\xaa\xd5\x24\x34\xcb\xeb\xba\x6a\x3e\x7f\x23\xe7\xa9\xf2\xb6\xa8\x54\x5e\x69\x4c\x22\x3b\x2d\x40\x32\xbc\x09\x4f\x72\x27\x2f\xaa\xce\x68\x7b\xcd\x82\x9a\x46\x1b\x3d\x46\x34\x5f\xed\xf6\xe5\x92\xcb\x24\x15\x38\x80\xce\x1c\xb1\xf3\x09\x89\xe0\x1c\x01\xb3\x6a\x13\x6a\x02\xdb\x58\x95\x54\xee\xda\xb6\x46\x55\xab\x11\x14\x25\x38\xd1\xb9\xe4\x6a\xf6\x71\xc2\x09\x97\xea\xcc\xa7\x37\x73\x8f\x68\x23\x30\xe2\x82\x26\xf2\xd1\xca\x6b\x9e\x76\x84\xe6\x00\x55\x86\xe7\xf6\xd8\x76\xfe\x71\x9c\xbe\x53\xb3\x11\x64\x6d\xdb\xd9\x59\xe5\x1e\xc5\x79\x4c\xdb\x17\xf9\x3b\xdf\x2c\xb2\x9e\x38\xbb\x08\x90\x5d\x73\xf9\x84\x5a\x85\x87\xb6\x1a\x0f\xbe\xf7\xc9\x5a\xfc\xc6\xfd\x5b\xb9\x6f\xcb\xc1\x20\x36\x89\x3d\x7a\x5c\x07\x58\xd9\x21\x3c\x3e\x78\x1c\x74\x5c\xd9\x41\x5f\xb0\x0e\xa1\x05\xfd\xf9\x8e\xed\xb6\x9b\x1d\xb6\x02\x0c\xb7\x9b\x2c\x4a\xa1\x72\xc2\x81\x4a\x53\x70\x52\x00\x2b\xe7\xe9\x79\x54\x53\x4f\xb9\xfa\xb1\xc0\x1d\xc6\xc6\x89\xae\xbd\xf4\xe7\xd2\x7c\xc6\x29\xf8\xb4\x24\x93\xcd\x22\xdf\xd4\x2c\xf6\x5f\x6f\x99\x8c\x75\x0c\xdf\x3e\xa3\x28\x23\xe0\xa7\xcd\x26\x69\x3a\x8f\xb1\xeb\xf7\xc0\x7b\xaa\x6d\x36\x75\x57\xad\x50\x3f\xcb\xa3\x3e\xf3\xe1\x91\xf1\xc4\x87\x43\xd1\xf9\x85\x1d\x67\x82\x10\x7b\x8c\xea\x24\x47\x58\x76\x8c\x92\x62\x94\xc9\xfc\x32\xe9\x3a\xd8\xf0\xe7\xda\x70\xd1\x01\x53\x64\x5c\x63\x15\x28\x0d\xf7\xf4\xd0\x08\xf8\x6c\x25\x2f\x95\xad\xb5\x41\x95\x98\x15\x90\x14\xf5\xfb\x4a\x66\xd6\x56\x4a\xe1\x85\x33\xad\x4a\xf1\xc2\x3a\x9e\x17\xa5\x98\xa8\x4b\x9d\xe7\xd0\x1a\x39\xa2\x7a\x4b\xa1\x17\x0b\x95\x6a\x59\xc1\xd8\x94\xbb\x8a\x26\xdc\xe9\x77\x06\xdc\x0b\x16\x03\x03\x2c\xc4\xa4\x62\x33\xf1\xc2\x71\xb0\x77\xcd\x14\x56\xb6\x54\xe5\xac\x28\x17\x2a\x6d\x30\x87\xd9\x3a\xec\x3d\x9a\x51\x9c\xb5\x9d\x3d\x27\xa9\x02\x8a\x1f\x02\xbd\xdc\x3b\xdc\xc5\xc7\x38\x4c\xf8\xaa\x4f\x37\x00\x62\x1b\xfc\xae\x63\x5a\x80\x4c\xf0\x3a\x24\xff\xf8\x9b\xd6\x64\xb3\x75\xd9\xf9\xf8\x89\x7b\xa6\x64\xb7\xf4\x4f\xc9\xe8\x85\x1d\xa0\xe1\xa9\xbb\xcd\x11\x22\x62\xf8\xa0\x3d\xb1\x7b\x34\x95\x30\x32\x17\x9f\x8c\xf1\xc5\xbf\x60\x4c\xbd\xcb\x62\x05\x4f\x7e\x90\xf9\x25\xd3\x8d\xb4\x88\xf3\x0b\x24\xf6\x7d\x50\xcf\x2f\xf2\xed\xb7\xee\xfd\x38\xd3\x51\xf4\x28\x36\xc9\xdd\x2c\x32\x3c\x14\x64\x95\x6b\x69\x40\x2f\x6b\xd2\x6d\x30\xbc\xfd\xb3\x6d\xa1\xb1\x55\x97\x3e\x18\x13\xdc\xec\x68\xf8\xa9\x3b\xea\xf8\x86\x8c\x24\x6c\x68\xaa\x0b\x4d\xa2\xee\x32\x5e\x53\x99\x77\x23\xed\x78\x28\x43\xc7\x9c\x66\xd3\xf6\x12\x90\x93\xd7\xda\x4c\x55\x96\xc9\x5c\x15\x2b\x62\x57\x2a\x59\x5e\xaa\x2a\x92\xce\xa2\x4d\xe3\x4a\x1e\x73\x31\x16\xd7\x98\x10\x6b\x90\x15\x53\x69\xf3\x52\xd4\x1e\x01\x5b\x3b\x8f\x50\x01\x3f\xa5\xa8\x12\xe7\x14\x60\x2d\x47\x44\x2b\xd3\x58\x5a\x2c\x8b\xe2\x8e\xd9\x04\x40\xb7\x41\xbc\xaf\xec\x6d\xe6\xba\xc0\xec\x8e\x9f\xd5\x47\x4b\x42\x49\xaa\x9f\xed\xde\xcd\xa5\xf9\x1e\x93\x46\x52\x69\x90\xf8\x61\x42\xf1\x22\xbb\xbb\x89\xaf\xce\x65\x71\x6e\x5e\xaa\x19\xfc\xf8\x07\xbd\x92\x13\xd4\xb3\xc4\x86\xe1\x20\x11\x9d\x8f\xd3\xc1\xa5\xd8\x44\x4f\x9f\xb2\x98\x81\xcb\x6e\x85\x72\xbc\x4f\xb4\x61\xe1\xe2\x32\x45\x7d\x7e\x6f\x4e\xed\xee\x3a\xb3\x39\xd6\xb6\xf6\x85\xda\x0a\xf1\xe2\xf4\xf4\x49\x6f\x5b\x32\x3a\xcc\x07\x61\x5f\x01\x07\xeb\xb2\xd3\xfd\x1b\xd2\xd2\xd5\x7c\x47\xee\xb0\x33\x45\x08\x9c\xf8\x6f\xe2\x0a\x75\x6c\xa5\xe3\x21\xba\x4e\x93\xe4\xdb\x52\x8a\xbd\xb0\xb1\x5d\x5f\xcd\x2f\xc0\x3e\xbe\x13\x98\xcf\x5d\x91\x14\xf4\xff\x77\x85\x4d\x16\xf2\x83\x32\x0e\x72\xfd\xc9\xba\x1f\x14\x1e\xc5\x6b\x1a\xa7\x81\x81\xc1\x54\x07\x80\x2a\x95\x53\x07\x61\x2a\xc3\x1a\xc1\xf1\x74\xbb\xf6\xc2\x2d\x03\x51\xb9\x55\x8e\x8a\x56\xdb\x8e\x41\xc3\xa1\x60\xbe\x89\x51\x7d\xb1\xac\xd6\x77\x42\xe0\x63\x17\x31\xf6\x10\xdc\xc4\x68\xea\xa3\xfc\x99\xda\x90\x9b\x15\x71\x1f\x96\x91\x4a\x0e\x51\x75\x6b\xb3\x8d\x52\x70\x67\x02\x5c\xd9\x48\x3c\x39\x12\xd3\x54\x56\x72\x24\xbe\x3c\x12\x70\xe1\x56\x6b\x51\xaa\xd9\x48\x7c\xd5\x75\xc9\x48\x05\xa6\xd1\x04\x66\x62\xb2\xe6\x52\xd5\x22\x61\xcf\xf8\x91\xf8\xe6\x68\x8b\x6b\xfc\x48\xfc\xe5\x48\xa8\x6a\x3a\x70\xf9\xe4\x1c\x45\x7f\x2a\xbe\xe6\xba\xf8\x36\x49\x6e\x10\xef\x96\x3c\xee\xda\x72\x37\x72\xb9\x54\xb2\x44\xd1\xee\x4f\x0f\x31\x68\xc9\x25\x0d\xd3\x6a\x98\xa9\x43\x53\x62\x4b\xa6\x9f\x26\xc9\x20\x0c\xfa\x28\xf5\xd9\x8d\xf4\x5e\x8c\x17\x17\x51\xa8\x43\x80\x43\x4c\xae\x87\x51\x95\x4b\x10\x40\x94\x4c\x55\xf9\xd1\xc1\x4a\x6a\x67\x03\x96\x23\x17\xad\xda\x29\xa5\xa3\xff\xd1\x0e\x29\xbf\xcd\xa7\x74\xc8\x65\x1d\xef\xbc\x7a\x3f\xb1\x8e\xe4\xa7\x97\xd2\xb4\xa3\xb6\x56\x98\x8c\xe7\x07\x07\xe1\xee\xd9\x01\x72\x1e\x35\xce\xfd\x1d\xa6\x00\x3f\xad\x80\xb2\xf8\xb9\xe1\x88\xf8\x92\x5e\xb7\x94\xf6\xe1\xac\xb9\xea\x5a\x00\x53\xf8\x55\x10\x4d\x8f\x3c\xb4\x11\x89\x1a\x5c\x0e\x7a\xa2\x63\x94\x2c\xa7\xf3\x4e\xd7\x9e\x15\x14\x50\xda\xc6\xa3\x4e\x13\x91\x70\x58\x70\x0b\xab\x88\x7e\x20\xdd\xae\xf3\x9b\xda\x6c\x70\xdc\xb6\x05\xd2\x12\x1a\x68\x6a\xf3\xf9\xf4\x75\xde\x9f\x16\x59\xe6\xf3\xe3\x76\xf0\x88\x76\x46\xdb\xaa\x6a\x36\x4a\x2e\x31\xa8\xcf\xc4\x81\x2d\x45\xee\x04\x5d\xf4\x68\xf9\x78\x4f\x51\xa9\xc9\x9e\xa8\xe5\x9b\x74\xfd\x3b\xbf\xd6\xc3\xc6\x40\xea\xf7\x7f\x76\x98\x16\xa5\xbf\x1b\xd0\xbd\x79\x2a\x0e\xc4\xb1\xff\xb9\x6f\xa7\x32\xaa\xeb\x57\x83\x19\x5d\xa9\xfc\x5f\x5e\x3a\xea\xc5\x84\x63\xce\x89\x9c\x1e\x09\x2d\x9e\x72\x4b\xf8\x7b\x7f\x2c\x1e\xd7\x1c\xaa\x6d\xa9\xd0\xb6\xe0\xcc\x48\x11\xc6\x0d\x6b\x73\x2f\xd2\xf4\x4f\x9b\xfa\xe1\xff\xec\xd4\xb3\x7f\x1a\xdf\x5a\x10\xc1\xae\xe1\x33\xf0\x20\x5e\x6d\xbf\xaf\xd1\x24\x75\xf4\xe7\x2e\xf2\xf2\xff\xaa\x45\xee\xef\x87\x9b\xfa\xa7\x2c\x94\xab\x9a\xbb\xd0\x3c\x7f\xfb\xe6\xd5\x1c\x8b\x38\xd4\xee\xe4\xdf\xb9\xa0\x0a\xf0\xa5\x69\xca\xd5\x95\x83\x3b\xd8\x6b\xc4\x69\xd6\x1a\xb8\xcf\x3f\x44\x29\x53\x5d\x50\x3c\x1b\xfb\x13\x4e\x8a\x1b\xfb\x7b\xa6\x33\x65\xff\x5e\x4a\x63\xae\x8b\x32\xb5\xbf\xf5\x42\x5e\x2a\x1b\x08\xc7\x6b\x8e\xcd\x63\x1a\x2d\x07\x2d\x75\xab\x09\x08\xb7\xb5\x99\x98\xd5\x64\xa1\x2b\xdb\x7d\xa9\x8c\xaa\x3e\xb9\xfb\xb8\x2a\xb4\xeb\x9f\xca\xc4\x4a\xb3\x16\xcf\xdf\x9e\x50\x54\xaa\xd5\xd2\xe7\xea\x3a\x30\x03\x86\xf5\xd7\xdd\xc3\x84\x32\x78\x04\x26\x22\x9f\xbc\x61\x1c\x46\x08\x99\xda\x6e\x1c\xf1\x96\x05\x66\xc6\x71\x6d\x40\x8e\x8d\x72\xb1\x14\xce\x5d\x38\x78\xd2\xd4\xce\xc2\x2e\x94\x46\xfd\x98\x67\xeb\x20\xc6\x99\xd5\xd8\xac\xa1\xef\x51\xe8\x85\xe9\x91\x1b\x27\x60\x93\x29\xbe\x97\x65\x4f\x5c\x96\xc5\x6a\x69\x7a\xc2\xc5\x21\x92\x69\x93\xbd\x42\x38\x64\x83\x5d\x52\x9c\x3e\x38\xf2\x45\xa7\x2c\x7a\xd4\x3e\x0e\x52\xf5\xf3\x3a\x16\x07\x62\xc4\x8d\x6a\x91\xfb\x24\x91\xe0\x6c\x50\xcf\x4f\x43\xc0\x1b\x9a\x9a\x2d\xc7\xe0\x23\x25\x3d\x64\xed\x13\x9a\x88\x55\xcc\x50\x5f\x61\x3e\xc8\x17\x98\x3c\x99\xca\x5f\x95\xa6\x12\xe5\x0a\xaf\xf4\x20\x64\x4c\xa5\x28\x18\x2e\x38\x2f\x6f\x89\xe9\x96\x07\xea\x46\x4d\x5d\x7f\xb5\x74\x00\x71\xbc\x91\x4f\xf0\x31\x2d\x72\xca\x83\xc0\x56\x1e\x0c\xc1\x95\x68\xde\x41\x6d\x21\x35\x77\xeb\x85\x7f\x2d\x44\x5c\x08\x89\xbb\x33\x36\x1b\x6a\x11\x92\x07\x02\x0b\x93\x8e\x84\xf6\x15\x81\xd4\x8d\xf3\x68\x05\xa6\x44\x96\x00\x3c\x34\x42\x2b\x13\xe9\xf3\xc2\x95\xdb\xb7\xdb\xd6\x5f\xb3\xe0\x0c\x28\x93\x17\xd3\x30\x9a\x10\x4d\xcf\xe9\x13\xb3\x95\x1a\x39\x94\x74\x00\x7b\x21\x4d\x65\x53\xd5\x4a\xcc\x7a\xeb\x86\x46\xbf\x9a\xa5\x9c\xb2\x53\x04\x60\xed\xc8\xc3\xa7\x61\xd3\x12\x1d\x41\x42\x9a\xf5\xa3\xdb\x0e\x5f\x1f\x08\x54\xcf\x3a\xe6\x8e\xbd\xa5\xe1\x78\xa8\x75\x1e\x9e\xea\x18\x07\x1c\xd4\x7c\xc0\x18\x7b\xa3\xd4\x41\x87\x5a\x2a\x8f\xc1\x81\x43\x1f\xb3\xb5\xb6\xa7\x66\x1b\x87\x6a\xc1\x0e\xdc\xbd\x05\x6d\x7b\xd0\xbe\x09\x0c\x58\x47\x14\x7c\x4e\x68\x6e\xc9\x62\xa3\xed\xf8\xd3\xc1\xea\xa2\xdc\x9b\x07\xcd\x65\x81\x73\x1e\x36\x51\x5a\x0b\x8e\x77\xaa\xe6\xca\xde\xb0\x94\xd4\xce\x25\x3f\xa7\x48\x29\x6a\x8c\xee\xad\x0f\x4b\x45\xfe\x08\x40\x70\xc8\xb0\x1a\x26\x5c\xeb\x71\x2a\x75\x5b\xa9\x46\xb8\x84\x54\x4c\x15\x7d\xec\x7b\x40\xb1\x1c\x8d\xb4\xeb\x1a\xb9\x27\xac\xe2\x8e\x75\xf7\x81\xb1\x6c\x64\xf5\x05\xde\x33\xca\x0d\xc4\x9b\xc3\x01\x34\x9e\x86\x33\xb1\xeb\xc6\xd4\x91\xae\x7a\x5f\x53\xbd\x70\xe5\x82\xb8\xc7\x80\xe2\xfb\xfc\x15\x99\xca\x2d\xe5\xb6\x69\xb2\x89\xe4\xfb\xfc\x6b\x18\xe3\x51\xe7\x3e\x8f\x84\xde\xdf\xf7\x19\x90\x2c\xb1\xb7\x5d\x9d\xe9\x0b\x4a\xa9\x53\xcb\xe7\x14\xd0\xec\xdb\x68\xba\x32\x4d\x3d\xad\xb1\x78\x52\xf6\x82\x73\xde\x43\xb3\x57\xb0\x08\x72\x41\xf6\x0d\x06\xa9\xa6\xe4\x96\xc8\x85\xbc\x29\x72\x5b\xf7\x49\x8c\xe9\x53\xf4\x74\xe2\x20\x89\x30\xc6\xff\x3e\x66\x87\xcf\xad\x1a\x11\xfe\xc4\x24\x80\x61\x1a\x2a\x37\x08\xdd\x0a\xc7\x96\x3e\xc6\xfe\x59\x59\x61\xb0\x58\x0b\x27\xfd\x1b\x2e\x4b\x35\x55\x68\xcc\x0f\x9c\xda\x3e\xc9\xba\xdb\x66\x39\x68\xba\x97\x6f\xad\x11\xb6\xd9\x88\x06\x14\x1a\xda\x1e\x67\x28\x6e\x9b\x47\x53\x0b\xe4\x62\x15\x1a\xeb\x96\x59\x76\xc7\x9a\xcd\x27\x2f\x1a\x76\xb5\xc8\xd2\x17\x8d\xf0\x06\x9a\x4b\xae\xae\xad\xbb\x74\xe8\xbe\x67\x77\xee\x22\x70\x71\xfa\x05\x53\x0f\x3d\x44\x4f\x2d\x21\xcb\x89\xae\x4a\x59\xae\x9d\x97\xb7\x2b\xd1\x8f\x75\x9d\x31\x2d\x30\x55\x01\x9d\xa8\x5c\xcd\x74\x45\xce\x5c\x00\xed\xa0\x8c\x2a\x41\x3b\x32\xc1\x7f\xda\x2e\xfd\xb3\xdb\x14\x30\x0f\xdb\x76\x29\x72\x3b\xd8\xe2\x4f\x1f\x99\xa4\x68\x3b\x23\xbf\xd5\x7f\xf3\x22\x22\x37\xf7\x4f\x76\xfb\x3d\x8a\x60\x90\x58\xac\xa8\xb9\xba\xf3\x24\xad\xea\x09\x46\xe3\x86\xa8\x4a\xa9\xbb\xab\xfb\x97\x87\xf6\xa5\x45\x9e\xd8\x1f\x16\x93\x05\x62\x52\x83\xaa\x10\x0e\xed\x4c\xe1\x1c\x28\x26\x72\xfa\xa1\xbf\x2c\x8b\xa5\xbc\x44\xe7\xb7\xc2\xb9\x49\xc7\x76\x8e\xd0\xb9\xc0\xf6\x73\x26\x1e\xe3\x2a\xfd\x6c\x1e\x8b\x8b\xc0\x2b\xa4\xc5\xa9\xf8\x27\xb5\x32\x0a\x26\x32\xfd\x57\x26\xd2\x80\x1c\x49\x15\xf8\xe4\xa8\xb6\x7a\x66\x24\x16\x58\x9f\x88\xae\x4d\x80\xd5\x91\x90\x54\x57\xc2\xbe\x70\x36\xf7\x0f\x4a\x2d\x09\x0f\xec\x71\xf1\xbb\x57\x5f\xf9\x9d\x28\x5d\x8b\x9e\x69\x43\xea\xc8\x95\xb6\x05\xbd\xef\x73\x2e\xfa\xf8\x8a\x61\x78\xbc\xb6\x83\xf3\x2c\x6a\x39\x4b\xed\xd3\xd0\x4f\xf0\xf8\xb3\x28\x98\xf7\xb7\x73\xbd\x1c\x45\x34\x3d\x72\x2a\x0a\xf9\x9d\x12\xee\xcd\x8f\x1e\xf4\xcf\xd5\xd5\x13\x8f\xe1\x46\x38\xb8\x68\x40\x66\xb1\xca\x2a\xbd\xcc\xd4\x0b\x1a\xd2\x84\xcc\x06\x4f\xc3\xf4\x5a\xd2\xc4\xd5\xd9\x08\xdb\x36\x58\xf5\x5d\x6c\x43\xd3\xf9\xc7\x76\x80\x89\x71\x23\x67\xa5\xdb\xd6\x64\x62\xd1\x2a\xa6\x45\x9e\xaa\xdc\x60\xc6\x80\x40\xa4\x5d\xf6\xd8\x2f\xb5\x75\xcb\x22\xa7\xb3\x5c\x5d\xff\x1c\xf8\x9c\xb1\xcf\x5c\x7d\x95\xae\xf7\x90\x5f\x5a\xc8\xe5\x92\x79\xec\xa5\xd8\x0d\x53\xa0\xdd\x05\x81\x4f\xf0\x27\x23\xfc\x60\x89\x62\xb3\xe1\xb5\x7c\x0c\x49\xc2\x95\xb4\x55\x08\xe5\x9b\x05\xe7\xec\x31\x6b\x21\x97\x75\x35\x53\x74\xa4\xea\xd9\x48\xc3\x51\x1a\xdb\x61\x94\x3f\x6a\x4e\x52\xe9\x05\x9b\xed\x78\xbc\x65\x61\x2a\xfb\x9a\xfe\xce\x53\xfb\x77\x2d\x5f\x00\x85\x00\xba\xf6\x68\x87\xf5\x3f\x5b\x3c\x89\x83\xb6\xe3\x78\x4a\xfe\x85\x43\xb0\xa0\x77\x98\x41\xd0\x3b\xfc\xdc\xda\x7b\x9e\x6e\xe9\xbd\x6d\x19\x35\x64\xbe\xd3\x63\x92\x31\xbd\x9d\xd6\x00\xe6\x56\x6a\xb1\xec\x09\xdd\x0b\xfc\x26\x97\xa5\x7a\x2d\xc3\x7a\xb7\x30\x7c\xed\x49\xa9\xb0\x06\x85\x46\x9f\x18\xeb\xfa\xe7\x90\xd9\xf2\x50\x7f\x55\x95\xd0\xb9\xae\xb4\xcc\xbc\xd7\x24\x32\x46\x30\x3b\x67\x65\xbd\x21\xab\x34\xb4\x30\xec\x7d\x89\xe9\x47\xb6\xd2\x14\x74\x6c\x7a\xd4\x71\xab\xf2\xfc\xc4\xb1\x38\x73\x99\x60\x2f\xc4\xc8\x2f\x9b\x7d\x3c\xed\xcc\xde\x96\x8a\x0f\x44\x55\x60\x96\x54\xeb\xd4\xca\x1e\x8f\xe8\x48\x57\x5e\x51\x01\x4a\x38\x90\x70\x06\x61\x62\x7d\x4b\x53\xcc\x3a\x9f\xce\xcb\x22\xd7\x7f\x97\xce\x53\x9d\x3b\x39\xc9\x43\xd1\x1a\xa5\x71\xb7\xa8\xdd\x40\x72\x63\xdf\x25\x4f\x75\x10\x02\x38\xf8\x6b\x20\x3a\x01\xce\xd7\xb6\x8f\x5d\x9c\xa8\x3d\xaf\x8a\x07\xff\x71\xe5\xd3\x27\x5b\xd9\x91\xf3\x05\xda\xbb\x56\x46\xc8\x55\x94\x4c\x11\x54\xca\x48\x53\x94\x18\xf1\x88\x53\x0e\x90\x1c\xb3\xba\xf9\x7d\xb7\xa8\x45\x23\x04\x78\x8c\x61\x22\xf8\xf1\x71\x00\x85\x51\xf4\xf1\x66\x13\x1d\x1f\x1f\x25\x0d\x53\x1d\x0c\x06\x3a\xaf\x54\xc9\x5e\x82\x91\xc1\xdc\x88\x5c\xc1\x0f\x59\xae\xf9\x83\xb3\x0b\x1f\x01\xcd\x5f\x17\x2e\xfb\x39\x30\x3d\x76\xc7\x28\x66\x35\x5b\xbb\x4b\x90\x1e\x8f\x42\x1d\x47\x79\x92\x1f\x05\x2a\x9a\x3c\x15\xcb\x52\x2f\x80\xf1\x67\x4d\x85\xa3\xb9\x16\xc2\xb1\x9a\xca\x33\x05\x27\xb9\xa3\x4f\x3f\x02\x46\xb5\xc8\x46\x5e\x19\xf4\x7c\xb9\xcc\xd6\x01\x44\xdc\x28\x11\x90\x68\x20\x38\xb1\x74\x53\x32\xd6\x84\xa3\xd8\xa3\xca\xb4\xd7\x7f\x9e\xf0\x49\x3f\xbb\x68\x99\x8a\x3d\x15\x3f\xe7\x7d\x62\xda\x66\xac\x4d\x74\x87\x76\xb2\x16\x9c\x38\xb6\x9a\xab\x85\xb0\xd1\x91\x6e\xad\x74\xd1\x88\x31\x8e\xf2\x89\x2c\x8b\xbd\xb5\xe0\x93\x9a\x03\xb4\x5f\xd2\x99\x5d\xd2\x99\xbe\x10\xa1\x3f\x74\x79\x92\x37\xde\x85\xce\xd1\xb7\xed\x7a\x21\xc4\xcb\xe8\x66\x8c\x31\xd7\x23\x6c\x3c\xd9\xa0\x95\x9f\x26\x93\x38\x0a\x5c\xc9\x65\x16\x6c\x05\x46\x10\xd1\x16\x39\xef\x9c\x08\xa9\x75\x0e\x9c\xb6\xef\xd5\x32\x2e\x56\x55\xa6\xb8\xe4\xb8\x65\x59\x03\x9e\xf0\xc7\x55\x55\x0b\xc3\xf8\x14\x67\xf3\x00\xa6\x75\x6f\x73\x94\x0f\x30\x98\xd9\xef\x28\x17\xd5\xc5\x8f\xb9\xc4\xfe\x1a\x24\xe1\x70\xa5\xae\x03\xdc\x75\xd6\x11\xfb\xed\xf1\x0e\xeb\x6d\x11\x1b\xfc\xaf\x07\x41\xc2\x7e\xe6\x49\x44\xc9\xce\x2e\xba\x3d\xc6\xdd\x9a\x56\xc1\x91\x36\xcc\x33\x68\x99\xae\x96\x7b\xa6\xf2\xc2\x8e\x15\x33\x10\x8b\x3d\x09\x67\x6f\xb0\x3b\x81\xdc\x0e\xe3\xbb\x40\xec\x85\xca\x84\xb7\x33\xd8\xef\xe3\xd6\xe0\x18\x76\xa6\x18\xf1\x1d\x80\xdd\x60\xa2\x8e\x48\xba\xc4\xe8\x00\xe8\x92\x0e\x84\x4d\x11\x6c\x9f\x44\x31\x02\x75\xb9\xc6\x52\x9c\x34\x00\x95\x07\x50\xcf\xd5\xbd\x0e\xa6\xaa\x67\x82\x13\xdd\xdc\xaf\xe7\x36\x8d\xb6\xca\x91\xa4\x88\xa2\xe2\x3b\x9f\xc8\x38\x88\x5e\x72\x70\xb6\x99\x88\x83\x1b\xa2\xd7\xdc\x87\xa0\x2c\x9a\x7f\x87\x0f\x6c\x15\xd4\x6d\x07\xb5\x89\x63\x6e\xb9\x21\xf1\x0c\xf0\x2b\x16\xa1\x01\xb3\x07\x12\x68\x74\xd2\xf6\x65\x33\xd5\x6a\xb7\x29\x20\x51\xeb\xef\xcb\x62\xf1\x0e\xf5\x9b\x2d\x3a\x55\x94\x7d\x5f\x58\xe2\xec\x98\xdb\xf7\x77\xaa\x59\x39\xd6\xe7\x27\xce\x46\x6a\xad\x55\x36\x3b\xe9\x99\x55\xa7\x1e\x5c\x90\x8b\x0b\x4b\x24\x0b\xaa\xb7\x1d\x7c\x56\xef\xc8\x46\x14\xba\x9e\x3a\xa2\xe3\xc5\x99\x7a\x6b\x2c\x04\x22\x0e\xbc\x6f\xcb\x3b\x20\x8a\xc5\x2a\x4f\x25\x59\xc6\xdd\x85\xa9\x72\x83\x49\xc5\x30\x0c\x52\x85\x65\x55\x4b\x25\xa7\x73\xcc\xbc\xcd\x59\xde\x96\xfd\x4c\x5d\xa9\xcc\xd2\xc6\xc4\x74\x9d\x1c\xca\x60\x12\xe3\xba\xde\xf7\x13\xfd\x7b\x43\x58\xb3\x5b\x8e\xa8\x03\xc5\xa6\x8b\xeb\xb9\x51\x9f\xe7\xeb\x7f\x72\xe0\xf8\xb0\xc7\x3b\xcd\xed\x5d\xc4\xc7\x27\x4d\x85\x2c\x93\x67\x8d\x7a\x05\xad\x4a\x05\x17\x9d\xb2\x5b\xdf\x37\x64\x4e\xa1\x69\x50\x6d\x61\x77\xcc\x3a\xb2\x45\x61\xaa\x17\xae\x04\x03\x79\xb3\xd2\x89\x48\xc2\x15\x78\xb9\xbd\x1b\x70\xe2\xe1\x51\xe5\x86\x5b\xe6\x18\x9d\x6a\x0f\xe2\x6d\x12\x2a\xeb\x24\x2e\x3e\x55\x38\xf6\xf1\x6a\xed\x27\x43\xdb\x93\x51\xb7\x39\x32\x84\xe3\x7d\xde\xae\x03\x72\x47\xb6\x6b\xfd\x90\x5a\x28\x65\x6c\xb6\x6f\xce\xc1\x92\x19\x22\x53\xfe\xad\x0b\xe7\x3c\x6a\xe4\xea\xc3\x6a\x04\x32\x13\xab\x25\xca\xcc\x8a\x84\x96\xa5\xf3\x49\xb1\xd3\xf2\x34\xb2\x25\xfc\x2e\x34\x2d\x23\xdf\xeb\x72\x21\x5a\x78\xf9\xbc\x5c\x89\x9e\x09\x99\xaf\xbb\x28\x14\x91\xc7\xb0\x98\xcb\x3c\x75\x61\x86\x98\x9e\x7e\x7f\x5f\xf3\x1d\x64\xb7\xe8\xbd\xdd\xa2\xf7\x7e\x8b\xec\x94\xda\xb7\xe6\xbd\x05\x4b\xc8\xae\x44\xb1\xf2\xd1\xf5\xe6\x6d\x44\x6e\x7f\x1c\xf7\xf4\x8c\x52\x63\xdc\xb1\x7d\xf5\xa6\x81\xfd\xcb\x0e\xed\x0b\x72\x79\x1b\x05\x4e\x55\x5c\x4b\x23\x64\xbb\x79\xb9\x27\x74\x6e\x54\x59\x09\x99\xbb\x73\x0d\xf0\xeb\x5b\x8f\xe3\xdf\x1e\xb9\x64\x31\x4c\xdf\x7d\x0a\x2b\x8d\x9e\x76\xdd\xc1\xb4\xc8\xa7\xb2\x4a\xfe\x10\x6c\x59\x65\x00\xe1\xfb\xc7\xe2\x22\x70\x5f\x14\x1d\x71\x8c\x49\x0a\x47\xa2\xd3\x11\xb7\x36\xd5\x44\x77\x4b\x6c\x66\x6c\x89\x2d\x3d\x14\x9e\x8a\xf7\x2e\x65\x69\xdb\xc5\x65\x27\xa9\x7b\xe2\x3d\x1c\x4b\xfb\x25\xef\xf2\x96\x6f\xbd\x0b\x41\xdc\xcb\x7b\x54\xdb\xb6\xf4\xd1\x66\x85\xa4\x56\x91\x1b\x93\x53\x97\x12\x17\xea\xa4\xb3\xa3\x56\xb5\xd3\x76\x2c\xb8\xeb\xe2\xfe\x6b\x59\xac\x96\xfc\x8d\x49\x6a\x9d\x98\x5e\x80\x76\xe1\xad\x3e\x59\x9f\x62\xe2\xff\xe0\x6d\x10\x9b\x88\x2b\x9e\xac\x6d\x7c\xc9\xb8\xde\x6b\xbd\xa9\x59\x2d\x55\xf9\xda\xd1\x92\xba\xbe\x27\xa4\x95\x01\x97\xe3\xa8\x79\xa4\x66\x26\xf2\xfa\xde\xb3\x1a\x21\xdf\x96\xbe\x28\x56\x38\x21\xae\xf1\x87\xb7\x7e\xe7\xa0\xe3\x32\xdc\x7a\x2d\x27\x32\xd9\x7b\x7b\x3e\x42\xd8\x2d\x35\x0d\xe3\x86\x79\x6e\xdf\xc9\xe9\x07\xac\x0b\x58\xbf\x62\xbc\xab\xc6\x2f\x1c\xf5\x26\xb3\x6b\xb9\xe6\x7a\x68\x5c\xfa\x0f\xc7\x72\x5c\x43\x51\x06\x4b\x0b\x75\x49\x0d\x65\x92\x07\xf1\xde\x9e\xa5\xc0\x79\x7a\x86\x59\x46\x2f\x12\xd2\x26\x05\x50\xf2\x73\xf9\x19\xab\x58\x57\xea\x52\x95\xce\x10\xa4\x67\x33\x57\x6f\x01\x13\x6e\xb8\x0f\x43\x52\xbb\xc3\xcd\x7f\xc6\x9a\x29\x62\x2c\x12\xfb\xfd\xbe\xbb\x30\x2d\x30\xd8\x85\x98\xb8\xa8\xd7\xb2\x9a\x0f\x4a\x20\xcc\x8b\x04\x2f\xdd\x83\xc1\xa1\x9d\x11\xb1\x81\xb8\xba\x5a\x84\x32\xe5\x08\x6b\x6c\xf4\x4e\xe3\x26\x1f\x47\x17\x7d\x58\x74\x6a\x1a\xf0\x43\x51\x62\xe1\x50\x58\x58\x4a\x52\xc5\xd4\x10\xd5\xa9\x57\x02\x69\xc2\x7e\xff\xff\x07\x91\xeb\x37\xfd\x9b\x90\x82\x12\x6e\x72\xbd\xbb\x52\x51\x26\x88\xc2\xf7\x6e\x0a\x1b\x49\x4d\x08\xf8\x1b\x15\xcf\x9f\x28\xd1\x39\x38\xe8\x60\x81\xd8\x6b\xdb\x6d\xe8\x05\xfe\x6d\x8f\xe3\x58\xec\xcb\x77\x45\xa6\x30\x23\xca\x9b\x22\x55\x3f\x68\x53\x45\xd5\x8e\x4e\x5e\x8d\x44\x87\xe0\xd7\x39\xe2\x2f\x47\xe2\x69\xbe\x5a\x4c\x54\xf9\xac\xeb\x63\x4f\x43\x0d\x08\xbb\x53\x79\x8e\x03\xe0\xc7\x64\x2a\x34\x7d\x1a\x14\xdb\xac\x0a\x3f\x64\x48\x6c\x95\xd3\x10\x19\xe3\x68\x48\xaa\x8d\x53\x97\xeb\x03\x1e\xa6\x06\xf6\xb3\xf7\x51\xfd\x8e\x7f\xc6\xe4\xcb\x71\xdb\x4d\x15\x7f\x23\x2f\x4d\x5d\x76\xdf\x86\x72\x0e\xf5\x85\x33\x9e\xd2\x21\x68\xde\xda\xee\x9c\xbd\x2b\xe5\xf4\x43\x10\x52\xef\xe5\x78\xd4\xbc\x56\xac\xa4\x34\x11\x18\x81\xb2\x46\xea\x98\x77\x73\xb5\x26\x8c\x41\xa2\x71\x59\xe4\xca\x49\xb4\x32\xcb\x7c\x99\x7d\x4b\xf1\xdb\xc4\x78\x6b\x4b\xb3\xbb\x13\x01\x2c\x44\xce\x7e\x3f\x58\x90\x9f\x04\x55\xa0\x50\xe4\x55\x44\xb5\x66\xb0\x72\xc9\x95\x2a\x5d\x98\x91\xcb\x83\x41\xda\xd6\x2a\x9c\x47\xa4\xa3\x0a\x69\x6d\xeb\x26\xb5\x09\xf8\x5e\xa7\x18\x40\x0e\x0e\x66\x13\xbe\xc1\xed\xc9\x24\x7f\x7f\x2c\x74\x20\x50\x13\x94\xf7\xf6\x18\xdf\xa3\xa6\x6e\x92\x21\xd6\xb6\x20\x6d\x70\xf7\x35\x10\xd6\xa1\x6a\x60\x73\xf3\x17\xc8\x76\xa7\x92\x00\x11\x6a\x00\x43\xd6\x18\x69\x36\x12\x00\xcb\x66\x59\x16\xba\x02\x72\xa3\x17\xc0\x9c\x29\x66\x73\xb9\x60\x8c\xaf\x04\x5e\x3b\x48\xbc\xdc\x67\xe2\x20\xdc\x97\xad\xb9\x4f\xd0\xe0\x96\x84\xd6\x38\xf4\xad\x74\x8b\x6a\x28\xe0\x76\xa2\x77\xa8\x28\x5a\xb2\xa8\xd8\x48\xb8\xd0\x6e\xbb\xf6\x4b\x7f\xa9\xcd\x54\x96\x9c\x2a\x50\x20\xcb\x37\x2f\xb2\x54\x95\x36\x16\x86\x2d\x1e\x98\xe2\x5b\x4e\xab\x95\x93\x10\xec\x61\x88\xae\x6f\xaf\x67\x0e\x1e\xb7\x69\xe1\xe0\x92\x08\x40\x1c\x5e\x01\xed\x0a\x94\x5a\x7f\xae\xa3\x53\xa5\x52\xac\x03\x66\x94\xdf\x34\xb3\x9a\x4e\x15\x31\xdc\xd6\x2e\x44\xcf\x8c\x99\xad\x32\xcf\xc0\x99\x4a\x2f\xa9\xc6\x78\xb4\x99\x35\x4a\x85\x59\x26\x99\x6b\xf1\xd3\x08\x78\x2d\xaf\xbb\xab\xa1\xc0\x7e\x1b\x1f\xd7\xf5\xb9\x80\xf8\xab\x46\xb9\xb4\xe6\x46\x36\x0e\xec\x8f\x57\xaa\x2c\x75\x0a\xb4\x29\xa7\x45\x00\xff\x59\xcc\xc4\x65\x56\x4c\x64\x86\x57\x50\xae\xb0\xec\x4d\x44\xbd\xb6\x51\xe1\xbb\x69\xf0\x76\xb6\x80\x78\x92\xd6\x08\xce\x55\x60\xab\xdd\xa9\x55\x7b\x25\x3a\x71\x4c\x0a\x8a\x30\xcb\x41\xc4\xb2\x76\x5d\xe1\x3e\xf7\xcc\xb2\xdc\x9c\x4d\xc6\x3b\xa2\xfb\x07\x6d\x7e\xe8\x64\xa9\x18\x3e\x12\x27\x79\xa5\x4a\x90\x73\x81\x55\x43\x77\xca\x47\xc3\xd0\xc5\x80\xbd\x11\x3d\xa7\xe2\x78\xd2\x3a\x0b\xe3\x5e\x38\x87\x74\x9e\x42\xf9\x71\x9f\xf4\xdd\xd8\x29\x1d\x4d\x03\x39\x71\x20\xd2\x57\x27\x2b\x66\xc2\x95\x2c\x70\x4f\x59\x17\x36\xa5\xda\x46\x2b\x9b\xe5\x07\x1d\xe4\x28\xb7\x9d\x77\xfd\x0b\x9c\x3d\x62\x6d\x45\x54\xf0\xc0\x44\xc6\x62\x42\x35\xa7\xdb\x0e\xd5\xda\x6d\x24\xcc\x2d\xbe\x45\x7c\x23\xa7\x68\x9f\x82\x29\x70\xc7\x6f\xd5\x26\x84\x87\x85\x2e\x2f\x0b\xa6\x36\x3d\x6b\x5d\xf6\x69\xfd\xe2\x7e\x64\x39\xf3\x4e\xaf\xbc\x55\x69\x94\x3c\xac\x7d\x23\x1b\x68\xf4\xcf\xc8\x77\x5d\x6f\x28\x3c\x05\x5e\xc3\xc1\x1c\xb3\x2e\xd1\x56\xc8\x78\x1e\x83\xc0\x27\x36\x8c\x3d\x08\xcb\x95\x4a\xeb\x0a\x11\x95\xb9\x7b\x2e\xb2\xe2\x9a\xb5\xa1\xf4\x25\xe6\xde\x75\xae\xba\x80\x3f\x14\x22\x8c\x11\x8d\x74\x80\x1e\x1a\x07\x14\xec\xc4\x4f\xd1\x61\x5e\x54\xf7\xee\x14\x79\xf3\x8d\x3d\xb9\xb7\xbe\xfd\x73\xff\x27\x56\xc4\x5e\x96\xaa\xff\x91\xae\xc5\x64\xa5\xb3\x2a\x9c\xce\xc0\xe5\xad\x0a\xc6\x74\x55\xf6\x9c\xf4\x56\x2f\xc4\x77\x2b\xce\x98\x74\x5e\xb4\xbe\x04\x3a\x7e\x81\x33\xc4\xfa\x44\xa1\x51\x83\x0e\x06\xfb\x98\x72\x09\x3f\x9a\x68\xbd\xcc\xd8\x16\x1a\xe3\x78\x8f\xe0\xd2\x72\x67\x9c\x88\x8b\x8f\x75\x81\x7f\x39\xe4\x45\x80\x70\x49\x94\xc4\x62\xe5\xd8\x96\x13\x30\x51\x31\x09\x3b\x6a\x87\xae\x22\x1e\xf8\xfe\x3d\x7f\xaa\xdd\x45\xe5\x8f\x77\x12\xe0\x91\x1d\x60\x10\x3a\x47\xd8\xbf\x1d\x96\xfa\x34\x5e\xf6\x2f\x9b\xdc\x97\xdc\xd7\xdf\x95\x28\xb7\x2d\x74\xae\x17\xfa\xef\x56\xd7\x47\x19\x02\xac\xa8\x86\x56\x40\x02\x00\xa0\x38\xf2\x0f\xc0\x5f\xa3\x33\xb9\x25\x83\x21\x85\x09\x73\x4e\xf3\x49\x79\x27\x3f\x00\x3d\x34\x36\x11\x3a\xe5\x77\xa8\xf8\x00\xd3\x45\xc4\xb5\xd0\xcb\xa2\xa8\x3c\xb0\xb4\x11\x32\x17\x27\x58\x04\xc9\xa9\x90\x6c\x88\x46\x5b\x41\x14\xa6\x17\x54\xd7\x2f\xb4\x9a\x88\x67\xe2\x31\x4a\x6c\xa4\xb8\x1b\x7b\x03\x49\x37\xd0\xa2\x9d\xbc\xf4\xf1\xc8\xb6\x34\xe8\xa5\xaa\xbe\x5b\x9f\xa4\x81\xa4\x3c\xa8\x55\x33\xdc\x56\x50\x7b\x67\xa7\x5d\xbf\x79\x18\xeb\x37\x89\xfc\xba\xfb\x38\x09\x15\x15\x27\x2f\x3b\x17\xbc\x12\xab\x0c\x0e\x83\x53\xda\xd2\xf1\x74\x7b\x41\x01\x65\xdc\x6f\xd1\x25\xe7\x3d\xc7\xa4\xfa\xf7\x71\x1e\x2b\xef\x21\x67\xb9\x93\xb7\xa5\x72\xb8\xec\xb8\x2d\x94\xb4\x4c\x05\xff\xbd\x52\xa5\x9e\xad\xd9\x89\xbb\x5c\xa3\x5b\xb4\xa9\xd4\x52\xac\x96\x42\x0a\xa4\x5c\x21\xc5\xa7\x8b\xc3\x76\xe8\x86\x9f\xd6\x99\x91\x46\xc2\x7b\xcb\x91\xb4\x90\x52\xbb\xf7\x56\xb3\x48\x51\x2a\x14\x45\xb0\x35\x0c\x47\x21\x89\x20\xb4\x46\x61\xa9\x28\x45\xa9\x2f\xe7\x55\xbf\x2a\xfa\x99\x9a\x55\x4e\x17\x10\x5d\xa2\x54\xaf\x09\x24\x07\xc3\x0c\x94\x2b\xdb\x14\x7a\xf8\x60\x24\x5a\x84\x7e\x5b\xaf\xdd\x1a\x3a\xea\xd0\x19\xfd\xf9\xa4\x28\x2b\xc1\xd9\xd5\x75\x25\x64\xa0\x5e\xf6\xbb\x59\xc3\xb1\x84\xc3\x04\x09\x67\x30\x83\x7d\x78\x35\x07\xa2\xfd\xad\xef\x23\x01\x6c\xf3\x46\x8a\x3c\xf5\xc9\x93\x43\x13\xc1\x29\xc6\xd1\xf7\xf8\xca\xa7\xc0\x33\xda\x39\x80\x9f\xcd\x3f\x68\x38\x8b\x44\x3d\xd3\x20\x0f\x85\x30\x1f\x23\xad\xb4\x1a\xf6\xad\xf8\xbd\x25\xdf\x94\x55\x18\x97\x3c\x94\xad\xf8\x12\xdb\x3c\x31\x22\x0a\xde\x38\xcb\x52\x13\xbb\xe8\x88\x44\x3a\xc4\x5a\x1a\x28\x52\xfe\xe3\xa4\xb5\x11\x94\x42\x04\x85\x77\xab\x97\x2e\xd5\x42\xea\xbc\x67\xab\x16\x5b\x5d\xb3\x2c\x9d\xcf\x91\xc5\xcc\xa5\x53\x9d\xfb\x4c\x4d\x31\x46\x7b\x69\x64\x8b\x0e\xfc\x28\x94\x52\x77\x1b\xc9\xf3\xb6\x0b\x5d\x81\xf8\xd6\x72\xdc\x6b\xf2\x64\xa8\xff\x69\xf5\xe3\xa4\x08\x3f\x64\xd3\x81\x96\xab\x1b\x35\x5d\x11\xcb\x8b\x4a\x07\xd8\x7d\xc7\x11\xe8\x19\xde\x17\xec\x4d\xb2\x2c\x8b\x2b\x4d\x75\xd3\x91\xbc\xe0\x2f\x56\xfe\xfd\xe6\x93\x5a\x96\x2a\xe4\xa5\xf8\x0c\x2c\x8a\x94\xea\x6f\x47\x19\x32\x31\x47\xf6\xfd\x7b\x3b\x01\x61\xc1\x2d\xad\x25\xa9\xec\xb9\x68\xca\x6e\x42\xa2\x81\xb2\x77\xb5\xd7\x43\xd7\x6a\x88\x73\x01\x5f\xef\xf1\x56\x43\xb8\x00\xfe\x9f\x8f\x6a\x5c\x53\xba\xbd\xce\xf1\x50\xfc\x98\xab\x7e\xa5\x17\x4a\x48\x0c\x28\x60\xad\x0d\xbe\xc2\x42\xdc\xa6\x92\x13\x2c\x82\x7c\xff\x5e\x4b\x11\xeb\xb1\x65\xcb\x11\xeb\xaa\xa4\xd3\xe9\x36\xeb\x56\x0f\xde\x17\x3a\x87\x57\x94\x82\x8b\x3e\xb0\xe3\x3b\x35\xeb\x8b\x79\x59\x2c\xd4\xd3\xc3\x2f\x29\xc4\x9b\x94\xf3\x5c\x88\x3b\x28\xf3\x4d\xf7\xf7\x5a\xc0\x7a\x1f\x56\x41\xde\x52\xcb\xa5\xcb\x52\x9b\x80\x7b\xf5\xd3\xae\x17\xe9\x06\xee\x67\x37\x2c\xa4\x6d\xa7\x74\x42\x4e\xa5\xc0\xa9\x84\x79\x01\x39\xc7\x91\xbb\x83\x31\x72\xda\x55\xd6\xef\x36\x16\xf4\x8b\x9a\x7c\xd0\xd5\xd3\xaf\x9e\xfc\x65\xf0\xe4\xb1\xe8\xdb\x4c\x48\x5f\x0f\x0e\x06\x4f\x86\xb4\x5a\xf1\xf8\x2b\xa0\x89\x37\x58\x7b\x41\xd8\x67\x7f\xe9\x62\x47\x2f\x55\x45\xf2\x05\x25\x09\x9a\x16\x39\x7a\x3c\xe8\xfc\xd2\x65\x36\x14\x8f\x50\x82\x43\x8f\xc4\x47\xf1\x06\xb9\xaf\xc7\x00\x44\x55\x56\x81\xf7\x6e\xaa\xaf\x6c\x72\x61\xaa\x1b\x13\x24\xc8\x3a\xec\x61\x86\x21\xfa\x65\xc4\x97\x22\xa1\xa1\x74\x7e\xd9\xf5\x88\x04\x3d\x0c\x08\xda\xca\x82\xc0\xe6\x29\x48\x7c\xb6\x32\x0a\x5e\x67\x2e\x3c\xe9\xa4\xfa\x0a\x13\x06\xee\x61\xca\x88\xdb\x26\xc8\x28\xe1\x0a\xf1\x03\x57\x2a\xaf\x7c\xaa\x95\xa1\x4b\x3e\xd5\x41\x47\xb7\x65\x41\x1a\x8c\x0e\x36\xe7\x34\x4d\x0b\x93\xe6\x83\x85\x9e\x96\x85\x29\x66\x15\xd6\x03\x57\x79\x7f\x65\x86\x99\x9e\x94\xb2\x5c\x0f\x17\xe6\xab\x27\x5f\x7f\xf9\xf8\xdb\xff\xf5\xf8\x9b\xff\x3c\x1d\x7c\xf3\xd5\xff\x7a\xfc\xed\x40\x9a\xe5\xcd\xfd\x7b\x44\xe8\xda\x20\xc5\x80\x4a\xf5\x15\x25\xd9\x44\xc6\x6b\x2c\x3a\x4f\xa5\x98\x97\x6a\x36\x7e\xf8\xe0\xe1\xb3\xa7\x43\xf9\xac\x73\x14\x81\x27\x48\x83\x54\xcb\xec\x02\x5f\xf1\x59\xe8\x3c\xe8\x08\x84\x04\x0f\x22\xd3\x94\xca\x02\x27\x02\x13\xc0\x6c\xa0\xed\x66\xae\x80\x63\xd8\x5c\xeb\xb4\x9a\x77\xea\xe5\xc9\x7a\x5c\xd1\x4b\x9b\xff\x7a\xfd\x43\xe4\x9a\xb0\x1b\x3d\x8a\xd2\xe5\x44\x13\xe2\x0e\xf2\x2d\xe9\x73\x30\x11\x0d\xdb\x8e\x1e\x87\x26\xcf\x30\x07\x41\x64\x2c\xc1\x27\x3f\x1b\x77\x62\xfe\x93\xb2\x67\xe6\xa4\x2e\x44\x9d\x53\x04\x10\x64\xa1\x3a\x5d\xbb\x09\x16\x8b\x83\x34\x54\x9b\xcd\x67\xee\x0d\x3a\x5a\x0f\x69\x4f\x6a\x9b\x61\xa2\xb5\xf3\xe0\x3d\x57\x43\xed\x13\x76\xd0\x7e\x64\x8b\xbb\x76\xb6\x6d\xa1\xed\xfb\x33\x77\xec\x13\xea\xf4\xd9\xa4\x46\xad\x59\xf4\x02\xa8\x7f\xce\x6e\x85\x6b\xc4\x8b\xa4\x2a\xc4\x0c\x19\xd8\x09\x65\x0a\x34\xe2\x7a\xae\xf2\xa8\x9d\xc8\x30\x6d\xe0\x47\x4f\x4f\x00\xd5\x78\xef\x5d\x82\x40\x97\xe9\x68\x0b\x30\xed\x1c\x3e\x09\x9a\x20\x3c\x5f\xc9\xec\xe8\x13\xce\xc2\x19\xa5\xa4\xba\x70\x19\xe3\xc4\x71\xdb\x51\xb0\x5e\x44\xc9\x95\xcc\xda\x12\x36\x01\xc0\x12\xae\x7f\x87\xb7\xf4\x95\xcc\x06\xe8\x3b\x83\x9c\x84\xf5\x57\x82\xa7\x94\x78\x95\x3b\x74\xa5\x56\xe3\x4d\x8a\xd2\x0f\x23\x99\xbc\xed\x26\x9c\xfa\x92\xa5\x6e\xf8\x3f\xaa\x34\x3f\x60\xae\xda\xb5\xe6\xc7\xaa\xbd\xe2\x79\xdc\xe0\xac\x33\xc2\x6c\x2b\xc1\xa3\x20\xcd\x07\x3f\x5d\x59\x23\x73\x43\xf3\xec\xdb\xb0\x64\xc5\x2d\x38\x05\xb1\x7f\x8d\x1b\xf0\xb2\x98\xfa\x26\xf8\xc4\x37\xb0\x19\x93\x43\x0d\x2d\x3d\x71\xcb\xc5\xf2\x83\xa1\x54\x54\x9b\x37\xa9\x07\xc2\x06\x47\xee\x33\x03\xf7\xa6\x7a\x27\x2f\x41\xf4\x1d\xfe\xfa\x34\x39\xbf\xde\xef\x9e\x9b\x47\xe7\xc3\xe3\x67\xc9\xf1\xe8\xe9\xf9\xf0\xfc\xf0\xd9\xa6\xfb\xc5\xb0\x1b\x0f\xa7\xcd\xa9\xad\xff\x36\xfc\x75\x70\xf6\xeb\xe8\xc1\xf9\xd9\xf9\xa0\x77\xf1\xe8\x8b\xa1\xe3\x17\xe0\x3d\x1a\x81\x7c\x32\xe2\xa9\xcc\x1c\xa2\x4a\x60\x9f\x50\x74\xe1\xa8\x10\xe0\x65\xd1\x2a\xe7\x98\xd7\x6b\x9d\xe7\xc5\xb5\xd3\x0a\x9a\x9e\xf8\x7d\x25\x33\xcc\xb8\xdb\x43\x7e\x36\x08\x2f\x72\x00\xf5\x4a\x70\xd7\xd8\x9b\x5f\x19\x83\xb8\xf1\x65\xa9\x96\x61\xef\xf5\x33\xa4\xdd\xd1\x18\x3e\x12\xef\xcd\x5c\xe7\x95\xe8\xff\x72\x70\xf8\x8d\xe0\x52\xd8\xae\x4e\x9c\x1b\x8a\x2d\x48\xfc\xbd\xf3\x33\xdc\xc5\x2a\xa2\xec\xf5\xc8\xfa\xa1\x5b\xaf\xc8\xf6\x9f\x3b\xe5\xc6\x3f\x31\xe1\xa6\xeb\xa1\x73\xbd\x0c\x41\xf1\x91\xb9\xb0\xca\xcc\x7f\x11\x15\xed\x0c\x09\xb3\xc3\x02\x66\xc8\x5b\xe0\x5d\x9b\xbf\x0d\x83\x0b\xb6\xd1\x2f\x06\x37\x34\x54\x15\x04\x53\xf8\x84\x0e\xc2\x64\x33\xff\x0c\xd4\x1c\xd0\x62\xb7\xd1\xda\x48\xa2\xcb\xa5\x56\x42\x30\x7a\x0a\x15\x4d\x33\x52\x70\xc2\x51\xec\xd9\x68\x23\x8f\xbb\xd6\x27\xc8\xb9\x31\x70\x32\x39\xbb\x1b\xbe\xe5\x0e\x13\xae\xce\x28\x2f\x2a\x2c\xe3\x8a\x0f\xb0\xca\x6b\x63\xe5\xa1\xb3\x8a\xaf\x51\xd5\x16\x07\x8e\x34\x38\xa0\x98\x56\x11\xe0\xa5\x5f\xc2\x65\x1c\xac\x8b\xc1\x5e\x38\xdf\x0b\x31\x12\x14\x06\xd4\xfa\xb9\x5d\x70\x63\x0b\x3e\x8a\xb5\x2d\x93\x64\x54\xf5\xf9\x32\xec\x80\xf9\x40\xdd\x54\x2a\x4f\x31\x07\x0a\x0c\x3f\x6a\x51\x29\x87\xd7\x1f\x19\xa6\xac\x63\xf7\x5c\x47\x6e\xdd\x30\x83\xc0\x79\xca\xa8\x6c\xc6\xad\x8e\x82\x68\x96\xba\x4a\x79\xb7\xe5\x78\xb8\x70\x5e\x18\x61\xb9\x32\xf3\xd3\x4a\x4e\x3f\x58\x22\x15\x4e\xcd\x62\x74\x23\xb9\xe0\x8e\xcd\x92\x85\x59\xd4\xda\x3c\x6d\xad\x22\xa2\x76\x53\x60\xef\x33\x4c\x94\xd5\x23\x8f\xa9\xc8\xee\xdd\x12\x99\x1d\x7b\x33\xd4\x92\x0c\x7d\x7c\x1a\xc1\xee\x87\x02\x7f\x30\x0b\x80\x6b\x5d\x09\xf8\x86\xeb\x5b\x73\x76\xd5\x2f\x5a\x4c\x00\xa2\x0b\xaf\x8b\x85\x32\xf0\xda\x3d\xac\x8d\x44\xae\x89\xb4\x75\x75\x78\xc3\x3e\x63\x28\xb8\x88\xae\xec\x84\x66\x24\x46\xc1\xcc\x4a\x55\x85\xa6\x22\xec\xc9\xfd\x3e\xae\xfd\xde\xe7\x7a\xaf\xee\xc1\x28\xb2\x2d\x79\xc5\x02\x91\x87\x5e\x50\x6a\x7b\x3b\x7e\x6e\xc1\x19\xbe\x04\xe1\x71\x2f\x8a\xc6\x3c\xbb\xe8\x51\x38\x39\xef\x18\x0e\x93\x17\xd5\x9f\x3d\x06\xa0\x4a\x38\x84\x36\x9f\x30\xc2\xee\x2e\xf7\x49\x7a\x56\xe8\xd8\xab\x56\x4f\xbc\x2b\x5f\xe8\x34\x3d\x74\x6e\xcf\x01\x2a\xa0\x45\x96\xaa\x38\x99\xb9\x5e\x82\xc0\x84\x96\x0a\x1c\x86\xf4\xc7\xb6\x5b\x53\x88\x2f\x92\xce\x72\x44\x79\x3c\xbb\x03\x6d\xe0\x17\xa6\xe2\xec\x8a\x6b\xcc\x14\x12\x60\x3f\xb2\x1e\x12\xa4\x72\x2e\x99\x70\x5d\x88\xce\x92\xaa\x21\xec\xb4\xda\x8d\x82\xc2\xd5\x11\xbf\xd5\xa2\x83\xa6\x13\xd5\x3c\xee\x96\xc1\xad\xc1\x18\x1f\xe2\x5e\xc2\x5f\xdd\x40\x6d\x7d\xeb\x34\x02\x0d\x25\x0c\xe3\xb4\x28\x26\xef\xd5\xb4\x72\x4d\x9e\x8b\xa9\xca\xab\x52\x66\xa2\x54\x33\x55\xaa\xa0\xce\x3e\x9a\x77\x78\x52\x56\x1b\xd1\x65\x8e\xae\x28\x2a\x7a\xd3\xb3\x3a\xc6\xe7\xb6\xde\xea\xb5\x5c\x7b\xe3\x38\x40\x0d\x05\x4a\x82\x86\xb1\xaa\x44\x57\xc6\xeb\x81\x4e\x45\x71\xa5\x4a\xf1\xb4\x92\x97\xcf\xbc\x52\xf1\xbf\x4e\x4f\xc5\x95\x96\x22\x4a\x51\x2f\x92\x07\xdf\x7e\xf5\xf8\xb0\xcb\x3a\x97\xaa\xd4\xd3\x8a\xba\x2f\xd5\xb4\xb8\xcc\x11\x33\x44\xf2\xe0\xf0\xf0\xf1\xb7\x07\x23\xf2\x50\xa5\x0a\xa3\xb8\x67\x4f\x51\xf9\xf2\xfb\x4a\x4f\x3f\xbc\xa2\xdb\x71\xf8\x6b\x72\x3c\x3a\x37\x8f\x92\xa7\x67\xe7\xd7\xe7\xbf\x5c\xec\x3f\xeb\x9e\xfd\xfa\xec\xe2\xd1\xe6\x41\x72\x76\x7e\xdd\xbf\x78\xd4\xed\x7e\x31\xa4\x25\xea\x5c\x07\xac\xf2\x2c\x1f\xf0\x83\x3b\x8c\x92\xe1\x55\x82\x17\x1d\xdd\xe8\xde\x2a\xfd\x1f\xcf\xdf\xbc\xfc\xe1\xd5\x08\xf0\xb0\xd3\xed\x89\x2f\x12\x90\x64\xf0\x0f\x57\xb8\x1c\x7f\xd1\xb9\xf5\x82\xd8\xb6\x42\x2c\x7c\xf9\x84\x84\x93\x44\xbf\xfa\x1e\xb4\xdf\x4d\x6d\xac\x9b\x75\xdf\xa2\x26\xb6\x2a\x63\xe7\x69\x64\x0d\xf5\x6e\x17\x83\x30\xf9\x2c\x35\x7d\x16\x35\x75\x26\xbe\x31\xd6\x7e\xf6\xf6\x8a\xe7\xa4\xa5\xa4\xd2\x6b\x34\x51\xfb\x43\x96\x64\x86\x54\x39\x57\x70\x7b\xfa\x0c\xbd\x52\x71\x51\x68\x9f\xfc\xa0\x97\x7c\xce\x2f\xd5\x0d\xa1\x1e\x75\x6c\x4d\xb4\x67\x1c\xae\xe1\xf7\x08\xbd\x79\x9d\x05\x27\xf6\x72\xb0\x5f\x79\x5c\xb1\xf9\xdb\x62\xaf\x8d\xd0\x37\x88\x2a\x0f\xcd\xab\x45\x26\x8a\x12\xb3\xbb\x0b\xb3\x22\xd7\x59\x67\x36\x35\xc2\x4b\xb3\x70\x32\x1e\xb0\xbf\x6a\x90\x40\x70\x6f\x8f\xbd\xf2\xce\x0e\xd1\x25\xcd\xda\xff\x22\x43\x47\x84\x3a\x30\x64\x57\xf4\x9f\x89\x2f\x12\xf4\x64\xec\x06\x06\x1c\xd7\x93\xbf\xd2\x1b\xf6\x3b\x4c\x71\x2e\xf3\x29\xa0\x02\xd3\x88\x63\xfb\x0e\xf6\x7b\x14\x38\x1d\x7b\x3b\x8b\x99\x96\x7a\x59\x91\x7f\xb5\x25\x8f\x98\xa7\x06\x15\x9a\x55\x60\x90\xc1\x24\xed\x48\xb1\xb3\xb5\xc8\xd8\x92\x4c\x89\xd7\x26\xe4\xfa\x79\x8d\x46\x03\xcc\xb5\x86\x5b\xea\xcc\x0f\x58\x2a\x87\xbb\xe2\x83\xb7\x50\xe5\xa5\x4a\x04\xdd\x3d\xfc\xcc\x7d\xe9\xa2\x40\xec\xba\x5d\xcd\x28\xbb\xd6\x36\xc3\xb0\x5b\xed\xa0\xb8\xce\x55\x69\x55\xb1\x61\xbc\xd5\xc8\xa9\x63\x5d\x8f\xb0\x6a\xfe\x3b\xa8\x9e\xd5\xb2\x37\x3d\x74\x6b\x36\xdd\x90\x09\xf3\x92\x34\xdf\x06\xc1\x46\xed\xed\x79\xe9\xf4\x6d\x26\x75\xfe\x23\x52\xec\x80\xa5\x09\x19\x34\x62\xb8\x08\x77\x74\x5e\xa7\x3c\x76\x46\x6f\xbd\x63\x75\x31\x73\x8d\xa8\x3e\x63\x96\xa9\x54\x48\x23\x16\xaa\x9a\x17\x29\x1a\x07\xac\x0f\xee\xfd\xc8\x5f\xb2\x45\x66\x86\x6d\x38\xe3\xd1\x2f\x6a\x6e\xcb\x3b\xd1\x4b\x37\xfd\xa0\x79\x2d\x1f\xd1\x60\x30\x40\xaf\x05\x97\x1a\x00\xf3\x7a\x99\x20\x95\xbe\x6b\xdd\xc8\x9f\x84\x83\xa1\xb6\x33\xb1\xa4\xb6\x75\xbc\x9d\xd8\x2d\xb3\xc5\x3f\x33\x26\xa5\x2d\xe7\xed\x81\x4e\x79\x2f\x6b\xb3\x60\xc1\xcc\x29\xee\x2f\x55\xc5\x5a\xfb\xef\xd6\x27\xa9\xdd\xe3\xc7\x17\x35\x6c\xa1\x34\x6b\x81\xed\x09\x2e\x4f\x9c\x32\x6a\x0a\xbf\xcb\xe4\xf4\xc3\x44\x95\xe5\x5a\x7c\x39\xf8\xda\xda\x14\xfc\xe7\x64\xd8\x40\x4a\xc9\x9e\xfa\x59\x91\x5f\x62\x9e\x0c\xb2\xb8\x58\x74\x7e\xf0\xf5\xb7\x5f\x3f\x09\x91\x10\xe7\x6b\xe5\xbc\xb6\xfa\x11\x7c\x7e\x01\xfb\xc2\xa2\x4e\x3e\x8e\x00\x23\xe4\xe1\x4d\x8d\xb7\x08\xb6\xc4\x0a\x95\x36\xc1\xb5\xc5\x8b\x46\x45\x33\xbf\x03\xf8\x9d\x27\x53\x76\x01\x47\xe1\xeb\x2d\x6e\x5a\xcd\x0d\xdc\x89\xa9\xb4\xdf\x46\x12\x38\xbf\xc0\x5a\xbf\xdd\xfb\x75\xbf\x07\xe7\x76\xe1\x89\xc0\xe0\xfd\xef\xb8\xc8\xba\x23\x86\x3f\x98\x9b\x4d\xc0\x18\xb5\x48\x1e\x47\xdb\xe7\x61\xa9\xbc\x7d\x9f\x5c\xcf\x35\x9c\x68\x43\x89\x2c\xd5\xef\x2b\x7d\x25\x33\x54\x8f\x15\xf0\x95\x8b\xe6\xc4\x31\xa0\x8f\x6e\xcb\x3d\x16\xf2\xef\xd3\x82\x2b\x59\x80\x90\xbe\x5d\x3a\x8a\xee\xb5\x68\xa2\x2f\x7f\x7c\xcd\xe8\x8c\x43\x85\xd0\x72\x97\x7b\x5d\x1f\x55\xdf\x4b\xbf\xf5\xf1\xae\xb5\xa2\x4a\xf3\x24\x46\xf3\xb1\x8c\x57\x97\xdf\x9c\x5a\x8f\x25\x20\x89\x0e\xeb\x4b\x25\xd3\x75\x7d\xbe\x2d\x94\x2c\x60\xa9\xea\x4c\x15\x71\x49\x7e\x67\x07\xd8\x27\x49\xf2\x8e\x4f\xeb\x58\x2e\xbe\xde\xae\x8d\x9f\x1f\x0e\xc5\x2b\x36\xc3\x87\x95\xd6\xf4\x8c\xa6\xdb\x7a\x01\x1a\xa7\x61\xb1\xf8\x15\x72\x7a\xf1\x36\x44\xda\x06\x37\xc5\x78\x53\x5a\xbd\x73\x9a\x9b\xe2\xf7\xce\xb5\x0a\x63\x90\x78\xf8\x58\x83\x06\xcc\x0f\xfa\xfe\x85\x3c\x31\xe9\x16\x50\x48\xb1\x3a\xdf\xbf\x82\xf0\x46\x99\x5c\x75\x15\xba\x4a\x3a\x82\xe2\x73\x69\xa3\xd3\x8a\xac\x90\xae\x01\xbb\x52\x69\xf6\xdc\x84\x6f\xa3\x9c\xdb\x8e\x43\x6f\x31\x45\x37\x64\x9d\xfb\xf7\x82\x13\x3b\x76\x1a\x17\x87\x3e\x56\x98\x42\xa1\x87\x68\xa4\x59\x96\xea\xca\xca\x0e\xfc\x68\x03\xcf\x92\xe3\xd1\xcf\x79\xa5\xb3\xcd\xf3\x2c\xeb\x76\x41\x6c\x80\x8d\xb6\xd7\xea\xe5\x4a\x96\x32\xaf\x38\xdb\xc5\xb2\x2c\xd2\xd5\x14\xc4\x32\x36\x0b\xc0\x5d\x87\xf4\x1e\xd9\x5d\x74\xca\x28\x8b\x45\xf4\xfe\xfe\xbd\x1d\xdf\x89\x0b\x59\xc3\x2d\xb5\xd5\x64\x38\x31\xfa\x7d\xeb\x2a\x91\x57\x26\x78\x94\x63\x85\x1c\xf7\x13\xe6\x4c\x3f\xdd\xa6\x38\x43\x80\x53\x93\xa5\xba\xac\x97\x12\xe9\xc1\x05\xd0\x13\x2b\x58\x6b\x43\xc4\x89\x02\x0a\xab\x72\x95\x63\x8d\xe1\x31\xb7\x8e\xf0\x91\x0f\xf5\x9d\xa9\x29\x1b\x6a\xc8\x5d\xf4\xe2\x8b\x84\x93\x36\x3d\x65\x1c\xcd\xe5\xe6\xe1\x78\x2b\xab\x4c\x04\xa9\xdf\xad\xc4\x5f\x7c\x4d\xa7\x9a\x9d\xed\x01\x3e\xce\xdf\x26\x4e\x2f\x98\x1e\xf9\x6a\xb4\xec\x8a\x12\x42\x32\xef\x45\xfa\xcc\x3a\x00\x8f\x42\x7d\xda\x91\xc8\x8f\x44\x2e\xc6\x22\x6f\x2d\xfd\x43\xaa\xdf\x3a\x08\xf6\xf6\x44\x8e\xe0\x8a\xc3\xd7\xe2\x75\xe4\x6d\x4e\xdb\x2d\xcb\x70\x7a\x85\x56\x5d\xea\x5c\x46\x4a\x1e\xaa\x4d\x17\xe5\x30\xc3\x27\x26\x38\x61\xf4\xc4\x92\x05\xd6\xb3\xc2\x0d\x41\x2d\xe3\xc8\xc9\xf0\x1e\xdb\xa6\x01\xbd\xab\x06\x48\x5b\x84\x5f\x43\x0f\x4a\x22\x05\x8f\x8f\x0e\xf4\xcd\x7c\x8c\x81\x1e\x34\xf4\xb5\xea\x06\x5b\xcd\xf9\x81\xdb\x94\x5e\xa6\x55\x33\x30\x5d\x71\x58\xaf\xcf\x41\x48\x90\xa8\xeb\x9b\x9b\xe7\x6b\x59\xa0\xbf\xf0\x1d\xda\x25\x43\x9e\x4c\x35\x49\xdf\xc4\x6a\xe8\x2d\xfa\xa7\x60\xba\xd0\x45\x78\x1b\xb8\x9b\xec\xa0\x86\xa7\x2d\xe0\xa6\x57\xd3\x95\xd5\x93\x9e\xe9\x8b\x23\xfc\x09\xb2\xd8\x8a\xee\x28\x7b\xa5\x70\xb3\xe9\xaa\x6c\x65\x48\xbd\x4f\x13\x4a\xfc\x8e\x4a\xcf\x4a\x79\x19\xa4\x41\x25\xcf\xd5\x55\x19\x16\xc2\x3a\xc4\x03\x91\x00\xc4\xac\x1d\x79\x59\x18\x2a\xf4\x98\x4c\x57\x25\x27\xf1\x89\xf2\x94\x51\x02\xff\x25\x16\xb4\x2f\xf2\x7e\xe8\xb7\x4e\xd6\x55\x2b\x52\x87\x43\xd9\xc3\x67\xb9\xdd\xbb\x8c\x25\xb0\xf5\x1e\xdc\x35\x67\xc6\xf8\xa0\x02\x60\x9c\x00\xb3\xdd\xe7\xaf\x7e\x5a\x02\xad\xed\xa2\x1e\x42\xd5\xa2\xe8\xb6\x28\xd6\x15\x23\xff\x77\x80\xdc\xe4\x51\xa5\xca\x85\xce\xe9\xe6\xb6\xea\x58\x10\x2b\x83\x52\xb7\xd7\xba\x9a\xeb\x9c\x3e\xa8\xe6\x3e\xf5\x53\x2d\x02\x00\xd5\x6a\xa9\xba\x69\x2f\x56\xc5\x7c\xdd\x9b\xc2\x15\x54\xe9\x89\x30\x57\x0b\x7a\xc3\x20\x96\x38\x0e\x68\xb7\xdd\xb0\x49\x92\xe8\x81\xb8\x40\xd7\x3f\xfb\x23\x46\xb1\x63\x4b\x5e\x4a\x53\x25\xdd\x01\x5c\x8e\xcf\xb3\x2c\x71\x55\x8a\x47\x2e\xf7\x8b\x9b\x99\x9b\x45\x58\xbd\x37\xd4\xac\x39\x83\xea\x36\x8b\x4f\x6c\x3c\x8c\xaf\xa6\x5e\x30\xed\xba\x39\xe4\x87\x62\x6a\x43\x23\xc3\x1d\x20\x0f\x3b\xa3\x4b\x1f\x3d\x1a\x20\x44\x3c\x58\x53\xc9\xae\x81\x5b\x9e\x2a\x7d\xa5\x4c\x5d\x5d\xdc\xe3\x0c\x6a\xa5\x71\x09\x81\x80\x49\x5d\x19\x4e\xcb\x85\x57\x30\xcb\x47\xc7\x7c\x83\x1f\xa0\xd1\x0f\xfe\x86\x26\x21\x16\xc9\xb4\xd5\xf2\xd6\xa0\x8e\xed\x88\x7c\x3f\xb0\x22\x31\xde\x86\xf4\x2b\xd4\x10\x81\x08\x9e\x74\x7b\x0d\x43\x5a\x38\x12\xc9\x4d\xdd\x96\x39\x7e\x27\xa7\x1f\x3e\xd5\x3a\x22\xd3\x50\x8a\x72\xc9\x02\x3c\x1f\x0d\xf8\x44\x8a\x1c\x31\x12\xb5\x27\xf6\x4e\x73\x31\x21\x7e\x32\xee\xde\xf5\x29\x57\xe9\xf2\x47\x8a\x80\x9c\x18\x4f\xc7\xb1\x51\x8e\x84\x9e\xa5\xba\x24\x16\x2a\x22\x50\xbb\x96\x41\x0a\x63\x9a\x56\x65\xcd\x26\xad\xe4\x94\x6a\x45\xd0\x21\xd9\x56\x4e\x0e\x2e\x30\x6a\xd1\xac\x7c\x1b\xda\xb6\xb8\xcd\xde\x1e\xff\x55\x9b\x0e\x90\x22\x6e\x32\xb2\x0e\x4c\x64\x3e\x62\x06\x7b\xdb\xf8\xb1\xe0\x91\x6a\x67\x80\x0e\x93\xff\x07\xd6\x28\xee\x0e\xf9\xf4\x26\x5f\xab\x6b\x5c\xed\x27\xf5\xee\xbe\xf1\x56\x35\xe4\xb3\xef\x9c\xb0\xdb\x45\xee\x2f\x60\xeb\xa2\xe9\x22\x8b\xfe\x59\x3d\xd9\xd4\xe0\x2d\xbd\xc1\x20\xcf\xb3\xc6\xba\x3f\xbe\xda\x3b\x66\xf7\x4f\xf5\xf7\x91\x39\xfe\xcb\xbb\x13\xce\xb7\xb9\x3d\x30\xfa\xbf\x8e\x00\xb5\x25\x34\x87\xe1\x8d\xf9\x44\xd4\x75\xdb\xd8\xac\xe7\xba\xd9\x88\x3f\x6e\x51\x55\x63\x5d\x29\x7b\x81\xfc\x81\x63\x79\xf9\xef\xb3\xc6\x52\x71\xa9\xd1\xb0\x43\x27\x3d\xde\xd9\x21\x76\xc0\x6d\x43\xbd\x79\x4c\x8a\xcf\x2e\x7a\xdc\x12\x46\x79\x83\x0a\x4b\x47\xde\x42\x07\x0f\xf2\x42\x9c\xe5\x3c\x8a\x93\x35\xbc\x7f\x61\xd0\x18\xe1\xdd\x6b\xf5\xdb\xf0\x9c\xb2\xd3\x48\x2c\x2d\x83\x3f\xcb\xc3\xad\x72\x37\x36\xba\x2b\x72\x74\x52\xff\x2b\x76\xd8\xe9\x20\x9a\xf8\x5b\x3b\xd0\x99\x60\x17\x5b\x35\x30\xc8\x67\x7c\x8a\x75\xad\x31\x53\xeb\xb2\x54\x0f\x7f\x4d\x5b\xf4\x3d\xa1\xd6\xec\x59\x20\xf4\x62\x76\x85\xff\x8f\xbc\x7f\xef\x6e\xdb\xb8\xf6\xc7\xe1\xbf\x95\xb5\xfc\x1e\x46\x70\x8f\x4c\x5a\x14\x29\xd9\xce\x8d\xb2\xa2\xc7\xb1\x9d\xc6\xdf\xc6\x76\x4e\xe4\x36\xed\x23\xab\xee\x88\x18\x92\x88\x40\x80\x05\x40\x51\x4a\xe4\xf7\xfe\x5b\xb3\x2f\x33\x7b\x06\xa0\xe4\xb4\x3d\x67\xfd\x2e\xab\xab\x31\x05\x0c\xe6\x3e\x7b\xf6\xf5\xb3\x17\xe5\xa5\xf4\xf9\xf7\x82\xe2\x76\xac\x44\x70\xb3\xeb\xb1\x22\x36\x70\x85\x2d\xa3\xd7\x4f\xe6\xd2\x54\xb5\x51\x25\x04\x29\x00\xd8\x18\x12\xd8\x87\x60\x97\xb3\x87\x64\x2f\x35\x55\x76\x09\x86\x7a\xd1\x09\xa9\x4b\x21\x91\x05\xfd\x3e\xdb\x82\x6a\x85\x6d\xf4\x36\x0b\xaa\x1b\x38\x5d\xaf\x6d\x82\x3b\x14\x1d\x1f\xcb\x66\x3d\xcf\x40\x23\xd1\x1b\xbd\x3f\xd9\x1d\xcd\xbc\xab\x22\x99\x94\x01\x30\x4c\xd1\x5d\xcd\x49\x98\xa7\x65\xb5\x80\x00\xf0\xc9\xdc\x60\x55\xf4\x86\x33\x56\xfc\xe6\xb4\x5a\xcf\xcb\xe2\xd2\x54\x0d\xd5\xb5\x87\x5f\x36\x26\x15\x09\x9d\x5d\xfd\xf2\x6d\x61\xd9\xae\x22\x55\x88\xf2\x9a\x15\xdc\x98\xc7\xbe\x87\x40\x80\xb7\x58\x4b\xcf\x55\xe7\x3d\xc3\x90\x57\x53\x47\x41\xdf\x4e\x5d\xc1\x33\xee\xe6\x96\xbc\xe3\xf9\x35\x0a\x27\x3d\x31\x45\x7d\xe7\x36\xe2\xce\xdc\x87\x81\x9a\xe6\xda\x69\x1e\xb0\xc1\x53\x7c\x66\xab\x67\xf9\xf8\xa3\x74\x03\xc7\x52\xce\x75\x1a\xc3\xa5\x9f\xc3\x60\x94\x06\x03\x14\x80\x15\xe7\x59\xdd\xa8\x15\x61\xf1\x1a\xe5\x22\x26\x14\x44\x13\x5b\xa9\xa3\x1e\xdb\x4f\xed\xff\xb7\xa8\xd3\x63\x2b\x74\xe0\x6f\x9d\x63\x0d\xf6\xc8\x2d\xf5\xc4\xec\xd5\xc6\x7e\x28\x27\x1e\x63\xb0\xb3\x3c\x57\x93\xb9\x2e\x66\x46\xcd\xcb\x35\xd4\x66\x79\x34\x13\xf5\xe4\xdc\xcc\xb5\xe5\x84\xc1\xed\x63\x61\x97\xa4\xa9\x74\xca\x80\x7d\x58\xa5\x33\x78\x60\xaf\xd4\xb7\xd7\x2e\xc0\x25\x1e\x18\x34\xab\x27\x8d\xca\xb3\x0b\x03\xa2\x12\xc4\x66\x84\x85\xec\xf2\x23\xc6\x00\x54\x97\x4c\x2d\x27\x9f\x78\x38\x8d\x26\x5b\x98\x7a\xe8\x9a\xfb\x91\xa1\x72\x78\x36\xfc\xf4\x14\x13\x33\xde\xda\xda\x82\x56\x11\xce\x53\xb5\x87\x68\x9b\x82\x18\xe1\x73\xe0\xed\x61\x13\x4e\x8c\xea\x61\x17\xd5\x0b\x33\x35\x55\x65\xd2\xbe\xab\x76\x61\x16\x65\x75\xed\x2a\x46\x9c\x5e\x40\x05\x2a\xa7\x3e\x27\x09\x81\x98\x68\xb0\xd6\xdb\xc9\xc6\xd4\x41\xd7\xbe\x75\x9d\xa6\x18\x95\x0e\xd2\xac\x9e\x02\xca\xfb\xdc\x60\xaf\xe6\xba\x56\xe7\xc6\x14\xd4\x25\x88\xf4\x54\x7a\xad\xaf\xc9\xf1\xc6\x96\xb3\x14\xad\x51\x09\xf4\x27\xfb\xd5\xa4\x89\xab\x8c\xb3\x09\x6f\x1c\x03\x12\xb5\x78\x72\xc4\x72\xc9\x59\x81\x8e\xd2\xac\x14\xa5\x27\xa7\x6c\x5c\xb3\x1d\xf6\x55\xd7\x4d\xb9\x7c\x5b\x7c\xa7\xf3\xda\x8c\xb7\x20\xc2\xa6\x5a\x2d\x71\x8d\xc1\x9d\x01\xf4\xbb\xa2\x25\x8e\x0f\x22\x57\x1e\xac\x65\xe4\x58\xf0\xe7\x54\xae\x0e\xae\xbd\xe0\xd8\x73\x78\x1f\x52\x1c\x47\xac\xaa\x72\xd1\x26\x3f\x5d\x44\x27\x9b\x02\xb4\x0e\x87\xf8\xf5\xd6\x86\xfc\x76\x98\xfc\xa0\xcc\x67\x05\x12\xae\xdc\x45\xc9\xbb\x07\x2d\x55\x52\x6f\x23\x01\xba\xb9\xd9\x4c\xc5\xfa\x81\x77\x28\x69\x17\xd5\x6f\x1f\x07\xbe\x0c\x5e\xd8\x96\xd4\x59\x19\x58\xd7\x0d\xec\x11\xdc\x70\xaa\x37\x25\x54\xfc\x69\x59\xcd\x4c\x83\xb1\x75\x76\x81\x08\x93\x16\xf6\xee\x80\x04\xe8\xef\x2c\xc5\x6a\x4a\x75\x51\x94\x6b\x3b\x0b\x78\x46\x75\xad\x74\x8e\x26\x18\xd8\x7c\xa0\xd9\xb2\x3f\x6e\xfd\x2c\xab\xad\xfc\x64\xaf\xb3\x1c\xbe\xa3\x40\x64\xfc\xe5\xbe\x04\xd9\xd9\x2d\x7d\x53\x62\xd7\x7b\x80\x25\x92\x11\x3e\x8a\xdd\x74\xd7\x76\xd3\x71\x6e\x4a\xf3\x73\xd6\xcc\xfb\xbe\xb6\x93\x46\x57\x0d\x57\xf9\xb2\x48\x59\xe8\xcf\xcb\x72\x89\xdb\x2b\x6e\xff\x07\xaf\x40\x04\x53\x48\x6a\xae\xc0\x05\x20\xea\xb0\xef\x59\xcf\x45\x6e\x9e\x5f\xab\x0a\xd9\x08\xb7\x4d\x44\x57\xa0\x2a\xae\xf7\x19\x82\x14\x05\xe4\xc5\xbe\x82\xf9\x71\xfa\x4a\xb8\x60\x89\x5a\xc0\xe8\x6d\x79\x84\x0f\xab\xcc\xd2\x68\xb1\x64\xb6\x78\x0d\x65\x8f\xd4\x36\xdf\x50\x70\x0e\x3d\x8a\x21\xce\xaa\x27\x6a\x35\x2f\x57\x70\x5e\x20\x1d\x98\x63\xb7\x60\x13\xf8\x1b\x72\x48\x0f\x76\x76\xa0\x1c\xa9\x8e\x81\xee\x1c\x09\x65\xaf\x18\x31\x44\x43\xbb\xa5\x00\xe8\x3f\x59\x06\x9f\x1e\x85\x0f\x7f\x60\xc3\xa6\x1d\x5a\x00\x59\x4e\x93\x1f\xb4\x45\x9a\x54\x98\xba\x9d\x1d\x25\xdb\x7e\xaa\x64\x85\x87\xf2\x5d\x4b\xbf\x6d\xbf\x3f\x0d\xbe\x76\xc8\xb5\x76\xa8\xa0\x9f\x19\xd0\xcf\x03\x60\xfe\xec\x41\x06\x52\x04\x69\xb4\x68\x82\x04\x4d\x93\x88\x60\x3c\x8f\x98\xa0\x48\x01\x9a\x1f\xdc\x00\xa0\x8e\x5d\x55\x80\x04\x89\xcb\x8b\x57\xba\x4e\xd3\xdb\x95\x97\x7e\x2e\x44\xd2\x23\x37\x92\x68\x70\xb8\x35\x22\xcf\x66\x78\x38\x8c\xf2\x6b\xd3\x7a\xf2\x5b\x42\x1c\x68\x63\xb3\x09\xeb\x30\x0d\xce\xd7\xe0\x76\xf1\xe1\xbd\x2e\xbf\x8f\xda\xe4\xd3\x21\xc5\x60\xf5\xba\x92\x1b\x44\xa7\xc4\xd3\x75\xef\x2f\x41\xde\xe3\x8e\x7f\x7f\x66\x69\x80\x3f\x4f\xc0\x84\xf8\xfc\xf3\x70\x82\x5d\x2d\xe4\x83\xc1\x67\x2e\x52\xaf\xb5\x77\x45\x88\xc3\x06\x84\x09\x22\xe2\x6b\x4d\xe6\x58\x22\x0e\x94\x6e\x93\x8a\x5a\xaa\x5b\xd3\xee\x6e\xed\xe3\xad\xad\x9e\xcc\xf2\xd8\x53\xba\x9a\x05\x09\xe2\x02\x8e\xd3\xbe\x8c\xb8\x4a\x5d\xcd\x02\xe7\x21\x30\x1a\x05\xf6\x5c\xfb\x57\x0f\xcb\x79\x3f\x1e\xa7\x6c\x8d\xa1\x5a\x02\x47\x24\x14\x7b\x78\x47\x93\x41\x95\x32\xbd\x4c\x87\x73\x5d\x53\xbd\xe1\x57\xb0\xec\xa4\x7d\x8f\x9a\xf5\xfe\x43\xc1\xc6\xb1\xa5\x76\x76\xec\x3f\x12\x19\x80\x95\x5c\x2d\xd9\xcf\x7b\xd8\xd4\x4b\xcb\xb7\x3b\xd8\x29\x07\x46\x80\x8b\xd9\x6a\xde\x7b\x2f\xf9\x6d\xdc\xef\x39\x2d\xb9\x80\x1e\x00\x23\x86\x5d\xdb\x82\xec\xce\xf6\x6e\x91\x8c\x20\xef\x1e\x5f\x9e\x17\x9f\x8e\xe3\xb9\x95\x0a\x8e\xe5\x31\xa3\x17\xe1\x01\xbb\x95\xca\x21\x62\xac\x65\xde\xe8\x12\xf6\x69\x5a\x8b\xd2\xb5\xd4\xcc\x4d\xe1\x8b\xdb\xfd\x88\x31\xd5\xc0\x3e\x7a\x2e\x90\x07\x7c\xdb\x81\x8d\x88\x31\x6c\xdb\xc3\x90\x1c\xf0\x37\x9d\x51\x0d\x6d\x1f\x22\x3c\xc3\x42\xb2\x16\x87\x13\xa1\xf0\xe5\x09\xc4\x6b\xf3\x53\x0f\x61\x7c\x36\x56\xad\xc0\xa3\xf6\x01\x01\x6b\xa7\xa5\xea\x6e\x58\x4e\xff\x4b\x66\x09\x77\x70\xb2\x82\x7c\x31\x74\x35\x1b\x40\xdb\x03\x2a\xd2\x57\x32\x75\x85\xdc\xf5\x0e\xfe\x02\x2e\x79\x09\x81\x21\x9d\x8a\x69\xe1\x32\xcc\x49\x1f\x1e\xca\xf6\x2e\xa1\x17\xd8\xf4\xd3\xa3\xe0\x2a\x8b\x4e\x9e\x7c\xe5\x11\x3c\x83\x73\xd7\x59\xd9\x2b\x1a\x56\xbb\x2e\x78\xb3\xa1\xaa\xb6\x33\x60\x48\xc4\x6f\xdb\x0d\xe8\xbc\x97\x4d\x95\x56\xb3\xec\xd2\x14\x7e\x57\x40\x36\x19\xb7\x2d\x86\xf7\xbc\x9d\xa5\xf0\x06\x2d\x5b\x0a\xbe\x73\x96\xad\xf5\xdc\xc0\xdd\x89\x98\xa3\x5e\x22\xf2\x07\x56\x37\x08\x4a\x80\x55\x46\xa6\x77\xa7\x3b\x13\x39\x04\x0b\x6f\xe7\x73\x7b\x61\x5a\x0c\x78\x1b\xa2\xdd\x53\x6d\x6f\xf7\x1c\xcf\x21\x4e\xb0\x53\xfa\xb4\x0e\x40\x9e\x8b\x4e\xb5\xcf\x00\xa0\xaf\x74\x1d\x81\xf8\x36\x8d\xa8\x07\x63\x94\xde\x32\xe9\xdf\xf3\x45\x05\x55\xa5\xa5\x9d\x29\x80\x02\xd6\xc5\xb5\x95\xd4\xa1\x1c\x5d\xc8\xb7\xf4\x80\xf9\x4b\xc7\xcc\x48\xcf\x94\x3b\xba\xf0\xaa\x56\x59\xa3\x38\xf0\xfa\x58\xb6\xd8\x79\xf9\x72\x9c\x8b\x6d\x3a\xae\xeb\x87\xd2\x0a\x04\x3c\x9c\xac\x50\x59\xe3\x24\x0a\xdb\xc9\x06\x07\x94\x97\x81\x39\xca\x03\xf8\xd1\x30\xe2\xde\x13\x0e\x61\x4c\x1b\x6f\xe1\x56\xee\x1e\xb0\xed\x03\x0f\x17\x7f\xdf\x36\x58\xe8\x59\xeb\xc4\x80\x36\x20\xd8\x3c\x4e\xae\xa7\x23\xc4\xee\xc9\x45\xea\xc9\xa1\xe3\xcc\xed\x3d\x22\x77\xbc\x03\x80\x0b\x59\x0e\x4f\x68\x21\x7f\xc6\x36\x32\xf5\x37\x37\x8e\x75\xf4\x33\x02\x1f\x1e\xe1\xf7\x8c\xb9\x26\x5f\x9c\x86\x6d\xa0\x96\x58\x1d\x8b\x3f\x7a\x7d\x35\xc6\xef\xcf\x0e\x6f\xbf\x2a\x91\x0b\x75\x4c\x85\xb8\xaa\x63\x97\x66\xbc\xa6\xa2\x32\x9f\x4c\x96\x78\x92\xc3\xbb\x3e\x9a\xe8\xf6\xe4\x76\xee\x2f\xbb\x61\x78\xe6\x59\x8b\xde\xe6\x35\x6e\xe9\xcd\x3b\x2f\x30\x87\xfd\xc1\x5c\x77\x24\x71\x83\xce\x87\xdd\xd1\x2d\xf3\x69\xe5\xfb\xb2\xa0\x94\xff\xb0\x7e\xb7\x6d\x36\x5c\x61\xa9\x23\x0e\xb0\x4f\xed\x28\x5c\x40\x68\x87\xa3\xdb\xbd\xcf\xb6\x58\x57\x14\xd0\xd3\x55\x31\x09\x1c\x99\x56\xcb\x1c\x50\x6f\x4e\xb1\xf5\xd1\x48\x69\x28\x3a\x00\xd6\xca\x6e\x38\x53\x98\x6a\xe0\x7e\xd1\x85\x8b\x29\xb9\xfc\x61\xde\x3a\x55\x49\x65\xea\x32\xbf\x04\xdc\x8c\xb4\x2c\xec\xbf\xb1\xe2\xa7\x97\x80\xc8\x8b\x67\x38\xe9\x0f\xdc\x37\x69\xa2\x38\xb6\x01\x2a\xb2\x62\x84\xad\x67\xaa\xb3\xfc\x13\xeb\xb1\x9f\x44\xf5\x14\x65\x93\x4d\xaf\x13\xb0\x6e\x95\xb3\xca\xd4\x75\x67\x5d\x5c\x8d\x3a\x83\x2f\x39\xfe\xb5\x41\x47\xbf\x64\x69\x00\x5f\x27\xe1\x3c\x94\xe5\x22\xab\x9d\xa3\x22\x95\xeb\x5a\x48\xb7\x52\x0d\xc2\x08\x6d\xf9\x3d\xb4\x85\x69\x06\x3a\xbf\x4a\x69\xd5\x86\x76\x0e\x03\x26\x78\x68\x67\xa3\x93\x2d\xee\x70\x11\xa7\x86\x2c\x13\x2a\xd7\x7f\xf4\x50\x4d\x8b\x17\x65\x01\x66\xa9\xef\x74\x96\xdb\x7f\x7f\xa4\xd9\xf1\x28\xb6\xcc\x92\x4d\x0b\xa2\x24\xd8\x62\xd4\x1e\x4d\x25\xef\x33\x01\xf2\x51\x98\x35\x3c\xdd\x28\x32\xe1\xbe\x93\x3c\x61\x36\xc0\x87\x2d\xb1\x69\x5a\x08\xde\x4f\x78\x38\x4f\x31\x19\x09\x85\x98\xf0\x5f\x01\x5f\xc7\x73\x79\x0a\x79\xa0\xd5\x0d\xa6\x81\xbe\x51\xbc\x1d\xd4\x19\x22\x30\x94\xd5\x5a\x57\x80\x1f\xa7\x19\x1e\xb7\x74\x63\x70\x15\xfa\xda\xa0\xa3\xa7\x07\x67\xea\xac\x23\x72\x99\xfb\xed\x62\x34\x8f\xec\x10\xa0\x8b\xac\xb0\xd8\x44\x73\x1c\xa1\x75\xdf\xca\xe0\x19\x3f\x74\x7e\x3d\xe4\xdd\x18\x8b\x7a\x71\x81\x5e\x5f\xbc\xdc\xa2\xad\xc5\x03\x1c\xd2\x21\x54\x61\x21\xdc\x6d\xa2\x10\x18\x63\xc2\x32\x3c\x91\xa2\x1c\x1e\xba\x50\xba\x6c\x45\xb7\x6c\x71\x71\x9e\x4b\xf0\xae\xd9\x55\x89\xa5\xc9\x89\x3a\xc3\x29\x02\x21\x98\x87\x78\xec\x9b\x70\x83\x22\xd7\x93\x01\xf2\x84\xa7\x7e\xda\xce\xf0\xfe\xea\x98\x5e\xc1\x26\x8b\x0c\x81\xfe\x27\xee\x78\x87\xc0\x02\x2f\x7d\x83\xd1\xe9\xa2\x6c\x8c\xda\x75\xd2\xee\x26\xe8\x39\xef\x15\x57\xee\xd5\x54\x95\xe7\xbf\x58\xfe\x98\x51\xe8\x06\x94\xd5\x07\xbf\xd4\x28\x33\x67\x35\xe9\xe8\x49\x09\x22\x23\x50\xa8\xa8\x3c\xce\xb6\xca\x16\xc1\xb1\x0f\xb7\x5d\x7a\x8f\x48\xff\x5c\x9e\xff\x32\x50\x7e\xdb\x8c\xf9\x77\xa8\xe6\xc1\xf1\xf1\x20\xbc\x39\xd0\xe7\xd6\x58\x66\xcb\xce\x20\x39\xaa\x6e\x08\xef\xdd\xea\x0d\x2d\x1d\xf2\x35\x3c\xa3\xab\x65\x8f\xc2\x07\x27\xec\x55\x7e\xef\xb3\xdf\x4f\x27\xec\x59\x23\x0e\x98\xf6\xd2\x23\x77\x09\x00\xed\x25\x23\xa8\x7b\xfd\x58\x49\xa0\x4b\xea\xe1\x2d\x24\x82\x34\x00\xac\xf1\x73\x1f\x78\x2a\x20\x8a\xc8\x98\x18\x94\x2a\xfd\x25\xc9\x5a\x3d\xd7\xa5\x80\x83\x07\x9f\xab\x0e\x72\x32\x1a\x29\xbe\x8b\xec\x0e\xc7\xfb\x52\xdd\x28\xbe\xf2\xe8\xda\xf2\x37\x96\x68\x41\x46\x7c\x9d\xd2\x17\x1f\x60\xb2\x6e\xb8\x2a\xfc\xf3\x8c\x59\xe8\x43\x37\xf2\x0f\x28\x35\x95\x1c\x7a\xfa\x91\x26\x1e\xe8\xec\xdf\xd5\x81\x3a\x83\x99\xe6\x0f\xfd\xdb\x47\xfc\xc6\x7e\xdb\x61\x64\xf7\x74\x94\x09\x0f\x0f\x46\xdd\x28\x22\x1f\x67\xc1\x06\xe4\xb9\xde\x3f\x0b\x7d\x26\xdc\x24\x75\x14\xec\x24\x26\x6e\x47\x1f\xbb\x33\x30\xfe\x1d\x1c\xe0\xe1\xa6\x5e\xf9\xc6\x78\x2b\x30\x83\x49\xe0\x1d\x7e\xef\xbf\xd6\x17\x86\xa1\x03\xb1\x2f\x8e\x7c\x04\xe7\x87\x48\x8e\x2f\x26\xea\x00\x76\x18\x79\x5e\x60\xe8\x30\x3b\xda\x3d\xf6\xa3\x90\x4c\xde\x96\xfd\x83\x5c\x24\xb9\xaa\x41\x58\x69\x90\xa4\x33\xcf\xe1\x20\x6c\xdf\xf3\xee\x08\x5c\x38\xf6\x9b\xa5\x2a\xe6\x26\x5f\xc2\x2d\xb9\x8e\x78\x8d\x7a\x75\x5e\xda\x5b\xd5\xee\xca\xd1\x43\x35\x50\xc3\xe1\x70\x20\x9f\xbe\x11\x0c\x47\x98\x9a\x7f\x8b\x76\xc6\x5f\xd0\xfa\x79\xa4\x40\x2c\xa1\x61\x88\x95\x72\x78\x26\x28\x6b\x07\x5f\xb5\x93\x83\x23\x1a\xe4\xaa\x00\xa3\xfa\xaa\xb0\x44\x2b\x37\xf6\x04\x89\x3e\xd5\xd4\xfc\x42\x67\x05\x52\x0d\xaa\x1d\xdd\x0c\x31\xd3\xb4\x18\x58\xf7\x05\x2d\x4a\x04\x77\xf4\xb1\x72\xde\xb7\xfb\x51\xc7\x16\xba\x6e\x4c\xe5\xa6\x75\x68\x6f\x8c\x70\x16\x26\x65\x51\x93\x47\x00\x66\xd2\x50\x18\x75\xeb\xbe\x19\x60\x70\xdd\xaa\xc6\xb0\xf3\x61\x4c\xc4\xc5\xa8\x10\xfc\x26\x18\xc9\xb8\xc5\xcf\xc9\xf4\xe5\x7f\x5e\xa6\xb6\x90\xd3\x8a\x03\xe9\x2f\x9b\xb9\x3b\xc3\xe8\x1f\x43\x44\x13\xad\xd6\xf0\xed\x0a\x3e\xb4\x53\x13\x98\xb1\x32\xe7\xb3\x5a\x0f\xd8\xc2\xde\xd2\xf4\xb8\xd2\x68\x11\x6d\x05\x7d\x13\x03\x78\x24\x39\x5f\xb2\x98\xf3\x1b\xb7\x59\x42\x3f\xf1\x0d\xfb\x49\x8d\xb1\xa9\x40\xea\xa5\xde\x11\x33\x02\x03\xfc\x4b\xd4\x61\xc1\xb6\x23\x01\x43\xd9\xb2\x3d\xc2\x48\x3a\xa6\xbc\x2d\x6a\x6f\xcf\xaf\x4d\xbf\xb3\x5a\x9a\xe6\x3b\xeb\x25\x5a\xed\x45\x56\xbe\xb3\x44\xbf\x07\x6e\x1c\xcf\x5d\x45\x54\x3f\x3f\xf0\xb4\x46\x8a\x81\xc0\x17\xbb\x83\x2f\x4f\xcd\xa1\x6a\x2a\xa3\x1b\x0c\x76\xae\x95\xae\xdd\x4d\xe5\xa8\x52\x87\x63\x57\x34\x9d\x47\x96\xc5\x53\xa4\xd1\x0b\xd5\x75\x71\x87\x6f\x2b\x1b\x0d\xe5\xb6\xa2\x51\x2a\x4f\x30\x42\xb6\x43\x6b\x82\x63\x88\x1b\x6b\x13\x5f\x1e\x17\xec\xe4\xd0\x37\x17\xf3\x7c\x3a\xf1\xe8\xfe\xf4\xc0\x91\x89\x86\x36\x88\x28\x44\xdf\xb3\xe7\xc4\xbe\x8b\xfd\x13\xb2\xef\x82\x75\x8f\xda\x68\xef\x8d\xd6\xae\xef\x77\x1b\x0e\xc5\x2e\xde\x18\xcc\x31\x1a\x85\xc6\x92\xb5\xce\x20\x3a\xb0\x2c\xec\x15\x06\x6a\x4f\x37\x2a\x41\x17\xdd\x2e\xda\x96\x07\xe5\xb7\x80\xc2\x85\x67\xe4\xae\xa9\xea\x08\xf7\x74\x15\x05\xfc\x7e\x84\x41\xf3\x4e\x5e\xdd\xe0\xed\x50\x16\xea\xc5\xdb\xd7\x1c\x99\x8b\xa2\x9f\x4e\xaf\x7f\x40\xd5\xa8\x0c\x31\x43\xc5\xd0\x51\x97\x7e\x9b\xb8\x62\xa9\x4f\xf2\x8e\x6d\xf0\x9d\xef\x15\xed\x8d\x69\xe1\x73\x2d\x48\x4e\x65\x53\xe8\x23\x6a\x3d\x6d\x0b\xae\xbb\xf6\x3c\x53\x02\x98\x63\x75\x62\x1a\x10\x3b\xaa\x95\x41\x17\xa1\xac\x51\xe5\x64\xb2\xaa\xea\x21\xe0\x1e\xfd\x64\xbf\x18\xa3\x39\x5b\xc0\xe4\xc0\x8d\x6a\x2a\xfc\x54\x4f\x2e\xd4\xbc\x5c\xab\x85\x2e\xae\x55\xd6\x98\x05\x90\x0c\xbb\xc8\x78\x63\x98\x29\xea\xb3\xe9\xd2\xc3\x4e\x90\x95\x3d\xab\x4c\x3d\x54\x27\xc6\xa8\xfb\x5f\x7c\xf9\xd5\x01\x8c\x4b\xa7\xd7\x3f\xeb\xac\x19\xab\x03\xd7\xe2\xf7\x65\x9e\xaa\x1e\xf8\x58\xe4\x46\xd7\xa6\x1f\xd7\x74\xef\xb3\xad\x79\x99\xa7\xdc\x5d\x37\xd7\xf6\x61\x80\xe0\x27\x1f\x04\x53\x6d\x9b\xdc\xdd\xc5\x1d\x22\xb7\x78\x18\x07\x8d\xf9\x91\x79\x1f\x09\xd6\x88\x18\xff\x35\x27\x64\xb3\xd3\x9d\xd5\x2e\x74\xbb\x8a\x3b\x06\xd3\x23\x43\x84\x1c\xf8\xbe\xcf\x58\x48\x5a\x28\xe8\x33\x38\xf1\xe1\x11\x62\x65\xa3\x0b\x0b\x87\x81\x41\x85\x02\xbb\x74\x6f\x2f\x1e\x9d\xbf\xed\x69\x5d\xa3\x48\x9e\x88\x2d\xfc\xc9\x20\x06\x15\xba\x1c\x76\x8c\x69\x2b\xaa\xcd\x79\x80\x50\x05\xaf\xa6\x4a\xab\xa2\xac\x16\x3a\x87\x4f\x7f\x8a\x16\x1e\x78\xd2\x49\x45\x89\xea\xc0\xd5\xce\xf6\x92\x1c\x75\xc0\x81\x50\x8e\x6d\x9b\xc7\xb6\xb3\xd3\x35\x38\x99\x35\xad\x73\x3c\xaf\xe4\xd4\xfa\xa4\x48\xe7\xe5\xaa\xb0\x72\x79\xc9\xa8\xf2\x48\x1c\xe8\x30\x87\xf4\xc5\x01\xa8\xa8\x53\x8e\x2d\x3a\x93\x3c\xfa\xbb\x2a\x9b\xcd\x00\xd7\xf3\x1a\xeb\x95\x5b\xd4\x63\x16\x79\xe2\xd0\xe0\x07\xb8\x79\xaa\x68\x5f\xca\x10\xee\xa8\x64\x4f\x25\x50\x73\xc2\x64\xb9\xe3\x8b\x72\x3a\x8d\x8b\x7d\x0c\x48\x1b\x67\xfd\x79\x17\x1d\xca\x39\xf5\x06\xb3\xa6\xe4\x53\x35\xc9\x8d\x2e\x56\x4b\x12\xd8\xc9\xc1\xcf\xbb\xf4\x32\x4b\x4d\xa2\x99\xc3\x0e\x41\x0b\xf2\x4b\x5b\xe7\x0f\xc4\x4c\xf4\x54\xf2\xe2\xed\xeb\xe7\xe8\x6c\xff\x43\xa9\x53\x93\x26\x03\x5f\x03\xa1\xbb\x61\x6f\x11\xe4\x76\x43\x2d\x79\xa9\x37\x7f\x19\x1c\xd9\x18\xa8\x32\xa0\xab\xa1\x57\xa2\x53\xac\xf0\xad\x43\x9b\xc0\x9f\x53\xff\xe8\xa8\xcd\x39\x4b\x59\xad\x99\xcc\xd5\x44\xd7\x06\x1c\x26\x2b\xa3\xfe\xe0\xd1\xc7\xb8\x5f\xe0\x73\x47\xa6\x02\xe7\x3d\x7a\x5e\x95\xeb\xda\x54\x6e\x25\xbc\x33\x1f\x50\xe5\x8a\x4c\xa6\xe8\x5c\x00\x04\xbb\xa9\x32\x54\x1d\x59\x11\x00\x8a\x9e\x80\x4e\x00\xe1\xd1\xf5\xa4\xc9\x2e\x4d\xa2\x6c\x27\x10\xd0\x3d\x6b\x14\xe0\x0f\xa6\x2a\xab\x6b\x7b\x2b\x82\x97\x29\xe8\x9d\x0a\x43\x75\xa7\x59\x3d\x29\x2f\x4d\x85\x0e\x74\xcf\xe7\x55\x56\x9f\x40\x15\x63\x46\x58\x3f\x5f\xcd\x6a\x0a\x96\x03\x78\xf5\x26\x9b\x5c\x98\x66\x74\xf0\xe8\xd1\x57\x8f\xee\x4f\xca\x85\x1d\xe9\xf8\xe0\x73\xb7\xe5\xc5\xa6\x70\x3d\x04\x77\x17\x5e\xc1\x44\x7a\xfe\x13\x31\xcd\x1a\xa5\xeb\xeb\x62\x32\xaf\xca\xa2\x5c\xd5\x98\xf4\x55\x03\xde\x3d\x43\x37\x41\xbf\x01\xc4\x7a\x55\x64\x0d\x14\x48\x4d\xae\x05\x71\xdc\xaa\x4d\xf3\x2e\x5b\x98\x72\xd5\xb8\x93\x87\x33\xca\x0b\xe6\xc9\xbd\x13\x7c\x6a\x9c\x11\x7b\x12\xae\x23\x2f\x67\x64\x3f\x78\x38\x3a\x4d\xff\xd5\x0d\xce\x8d\x3d\xb3\xcf\x9c\x47\x25\xed\xfa\xb2\xb0\x3b\x7c\x20\xdc\xbd\x29\x4b\xf1\xba\xac\xb0\x0b\x54\xb0\xa3\x03\xb7\x9e\x0d\xa6\x01\x1e\xb0\x91\x29\x9d\xd3\x3e\xc0\x39\x90\xa9\x21\xfe\x94\x81\xbf\xe3\x34\xe2\x23\x28\x75\xdc\xa5\x29\xd8\x2a\xb6\xb2\x5b\x37\x2d\x4d\x8d\xa8\xc6\xdd\x9c\x8c\x8b\x55\x80\xba\x5f\xaf\xf2\x26\xf3\x00\xc9\x44\x63\x38\x7b\x24\x27\x6e\x22\x91\xa7\x9c\x06\x2e\x64\x8e\x37\x83\xd7\xa3\x1a\xdd\x9e\x97\x0e\xa8\xeb\xdc\x30\x4d\x07\x2f\xe1\xac\x79\x50\x8b\x2c\x79\xc8\xb6\x69\x48\xee\xe8\x8f\xb3\xfb\x3b\x8c\x19\xa2\xa0\x9b\x0b\x73\x4d\xf2\xd7\x40\x4d\xe6\x3a\x2b\x50\x0b\x06\x7e\x02\x7f\x34\xcd\x40\x55\x7a\x2d\x82\x19\xbc\x72\xa3\x9d\x50\x19\x53\x72\xaf\xf2\x0b\x75\x64\xab\x15\xa8\xe7\x84\x0c\x68\x9a\x1a\x59\x2a\x27\x58\xcb\xcb\x03\x5d\xc9\xec\x87\x04\x04\x8f\x5a\x63\x77\x8c\x5c\xef\xa4\x63\x26\x23\x9b\x66\x05\x7d\x19\xb0\x38\x38\xf4\x60\xbc\x19\x0c\xf9\x34\x23\x4c\xcc\xd6\x48\xc5\x15\xcb\x5d\x2e\x0b\x5a\x0f\xbb\xcf\x84\xc4\x8b\xe2\x7c\x27\x98\x4b\x47\x5f\x3d\xef\xdf\x21\x72\xb1\x66\xc0\x5d\xf7\x7a\x2d\x47\x29\xc3\x8b\x60\x82\x05\x65\xf9\xd6\xfe\x2d\xd2\x8e\x55\xab\x22\xc8\xed\x61\x8a\x26\xab\x8c\x83\xd8\x44\x51\xd0\xad\x29\xd8\x0a\x04\xde\x35\x0b\xe3\x4e\x38\x02\xbb\x95\x5f\x46\x86\x04\x33\x57\x13\xb3\x24\x6c\x14\xdc\x91\x41\xc6\x1a\xa1\x39\x09\xa5\x2b\xda\x1e\xd3\x42\x56\x1f\xc7\xfb\xf9\x3d\xd9\x36\x0b\xd8\x0a\x36\x04\x66\x87\x1d\xff\xd8\x0e\x4c\x42\xb5\x62\x11\x61\x20\x6c\x02\xe6\x9d\xf2\x41\x81\xcd\x02\x7d\xb2\xf3\x76\x4c\xed\x90\x8e\x45\xce\x1d\x14\xcc\xec\x3e\x8b\xbe\x84\x95\x8d\x71\x49\x02\xac\x67\xbf\x61\xc0\x8d\x03\xb3\xb0\x8f\xdd\xf5\xfb\x47\x83\xcc\x16\x4c\x1f\x3a\x7a\x84\xcb\xe6\xb0\x1f\xec\xb1\x3c\x16\x3d\xd8\x77\x3d\x18\xbb\xad\x2e\x2c\xee\xcc\x31\x39\xfc\x80\xda\xf9\x3a\x69\x0e\xa4\x01\x22\x04\x4e\x01\xa9\x6e\x74\x18\x0d\x61\x4f\xd8\xb2\x79\xa1\x1b\x1d\x32\x1e\xeb\xc2\x31\x7f\xe0\x62\x6b\x4b\xd5\xa0\xf0\x1b\xe3\x23\xb5\x07\x09\xc6\xe9\x0f\xfe\x73\xf8\xf2\x87\x97\xaf\x5f\xbe\x79\xf7\xe1\xcd\xdb\x17\x2f\xe3\x77\x2f\xde\x3e\xff\x73\xfc\x72\x8f\xa2\x27\x44\xd9\x67\xa0\x43\xee\x04\x7b\x67\xd3\x92\xed\x5d\x8c\x0d\x71\x73\xd3\xf5\xfc\x6b\xf0\x48\xed\xa9\xdd\xe8\x5d\x5f\xcc\xa1\xdb\xf5\x76\x1a\x7a\x6e\xd0\x2e\x15\xc5\xb3\x22\xad\xca\x2c\x55\x4f\xd5\x13\x42\x1f\x7a\x9b\xa7\xea\x67\x73\xfe\xa7\xac\x71\x77\x0b\x4e\x30\x45\x9e\x93\xcb\xf6\x4b\x2b\xf5\xd6\xf6\x54\x8f\xa6\x95\x31\xbf\x1a\xba\x4b\xa8\x16\x1a\x4d\x61\xd6\x9c\x54\x0b\x97\xcb\x1e\x7d\xa3\x09\x94\xb3\x28\xd5\xe9\x69\x6d\x9a\xb3\x33\xba\x18\x00\x0f\x81\xda\x41\xaa\x45\x30\x84\x64\xd1\x1d\x4e\x5c\xec\xdc\x40\xed\x0f\xf0\x34\xcc\x4c\xd3\x61\xe6\xa7\x0e\x60\xf4\x9a\x4f\xf3\x70\xef\x33\x0c\xae\xe7\xb4\xa6\x32\x93\x01\x3c\xd8\x0d\x33\xf5\x33\x3b\x6b\xa7\x6f\xb8\xca\x52\xc2\x1a\x83\x3f\x35\xed\x9c\xe0\x36\xc3\x0d\x77\xe8\xbe\x91\x38\x53\xb6\x67\x17\x26\x10\x4c\xe5\x66\x04\x9f\x57\x4c\x33\x86\x35\x61\x24\x02\x07\xa9\x30\x8a\x02\xc2\xf7\x65\x85\x5a\x94\xa9\xb1\x54\x07\x99\xd8\x9a\x7d\xc6\x2d\xdb\xe9\x7d\x61\x8b\xb2\x81\x04\x61\xea\xfe\x57\x8f\x1f\x7f\x3e\x74\x46\x08\x60\x6f\x9c\x56\xc3\xc0\x39\x44\xc0\xe2\x69\x55\xfe\x6a\xf8\x7c\x0d\xfd\xd5\x20\xc7\xec\x3b\x1e\xcd\xf7\xbe\xbc\x13\xec\xa5\x9c\x1a\x64\x1e\x21\x04\xf6\xb7\x0e\x37\x48\xe0\x29\xa1\x32\xda\x22\xcc\x82\x03\x3b\x4e\x31\x45\x17\x06\xb9\xcb\x55\x01\x16\xaf\x23\xfc\xe2\x54\x05\x6b\x79\x16\x08\xc3\x30\x70\x0c\x1d\x62\x5e\x1b\xc7\x41\x75\x70\xc7\x5d\x95\xbc\xc4\xa0\x96\xe0\x6e\x9e\x98\xc9\xaa\x02\xde\x38\x2b\x40\xbe\x2e\xf6\x4c\xb1\x5a\x98\x0a\x59\x11\xfb\xf7\xba\xca\x30\x0c\x85\x73\x25\xc1\xb7\x4d\x75\xed\x4d\x67\x3c\x05\x71\x87\xed\x94\x20\xa9\x1e\x2b\xea\x07\x5d\x0d\x9d\xa7\x20\x33\x3c\xf1\x03\x39\xaf\x92\xbd\xed\x3a\xd8\xfc\xee\x3b\xc1\xf8\x6a\x45\xd9\xb8\x61\x78\xd0\x4a\xd6\x50\x5e\xdb\xad\x8f\x84\x26\xd9\x53\xe2\x92\xbb\x75\x14\xd8\x79\xea\x7a\x6c\x0f\xef\xec\x70\x5b\x69\xf9\x52\x06\x1d\x4e\x02\xcb\x3c\x2e\x9c\xa7\x00\xa7\x3c\x5b\x67\x11\x6c\x60\xf4\xf2\x48\x9c\x7f\xa1\x85\xf4\xbd\xc5\xb0\xfb\x80\x80\xb8\xfe\xea\x46\x47\x37\x3d\x40\x57\x54\xe5\xd2\xbb\xa9\x81\xb4\xb9\xd0\x18\xf9\xc7\x15\x53\x4e\x37\x76\x31\x00\x68\xbe\xd4\xb8\x8f\xa2\xdc\xab\xa6\xb0\x5b\xc5\xb9\x35\x24\xd0\x7c\x22\xb7\xae\xca\x8a\x3c\xc3\x1d\x0c\xe6\x02\x91\x5e\xd5\x35\xa8\x9a\x79\xb9\x9a\xcd\xe1\x62\x84\xc3\x84\xd5\xce\x75\xca\xa2\x8c\xb9\xb2\x32\x4b\x1a\xee\x79\x98\xb5\x0b\x73\xed\xce\x33\xf6\x92\xc9\x6c\xd7\xa4\x1e\x46\x40\xd1\x63\x75\xca\x53\x26\x78\xa3\x33\xf0\x43\xbc\x17\xa1\xdb\x00\x3d\xeb\x8c\x6a\xa7\x46\xa0\x80\x5d\x37\xb6\x11\x6d\x6a\xea\x37\x3e\x6d\x99\xa9\xd5\x47\xd1\x5c\xc0\xd2\xd9\x4d\x5f\x99\x7a\x2e\xb3\xec\x59\x19\x9b\x29\x8d\xe5\x3d\xe7\x28\xe2\x4e\xca\x65\x66\x04\xb6\xb2\x63\x84\x5f\xda\xeb\xcb\x01\xea\xc2\xc4\xf4\x5b\x71\xef\xbc\xd7\xbb\x26\x6c\x40\x01\x65\x87\xdc\xa5\xb7\x0c\x57\x6b\xa5\xc6\xe5\x35\x3b\xa9\x38\xb8\xdd\xc2\xec\x9d\x5f\xef\xd9\x85\xe7\xfc\x7a\xd1\x71\x88\xf8\x56\x64\x15\x6d\x0d\x96\x48\x05\xd1\x6b\x6e\x62\xe1\xad\x9d\x58\x0c\xdf\xc2\x3f\x3b\x4d\x08\x5b\x41\xd6\x6a\x77\x48\x66\x9d\x87\x44\xc8\x35\xf6\x04\x67\xc8\x9c\xd9\xd5\xcb\x52\xea\x76\x56\xab\x29\x2a\xfd\xca\x0a\x65\xeb\x73\x43\x9b\xdb\x69\x57\xde\x98\x35\x96\xae\xe3\x12\x98\x78\xdb\xef\x74\xf6\x3f\xe2\xcb\x4e\x73\xc8\x37\x22\xcc\xb2\x80\x49\x13\x57\x98\x75\x7e\xcd\x55\xd1\x17\xc8\x8e\xc0\x2c\xd1\x15\xa7\x9e\x51\x87\x83\x6b\x08\xa0\xe0\xcf\x8d\x73\x26\x1a\x32\x05\xe8\x3a\x1c\xad\x73\xe4\xce\x09\x4d\x26\xca\x9c\x52\x1a\x3b\x16\x27\x6d\xac\xa8\x1e\x5b\xec\xcc\xcd\x39\x0e\xa6\x7b\xda\x3b\x48\x13\xc0\x00\xa0\x3f\x2b\xc4\x08\x05\x2a\x31\x03\x6b\x33\xc6\x97\x54\x44\xa9\x83\xa1\x7a\x53\x42\xab\x6b\x2d\xa0\xc6\xdd\xfb\x47\x76\x72\xf0\xac\xb6\x4b\xa1\x86\xab\x28\xa9\x27\x22\xf7\xa7\x6f\xe2\x1d\xfb\x62\x80\x6a\x34\x51\x4b\xdd\xcc\xd1\x4d\x1b\x4e\x1d\x78\x16\x9b\x46\xe8\x21\x52\x66\xf6\x59\xf1\x06\xa8\xb6\xd8\x42\x53\xd2\xfa\x83\xa9\x69\x69\x40\xdb\x96\x5f\x6f\x1e\xdb\x3b\x2f\x63\xc6\x67\x88\x87\x07\xc6\x26\xbb\x19\x70\xf6\x14\x29\xdf\x89\xe1\xc0\xea\x80\x20\xb4\x57\xf0\xe6\x06\xcf\x4f\xaf\x67\xdf\x79\xfc\x0e\x2e\xc9\x44\x8e\x13\x93\xad\x4c\x58\x81\x04\x6f\xa3\xd6\x8f\x3c\x08\x55\x70\xc4\xf8\x86\x77\x0e\xaf\x50\x7a\xbb\x63\x43\x71\x4d\xe3\x76\x4d\x8c\x5f\xa8\x17\x26\x87\xfc\x6a\x17\xe6\xba\xdf\xf2\x4f\x39\x7d\x78\xf6\x33\x9b\x55\x6c\xdb\x84\x2c\xab\x69\x1b\xc0\x31\x06\xb7\x04\x0d\xaf\xed\x5a\xb2\x02\x02\x0e\xa4\xa5\xa9\x7e\x87\x00\x7c\x5b\xa5\x90\x3e\xaa\x1e\x5c\x42\x60\x8c\x84\x85\xa8\xfb\x28\x08\x6c\x5c\xc0\x67\x4e\xce\x03\xb8\x00\xa6\x91\xe1\xfe\xec\xe8\x86\xfd\x2f\x61\xd6\x36\x9d\xa7\x46\xe4\xf9\xcf\x40\xaf\x6b\xb7\x68\x6d\x1a\xda\xa1\x4e\xaa\x6c\xd6\xa5\xc3\x36\xa7\x3b\x75\x59\x66\x64\x5e\xf0\x72\x0e\x28\x33\xae\x96\xe8\x2d\x06\xdb\xe9\x5c\x93\xe1\x12\x37\x30\xd4\x6a\x4f\x4f\xa3\x2f\x4c\x71\xfa\xf0\x4c\xd0\x86\x2e\x5d\x8d\x97\xe4\x2f\xcc\xb5\x23\x08\xad\x28\xb1\x0e\x3a\x4c\x19\xec\x11\x18\x07\xd6\x7a\xf0\x9f\xba\xf3\x37\x9c\x83\x4f\x61\xc1\xba\xae\x66\xe2\x55\x15\xe4\x20\xb0\xbb\x04\x50\x38\x94\x47\xe1\x20\xc2\x83\x47\xaa\xee\xb8\x9b\xc9\xe3\x80\xb5\x18\x74\xe7\x21\xff\x9f\xd8\x19\x48\x28\xc7\x3c\x35\x81\x15\x0d\x87\x43\x57\x10\xb6\x3a\x2c\x18\x44\x5f\x01\xec\xaf\xbf\x32\x06\x90\x50\xa4\x97\x5c\x18\xf0\x71\xbf\xd4\x79\xd2\x57\x96\x93\xd0\xcd\xaa\x32\xde\x45\xd5\xd6\xea\x6f\x2e\xc4\x56\x40\xf6\xcf\x1d\x36\xdf\xa4\xdb\x70\x8e\x05\xa4\xfc\x27\x8d\xc9\x73\xf5\x61\x5e\xae\x3f\xd0\xd9\x02\x74\x81\x14\x1c\x59\x71\xe5\x5d\x1d\x70\x00\x97\xb9\x26\xd5\x22\xa2\x80\x50\x4b\xf6\xc9\x50\xdd\x3f\x78\xf4\xe5\x57\x5f\xb8\x0f\xde\x59\xde\x12\x7a\x08\x8e\x4d\x4b\x53\x20\xbc\xb1\xdd\xb8\x38\x39\x2e\xc0\xcc\x6e\x55\xea\x2d\x00\xec\x80\xc2\x74\x38\x29\x8b\x89\x6e\x60\xae\x11\x1b\x29\xa6\x26\x42\x8b\x14\x70\x27\x50\xc0\xcb\xc8\x9e\xfa\x38\xca\xc6\x5d\xac\x90\x15\xa2\x55\x07\xe9\xcf\x16\x41\x8b\x36\x58\xf9\x16\xba\xc8\x96\xab\x5c\x3b\x49\xc5\x6f\x49\x07\x3f\xe1\x59\x1f\xea\xfd\x29\x1e\x7c\xec\xc7\x86\x80\x6c\xb6\x9f\xc2\xac\x73\xc8\x0b\x6c\x47\x62\x9c\xeb\x01\x58\x7c\x32\x72\xf9\x6a\xf1\x71\x84\x4d\xc3\x3b\xed\xfc\xda\x65\x98\x47\x19\x71\x9e\x35\x06\xea\x0b\xfb\x06\x9d\x3a\x0c\x9f\xc1\x3f\x6e\x38\x1c\x48\xbb\xe5\x30\x97\xc6\x8c\x3d\xb5\x09\x7e\x47\xb5\x22\xca\xf1\xe8\x50\xdd\x41\xa0\x6d\x57\xd2\xfa\xad\xd4\xe4\xa6\x31\xcc\x93\xd8\x6f\xd0\x25\xe7\x2c\xd6\x12\x0e\x10\xc9\xd7\x4a\xce\x1b\x95\x1a\x1c\x6d\xd3\xc9\x50\xb7\xe8\x46\xa7\x5c\x8f\x30\x20\x80\x3e\xe8\x11\x17\xb7\xd2\xac\x9e\xe8\x2a\xdd\xd8\x30\x6c\x8d\xee\xfa\xbc\x5f\x0b\x0c\xf4\x13\x3a\x10\x18\x74\x09\x1a\xca\x92\x8d\x0f\xcb\x2a\xbb\x24\xff\x27\x54\xb1\xb9\xdc\x97\xf0\x1a\x6c\x34\xad\xd7\x8c\x6a\xb4\xe5\x72\x58\x62\x22\xf4\x93\xd5\x62\xa1\xab\x6b\x58\xb0\x83\xa1\x7a\x59\x4c\xcb\x6a\x62\xd4\xb3\x1f\x5f\xa9\x7a\x55\x4d\x2d\x75\x44\xe9\x6f\xa1\x8b\x26\x9b\x60\xe2\xed\x26\xc3\x4c\xe1\xb8\x71\x0f\x86\x5f\x0f\xaf\xd4\x79\xa5\x8b\xc9\xfc\xde\x67\x5b\x8f\x86\xea\xd5\xc2\x72\x66\xe4\xea\x53\xa6\xab\xdc\x3c\xa8\xd5\x42\x67\x80\x62\x4c\x59\xc6\x11\xb9\x23\x5d\x4d\x18\x4b\xc9\x72\x11\x7a\x86\xfe\xb2\xba\x99\xd7\xa8\x33\x20\x6f\xc8\x85\x99\xcc\x75\x91\xd5\x0b\x7b\x18\x1e\x0f\x9d\x01\xaf\xb6\x1b\x34\x2e\x63\xbf\xa4\xdc\xc2\x2a\x59\x02\xb0\x97\x49\x60\x18\x89\x9d\x9c\x04\xe6\xc9\x56\xf4\x64\xa8\x3e\xbc\x31\x97\xa6\xfa\x60\xaf\xd2\xb2\x36\xa2\x38\x50\x68\xb4\xba\x56\x6a\x52\xa6\x46\xf5\xde\xbd\x7d\xf1\x76\xac\x5e\x58\x41\xe6\x03\xca\xea\x1f\x90\x48\xda\x79\xee\xdf\xfb\x6c\xeb\xf3\xa1\x7a\x06\x89\xa1\xa0\x36\x08\x3b\x0e\x67\x3b\x35\x8d\xce\x72\x2b\x70\x61\xbd\xc4\x93\xa8\x9e\x99\x0d\x39\x5f\xba\x60\x3a\x6c\x9d\x5f\x0c\x5d\x52\x7b\x0d\x86\xfa\x0a\x6f\x76\x2b\x82\x45\xb5\xaf\x96\xb3\x4a\x63\x6e\x8e\x9f\x8d\xbe\x78\xad\x41\x3a\x7b\xb4\x7f\xf0\xe4\xde\x67\x0f\x47\xe4\xc5\x74\x5e\xd9\x35\xe5\xac\x52\xbf\x61\x4a\xa9\x87\xef\x3f\xde\xbc\x3f\xe5\xdf\x67\x98\x4f\x6a\xab\x02\x4c\xa7\x17\xba\x9e\xdb\xf2\xbd\xd3\x67\x7b\xff\xff\xb3\xfe\x68\x16\x42\x7d\xda\x89\x78\x06\x29\x4d\x84\xb5\x42\x48\x84\xb6\x51\x7b\x9e\x9d\xdd\x0b\x15\x65\x40\xa7\xec\x6d\x03\x92\x9a\x00\x97\x19\x28\xcb\xf1\xb8\x8c\xc4\xe8\x02\x3d\x1a\x91\x62\x92\x23\x78\xbf\x7f\xf7\xfa\x87\xcf\xe1\xd9\xde\x43\x9f\x7b\x85\x4d\x68\x4e\xe8\xf7\x1c\xc3\x86\x54\x91\x74\x2c\x89\x0e\x26\x50\x61\xa2\x76\xe1\xce\xa9\x0c\xa4\xb1\xee\x29\x3f\x0f\x03\x95\xec\xfd\xe1\x20\x51\xfd\x30\x69\x30\x1c\x55\x6c\x74\x53\xda\xed\x10\xc8\xef\x4e\xe5\x84\xd4\xe5\x61\xbd\xbe\x6c\x53\xad\x20\x4f\x37\xf8\xca\x70\xba\x62\xff\x1a\x6c\xc1\xf6\x3d\x1a\x85\xdb\x05\x8a\x55\x9e\xdb\xf7\x10\x4b\x32\x16\x97\x8b\xbd\xa6\x89\x95\xc0\xc3\x57\xac\xc0\x3f\x08\x4c\xab\xa0\x9a\x2f\x1e\x34\x0c\x4b\xe6\xef\x4d\xaa\x61\x17\x5a\xd8\x55\x49\x82\x5e\xf9\xf6\xaf\x63\x85\x4f\xb9\x15\xdc\x7d\x84\xa5\x47\x9b\xe4\x38\xc8\x90\xf4\x7f\x4e\xde\xbe\x71\xaf\x64\xdf\x0f\xa5\x9e\x90\xd4\x84\x41\x66\x2b\xce\x65\xb5\x36\x4e\x57\x85\x52\x56\x09\xba\x54\xd1\xf7\x14\x93\x34\x20\x3d\x66\x92\x89\x7c\x7b\x6b\x0f\xb7\xfd\xc5\x68\x3d\xc2\x48\xe6\xc8\xe8\x4e\x1d\xfe\xd8\xed\xb3\xd7\x71\x7f\x75\xc0\x56\xfa\x9e\x51\x79\x57\xea\xe6\xc6\x5f\x04\xf1\x4b\xe1\xcf\x9f\x76\xb4\xc1\x5c\xba\x54\xd9\xb4\xda\x93\x76\xe2\xf0\x03\x51\xbb\xa7\x7c\xdd\x6d\x70\xed\xbe\x5a\xfc\x22\x2c\x13\x86\x1f\x20\x81\x7d\x03\x52\xba\x6e\x5c\x00\x36\x5c\x05\x40\x71\x81\x88\x0b\xa2\x8b\x12\x13\x04\xe5\xd2\x69\x25\x90\x30\xb8\x98\x48\x41\xe3\xaa\xf0\xb7\x27\x45\x26\x41\xb4\x56\x6d\x08\xce\x4e\xa5\x66\x59\x99\x09\x6b\x89\x3e\xfc\x2b\xf3\x07\x4b\xf2\x49\xf3\xf7\xe1\x77\x4d\x20\xd4\xbb\x71\x02\x6f\x4f\x7c\x10\x8f\xa3\x5b\x95\x93\xc9\x9e\xa2\x9c\x41\xb9\x2e\x1c\xc2\x37\x3e\xb5\xd4\xb6\x26\x42\xe7\xc8\xaa\x4f\x7f\x75\x18\x58\x69\x61\x0d\xbd\xf9\xfb\x0e\x71\xae\x05\x18\xda\xef\x20\x82\xb8\x99\x66\x7c\x5a\x45\xa2\xaa\x8d\x89\x36\x76\x76\xd4\xb6\x9f\xc6\x99\x3f\xe8\x09\x9d\x1e\x4b\xac\xeb\x24\xf0\xe7\xb6\xbc\x2b\x0c\x35\x42\x89\x69\xb1\xaf\xcc\x2d\x87\xe9\xf6\x0f\x0e\x76\xc5\x8b\x77\x56\xe6\x81\x79\x73\xf8\xfc\xb4\xe7\x80\x08\xf7\xee\x1f\x3c\xf9\xea\xeb\x27\xce\x8f\x1b\x81\x7a\x6c\x79\x0e\x86\xf5\x61\x96\x74\x55\xf9\xb7\x43\xba\x5d\xb7\xc4\xb7\xc0\x74\x13\x94\x7a\xcf\x5d\x6b\xe8\x48\xb2\x1f\x86\x95\x52\x7d\x6d\x59\x49\x80\xcd\x7e\xde\x0f\xc2\x2d\xe3\x2b\xdf\xef\x1b\x8f\xd2\xda\x05\x04\x44\x3f\x3e\x0a\xaa\x8e\x2b\x52\x6f\x5a\x91\x81\xf4\xc7\x8d\xa5\x8b\x90\xd6\x4a\x85\x12\xba\xd6\x30\x20\x65\xb4\xfd\x62\x95\x59\xe4\x57\x13\xe0\xb5\x42\xbc\x62\x47\x64\x5a\x78\x69\x60\xac\x99\x90\x2d\x3f\x76\x39\xa2\x33\x55\xa0\xe0\xd6\x0d\x61\x30\xcc\xc6\x0f\x84\x28\xfb\x27\x73\x7d\xab\x34\x7b\xcf\xdb\x86\x18\xc7\x31\x44\xc6\xc7\xb4\x35\x56\xd2\xa6\xe4\x0e\x7d\xd6\xb1\x81\x6a\x9a\xbf\xef\x91\xe6\xbb\x42\xf1\x17\xac\xa1\x3e\x5d\x82\x5e\x2e\x8d\xae\x6a\x54\x57\x12\x45\xe8\xb3\xb2\x9c\xab\xf8\x07\x8c\xe6\x1f\x1e\x0e\x15\x78\x3c\xdb\x92\x3b\xed\xa0\x62\x43\x95\x78\x3b\x23\x1b\x90\xee\x3c\x57\x95\xa9\x57\x39\x58\x40\xff\xe1\x3e\xfc\x07\xf0\xbc\x31\x51\x22\x6d\x97\xfd\x8a\x6b\x80\x74\x8d\xd0\x75\x70\xcb\xb1\x5c\x2a\x04\xd3\xd9\x43\x63\x1b\x46\xad\xae\x4e\x95\x46\xb2\xec\xac\x06\x0b\x9d\x92\xd6\x24\xc8\x3d\xd7\xa1\x48\x0d\x54\x3f\xcf\x7c\xb5\x33\xd3\x44\x9c\x2a\x01\xe4\x6e\xf1\xe0\x48\xd2\x07\x1d\x4a\xbd\x97\xd5\x77\xd1\xb7\x60\x63\x09\xf6\xb6\x3b\x6b\x56\xfb\x54\x88\xa4\x75\xff\x46\x57\x61\xd7\x65\xbf\x72\xec\xf3\x6d\xdd\x75\x5b\xf6\x7f\xa0\xcf\x09\x3b\xae\x26\x9e\xbf\xcb\x0a\x57\x12\xa5\x82\xc9\xaa\x6e\xca\x85\x14\x0e\xda\x93\x2c\xc9\x17\x77\x78\x20\xfb\xf6\x1f\xea\xfb\xcf\xec\xbf\x5b\x19\xd0\xf2\xcd\x75\x45\x46\x0c\xd7\x7f\xe6\xab\x41\xe9\x43\xba\x1e\xe1\xdf\x2e\x83\x6c\x4f\x04\x5f\xcb\x2a\xc5\xdb\xe8\x94\x47\xce\x13\x3b\x1f\xa1\x9b\x35\x1a\x02\x21\xe2\x82\x53\x2a\x97\x2e\xe2\x74\xcb\x49\x5c\xc0\x88\x2d\xb2\xd9\xbc\x79\xc0\x9c\x16\x56\x00\xdb\x43\x7b\x1d\x60\x0a\x32\x13\x7e\xcc\x44\xac\xbd\x45\x90\xf8\x05\x5b\xc4\x77\x95\xd2\x30\xb7\xe5\x3a\x14\x0f\xcb\x25\x20\x00\xa2\x92\xbc\x74\x9f\x61\x77\xd8\x13\x02\x2e\x20\x02\x91\x49\x75\x3d\x47\xbf\x15\xd1\x4f\x40\xc9\x1e\x86\x5a\x4a\x18\x1f\xda\x1c\x96\x4b\xe7\x85\x2c\x04\xf1\xe1\x70\xf8\xf0\x16\xd2\xef\x77\x50\xa8\xeb\x87\x16\x1e\x0e\x87\x43\xf5\xaa\xa0\x13\x56\x9b\xd0\xae\x20\x26\x58\x7d\xd0\x80\xbd\x98\x5f\x7f\x70\x1f\x93\x9f\x99\x1d\xc7\x20\x80\xc8\xcb\xeb\x78\x25\xa7\x50\x95\xfb\x72\x55\xb0\xb0\xc3\x53\x33\x0c\xf5\x97\x8e\x3f\x48\xf6\x12\x44\x92\xdf\x3b\x60\x8c\xd1\x8d\xbb\x7d\xd3\xcd\xd7\x72\x37\x0c\xee\xc1\x01\x25\x36\x26\xc7\xda\xae\xf0\x4d\x2e\xe2\xef\xfb\x5b\xe5\x0c\x61\x7d\xb8\xfb\xbe\x6e\x8b\x20\xf1\x8d\xfd\xb1\x15\x14\xd6\x96\xda\xfe\xb9\x32\x2b\xd3\x66\xd5\x2d\x3b\x11\xca\x03\x76\xf7\x43\x61\x29\xf1\x07\x39\x7f\xc8\x39\x8b\x50\x21\x6f\x6e\x54\x32\xbd\xb2\x0c\xc8\xae\x4a\xe0\xc3\x04\x67\x11\x7e\xf3\x19\x8a\x59\xd7\x86\xfd\xee\x1c\x71\x58\xda\xbd\xb1\x5a\xaa\xd4\xe0\x87\xe7\xd7\x96\xc6\xa3\xed\x6b\xd5\x28\x48\x13\x8d\x09\x1c\x39\x53\x3d\x44\x16\x6b\x95\x97\xe5\xc5\x6a\xe9\xef\xbd\xd0\x9e\x8f\x9e\x30\x58\xa5\xcf\x9a\xe0\x2c\x21\x54\xd8\x6f\x91\x76\xaf\x43\x79\x08\x27\xac\x95\x85\xd1\x16\xdf\x18\x84\x08\x75\x12\x22\x95\x74\x6d\x08\xb0\x59\x69\x23\xb8\x9e\x9e\x9e\xc5\x61\x5c\x34\x33\xdd\x8b\xc8\x43\xa0\xc5\x91\x4b\x73\xe8\x9d\xcb\x78\x74\xd4\x7f\xf8\x33\xac\xc5\x21\x0d\x55\x8d\xc3\x8b\xc3\xfe\xcb\x3c\x69\xe0\xe9\x8b\x8f\x09\xee\x15\x9f\xcf\xcb\xf2\x42\xf8\xf7\x7d\x80\x22\xdf\xdb\x87\x5d\xad\x14\x98\xf5\xb2\x4d\xf9\x39\x19\x88\xe9\xe8\xa0\xc7\x3d\xb8\x27\x03\xa7\xd4\xf4\x8a\x46\x07\x50\x27\xf0\x33\x1d\xb0\x2f\x0f\x81\x2c\x93\xe3\x08\x06\x84\xd7\xa6\x68\xb2\xc2\xe4\xf7\x84\x33\x31\xb0\xd4\x59\xe1\xb0\x99\xbc\x77\x71\x6b\xc0\x87\xf1\x44\x11\xf4\x61\x97\x7b\x32\x6f\x72\x84\x9c\x6d\xf5\x00\xb3\x55\x62\x1c\x47\x30\x14\xe0\x6d\xce\x0d\x6b\xa9\x46\x23\xa5\x57\x4d\xb9\xd0\x4d\x36\x81\xfb\x98\xc7\x29\xc4\x4f\x0f\xd4\x7a\x25\x60\x50\xb1\xe7\xab\x02\xfb\x1e\x0d\xb1\x75\x51\xa3\x9e\x76\xb5\x24\x20\xf8\xba\xa1\xee\xd4\x4d\xb9\x14\xf1\x09\xde\x1e\x00\xcb\x0e\x38\xc6\x14\xc3\x2c\xdd\x99\x07\xaa\x00\x60\x37\xdc\x1b\xed\x14\x1b\xdb\x72\xb3\xed\xec\x70\x39\xea\x3a\x56\x0d\x0c\x37\x00\x58\xf4\xba\xa2\x1b\xed\xdd\x67\x2f\xd9\x22\x35\x98\xf5\x7d\xb9\x3a\xcf\x41\xdd\x5f\xd4\xab\x05\xf2\xd0\x7b\x6a\x66\x0a\x53\xe9\x06\x52\x6f\xf9\x8d\xe9\xd2\x6f\x95\x95\x43\x8b\x97\x08\xbd\xe8\x0a\x29\x76\xf2\xed\xe7\xcf\x9e\x32\x10\xce\xf0\x29\xd3\x44\xf8\x12\x09\x63\x4b\xe1\x12\x33\xcb\xa1\x86\x2c\x24\x3f\x70\x59\xe1\xcc\x10\xfa\xe3\x1d\x40\x64\x1b\x20\x5c\x36\xa9\x65\x4e\xc3\x6e\x27\xd8\xa5\x33\x2f\x1a\x76\xdd\x37\x9d\x7a\x9b\x16\xad\xea\xbe\x6a\x6a\xd3\x34\x60\xf1\x79\xd4\xa1\x61\xde\x0c\xec\x4b\xfc\x99\x2d\x70\x28\x2f\x25\xa2\x77\x18\x57\xd5\x98\xaa\xe3\x50\xb6\xee\xef\xa7\xdc\x89\x48\x86\x0e\x89\x24\xe5\x55\x0e\xc8\x50\x14\xab\xdd\xd6\xdb\xfb\xec\x64\xa4\x0d\xbe\x8d\xdf\xdd\x4c\xa0\x29\x6f\xa6\x98\x40\xc9\xa2\xb9\xfc\x0a\x78\x72\x9c\x67\x24\x7c\x1c\x10\xd4\x80\x1e\xfb\x4a\x63\x25\x54\x48\x44\x76\x76\xb0\xa6\xd3\xfd\x33\x5c\x8b\x2e\xfa\xd8\xa6\xd9\x51\xf5\x31\x5b\x85\x16\xc9\xf6\x8d\x26\xcf\xd2\xdd\xbc\xd1\x9d\x8d\x8a\xc6\x80\xaa\xfd\xf7\xa7\xb6\xc7\x15\x8a\x7b\x74\xe0\x4c\xc5\x1f\xc9\x69\x3f\x44\xda\x72\x40\x48\x10\x48\x03\x15\x70\x4c\x98\xa9\x1a\x9d\x61\x9e\x6b\xfc\x52\x57\x06\xb4\x08\x56\xb8\xea\x4d\xaf\xec\xa5\x65\x89\x0e\x34\x77\xee\x52\x9c\xf4\x21\x95\x56\x0b\x62\x0b\x37\x82\x00\xda\x02\xd8\xc4\x05\xb9\xd9\x22\x9c\xcc\x11\x84\xa7\x33\x14\x41\x57\x3c\xa8\xd7\x92\x82\x46\xef\x88\xd3\x15\x92\xf6\xb0\x95\x1b\x95\x11\x10\xba\x2e\x6c\x0f\x1a\x82\xad\x4b\x8e\x2a\x95\x80\x6e\x18\xa8\xcc\x8d\x5a\x7a\xe3\x3a\xd0\x32\xc3\xff\x2e\x82\x60\x67\xa3\x83\x1e\xb4\xed\x1c\xb7\x70\x48\x5d\xb6\xfd\x66\xb1\xec\xe6\x61\x6d\x9f\x41\x83\x39\xe8\xa2\xf4\x3c\x16\xec\xfc\x62\x09\xde\x6e\x8b\x25\x5e\x64\x7e\x72\x60\xb6\x28\xac\x1f\xda\xa2\x9b\x0e\x20\xc9\x1d\x06\x5e\xe4\x45\xc0\x2b\x41\x57\xa1\x44\x8a\x68\x47\x49\x3a\x32\x0d\xbe\xd8\xc5\x6a\x01\x69\x99\x4e\x77\xf7\xce\x8e\x7b\xc7\xe3\xf7\xe9\xc3\xf7\xc3\x9b\xfe\xfb\x74\xb7\x77\x3c\x3e\x35\x2f\xcf\xe0\xc5\xfb\x74\xf7\xa6\x3f\xea\x0f\xeb\x72\x55\x4d\x8c\xb3\xcf\x4f\xea\xfa\x25\x18\x79\xc1\x47\x24\x79\x57\x2e\x93\x81\x4a\x7e\xb2\xc2\x9f\xfd\xf1\x6d\xd9\x34\xe5\xc2\xfe\xfa\xc1\x4c\x9b\x84\x9c\xa0\x40\x39\x5f\x7f\x9f\xa5\xa9\xe9\x8a\x0e\x33\xb9\x70\x87\x75\xe5\x50\xa0\x3c\x37\x1c\x80\x0c\x7c\x10\x6e\xe0\xfb\x98\xbd\xcb\x55\xc4\xde\x9b\x00\x04\x0d\xe9\xa3\x6a\x33\x10\x49\x52\xd1\xc5\xa8\x36\x93\x52\x40\xdd\xde\xfb\xcc\x99\x07\x4c\x6e\x37\x81\xfd\x43\x4e\x26\x6b\x2b\xfd\xc5\x9b\xa4\x59\xbd\xcc\xf5\x35\xeb\xa1\x93\xa2\x2c\x4c\x02\x01\x45\xad\x34\xc7\xa0\xc4\x07\xbf\x88\x17\x2e\x22\x5f\xd8\xb7\xdc\xbc\x54\x10\xa2\xaa\xcf\x73\xd2\xf6\xab\x1e\x98\xb5\xe1\xe9\x79\x79\x75\x53\xe9\x34\x2b\xfb\x7f\x18\x65\xde\x09\x22\x26\x81\x80\x46\x49\xa9\x79\xed\x3e\xe5\xc0\x5f\xf4\xaf\xe1\xe6\xbf\xa3\x12\x74\xe8\x53\xf0\xc0\xe0\xcf\x86\x7a\xb9\x34\x45\x0a\xe9\xe9\x7a\x71\x0d\x2f\x71\x22\x7b\x76\xfc\x97\x60\x62\x80\x1a\xb2\x62\xb9\xea\x68\xcf\x97\x86\x02\x09\x5f\x2c\xa3\x91\xba\x7f\x70\xf0\xe8\xe0\x4b\xb5\xc7\xa1\x52\x90\xc2\x99\x62\x74\x1d\x2a\x05\x7a\xf2\xd4\x22\xe0\x1c\x0a\x80\x97\xa9\x37\x92\x4b\x53\xc5\xcf\x10\x66\x5c\xdb\x5a\xd5\xb3\xe5\xb2\x56\xbd\x9f\x7f\x7e\xd6\xc7\x42\xff\xb0\xd5\xfd\x03\x74\xbc\xff\xb0\x47\xf4\x1f\xa8\x7f\xb0\xb2\xbf\x33\x6f\xc3\x6d\xf9\xf3\xcf\xcf\x20\x4d\xee\x72\xd5\x04\x2f\x7b\x2a\xb1\xdf\xd9\x2d\x0d\x4b\x41\xa7\xba\xb3\x20\x75\xd4\x96\xe5\x9f\xb7\x94\x06\x57\xbb\x81\x4a\xfc\x14\xa5\x96\xd5\x93\x0b\x81\x53\xec\x27\xd0\x0d\xf9\x44\x4f\x75\x95\xa9\xcf\x87\x07\x03\x95\xbd\x3d\xc1\x1f\x1c\xbd\xf2\x64\x78\xe5\xff\x78\x34\x7c\x8c\xdf\x96\x61\x88\x1a\xd8\x92\xf3\xb2\xf0\xd3\x8b\x38\x7d\x93\xb2\xaa\xcc\xa4\xc9\xc1\x39\x4c\x26\x7c\x26\x77\x94\x21\x14\x7f\x0e\x5f\x1e\x29\xdb\x63\xa8\xe5\x4d\x99\x1a\x86\x1e\xe9\x78\x62\x05\x08\x18\xd3\x90\x5a\x73\x43\xf2\x56\xef\xc6\x5c\x35\xba\x32\x1a\x95\xf8\x7c\x00\xfa\x7c\x0f\x02\x40\x0e\x01\x55\x2e\x4d\x95\x5f\x63\xf7\xd3\x68\x66\x5e\xbd\xfc\x7a\x8f\x6d\x57\xb6\x77\x59\x51\x98\xea\xfb\x77\xaf\x7f\xb0\x8c\xe1\x53\x6e\xe3\x9b\xab\xa7\x23\xf7\x1b\x98\x45\x1e\x5e\x51\xc2\xd8\x9e\xd3\xa4\x1c\xa9\xed\xed\xee\x41\xfa\x21\xc9\x0e\x42\x16\xbc\x1e\xd3\xda\xba\xa9\x3c\x1f\xe8\x32\x3a\x85\x99\xf9\xed\xff\xb8\xf1\x69\x39\x59\xd5\x59\xf1\xed\xea\xfc\x1c\xe1\x8f\x93\xb2\xa0\x67\x89\x5d\x0f\x0c\xa8\xa7\xcf\x2e\x75\x75\xef\xb3\xad\xea\xc2\x5c\x43\x74\x3d\x38\xc4\x5c\x98\x6b\xf2\x7b\x29\x57\xb5\xf1\xcf\x7b\xc7\x63\x78\x72\x03\x7e\xb8\xa6\xba\x21\xa8\xae\x85\x29\x56\xfd\x9b\x49\x9e\x4d\x2e\xf0\x3b\x68\xed\x75\x59\x2d\xe7\xfc\x1d\xb5\x0f\xff\xdc\xc0\x7f\xcb\x55\x73\x9e\xaf\x2a\x76\xb1\xb1\xa3\x02\x95\xe5\xd2\xb9\xe5\x9c\xfe\x7d\x78\xf6\xb0\x6f\xef\x96\x61\x6f\xb8\xdb\xbf\xe9\xff\x61\x14\xba\xdc\x20\x89\x7d\x57\xad\x0c\xd1\xb0\x30\xf1\xfb\xc7\x8e\xc2\x90\x1b\x27\x2c\xcd\x19\x6c\xc2\xe2\xb5\x9e\x9a\x67\xe0\xe5\xce\xa4\x08\x3f\x72\x0e\x29\x7c\x59\x3a\x80\x04\x59\x18\xa8\xb3\x0f\xe5\xaa\x40\x22\x50\x1f\xc3\xac\x7a\xdf\x03\xb6\xa0\x40\x68\xb1\x14\x64\xa1\x0b\x3d\xcb\x8a\x19\x41\xa9\xa8\xbd\x3d\x90\x49\x97\xba\x6a\x38\x7f\x14\x89\xa4\xb0\x04\x53\x3d\x31\x43\xcc\x2f\x57\x95\x4b\x82\x30\xd3\x85\x7a\x99\xae\x75\x95\xd6\x0f\x14\xc3\x26\xa8\x3c\x3b\xaf\x34\x85\x3b\x41\xb4\x3d\xd5\x96\xa5\x46\x63\x9a\x3a\x1f\xbe\x6b\x68\xc9\x51\xe1\x30\xcb\xcb\x73\x9d\x8f\x31\x84\xb0\x9d\x11\xda\x4b\xae\xf5\x80\x21\x55\x38\x86\x2b\xcc\xf7\xc9\x0c\x26\x16\x7a\x7b\xfe\xcb\xab\x62\x80\xe3\xc4\x20\xa3\x81\x67\x3d\x71\xf4\x03\xd5\x0c\x7c\x69\x52\x28\x2d\xcd\x24\xd3\xb9\x6b\xca\x89\x33\x6e\xf7\xd4\x56\x02\xcf\x66\xf6\x26\xf4\x9c\xe9\x0b\xa1\x86\x0f\xd9\x2f\xe9\x91\x8e\x49\xe4\x31\x69\x03\xaf\x40\x53\xaa\xa2\x84\xcf\xad\x38\x64\xae\x9a\x11\xc1\x7e\x50\x38\x68\xef\x7c\xd5\x50\x4c\x05\xba\x05\xb3\x83\xfd\xbd\x20\xd1\xf9\x0b\xa9\x4c\xec\xc4\xed\xb1\x82\x37\x24\x62\x2a\x30\x8d\x7d\x56\x88\x60\x6b\x48\x03\xe6\xec\x39\xf6\x5d\x9e\x99\x15\x2f\x22\xcd\x85\x6b\x91\xfe\x1e\xce\x23\xbc\x1d\x31\xf3\xea\x88\x4b\x1d\x8a\x57\x95\x7b\x0c\x85\x86\x41\x11\x91\x51\x55\x96\xe1\xc7\xd1\x70\x04\x4d\x66\x5c\x25\x6e\x03\xe3\x4b\x29\xb7\xcf\xab\x17\x03\x84\x1a\x83\x34\x6b\x45\x3a\xe2\x3c\x66\x8d\x77\x4f\xc2\x69\xe4\x51\xcd\x56\x59\x1a\x0d\x89\x1e\x3a\xe1\x64\xc6\xd1\xa4\x01\x30\x52\x91\x11\xf8\x01\x9e\xd2\x07\x35\x41\x9e\x58\x0a\x3b\x69\x40\xf4\x2d\x52\x70\xd0\xf4\x1b\x59\xa8\x89\x5d\x5a\x75\xdf\xa5\x1e\x6d\x12\x74\x03\x81\x38\x56\x7c\xe2\xe5\x96\x4d\x25\x82\x10\xc9\xb0\x3e\x82\x85\x11\x9f\x60\x77\xa2\x4a\x37\x15\x0b\xb9\xe3\xc0\x44\xfb\x02\x3d\x77\xd1\x6b\x0d\x59\x59\x9c\x02\x90\x2e\xe5\xf1\x67\x20\xa6\x1e\xd8\xb6\x5d\x05\x98\x16\x91\x33\x62\xc6\xc8\x3e\x5a\x2d\xf5\x0c\x2d\xe6\x2b\x00\x76\x61\x43\x29\x53\x66\xbc\xbb\xc8\xde\x6d\xc5\xaf\xe0\x72\xf3\xc0\x83\x41\x17\x28\xde\xc6\x00\x16\x88\x73\xcb\x0e\x4a\x5a\x9e\xda\x52\x5b\x06\x21\x47\xa2\x14\x82\x5f\x46\x39\x37\x3e\x46\xbb\x83\x66\xd3\xb9\x4b\xd0\x2a\xf9\x98\x88\x73\x40\x25\x65\x4f\x72\x20\x78\xce\x78\x01\xc9\x28\x92\x44\xf5\x37\xb9\x86\xdb\x97\xa8\x87\x6f\xe8\x0e\x0f\x1c\x6a\x58\x60\x6c\x5a\x02\x63\x78\x33\x0e\xcd\x95\x99\x50\x93\xa7\xcd\x19\xfb\x9d\x07\x92\x2a\x13\x3f\xdb\xce\x62\x79\x7a\x40\x6f\x3d\x7d\xc4\x5e\x2f\x96\xa7\x8f\xce\x5c\xb7\xeb\x65\x9e\x59\x76\x7b\x08\x7f\x94\x55\xd3\x8b\x3c\x2a\x2a\xa3\x1e\x2e\x56\x75\xf3\x10\x02\x6e\x99\xe6\x96\x44\x2c\xc1\xdb\x9e\x1b\xd8\x83\x40\x07\xa6\xcf\x5e\x7a\xdd\x96\x2a\x12\xc4\x39\xcd\x0a\xc6\x23\x15\x5a\xe3\x57\x53\x86\x22\x02\xcb\x5d\x0d\x39\x56\xb0\xc1\x15\xfb\x3b\xe3\x2d\x10\x02\x79\xb1\xc6\xca\x38\xff\x46\x52\x93\xb8\x5b\x43\x80\x0e\xc0\xb6\xa1\xc7\xa4\xab\x24\x5f\xf7\xc3\xa0\x27\x8e\xe8\xd1\xe6\x19\xf8\x38\xb9\xa8\x17\x7a\x99\xb1\x42\x85\xc3\x13\x08\xc7\xd8\x75\xc3\x19\xbc\x5c\xad\xc7\x5c\xc9\x30\x35\xb9\x99\xe9\x06\x25\xb8\xb1\x7b\x7c\x9e\x15\x29\x62\x4b\xd8\xde\x91\x5a\x82\xfb\x47\xc0\xb5\xdc\x0f\x17\xf9\x84\xd1\x97\x95\x01\x07\xd0\x7f\x73\x0e\x1c\xa9\x07\xb6\x59\xd7\x35\x5b\x5e\xe3\xd9\x0f\x6f\x18\x89\xef\xe0\x54\xb9\x34\x05\x63\x9c\x27\x7c\xc0\xdb\x75\x1c\xdd\xda\xe4\xaf\x27\x9c\x80\xa8\xa1\xb1\x23\xce\xf8\xd8\xd2\x7a\xf7\x0c\x28\x3f\x03\xa4\xd3\x24\x8f\x7d\x82\x6e\x7c\x61\xa5\x37\x86\x00\x1d\x07\x79\xc0\x3d\x24\x45\x85\x27\x79\x28\xcb\x92\xc3\xae\xe7\x6a\xb8\x3e\xde\xf9\x63\xc1\x85\x0c\x7f\x29\xb3\xa2\x97\x0c\x13\x74\x67\xfb\x38\x90\x97\x66\x60\xb1\xf4\xf7\x52\x00\x4b\x47\x46\x28\x06\x14\x0d\x6e\x1f\xbe\x2e\xdc\xce\x3f\x22\x7a\xc5\xcb\x28\xf4\x66\x1b\xcb\xc8\xc4\x4e\x5c\xc8\x6d\xc3\xe7\xa4\xfc\xdb\x97\x0a\x62\x70\x8d\xb6\x67\x30\x46\xe3\x62\x38\x89\xe0\x44\xd4\x6e\x28\x51\xf2\x5c\xaf\xe8\xe3\x5d\x5e\x9b\x66\xb5\x84\x8c\x3f\xf2\x41\x60\xfb\x41\x8e\x52\x72\x79\xf2\x12\x94\x19\x31\x85\xf3\xa2\xf3\x84\x6c\x75\x58\x38\xff\x75\x16\x60\xe5\x68\xc0\x9f\x4a\x7c\xb1\x38\xc5\x8f\x0b\xf6\x01\x20\x7c\x1a\x86\x4e\x85\xd7\x80\x78\x18\x8c\xcc\x9f\x99\x48\x7d\xbe\xed\xde\x0c\x3b\x79\x1f\x71\xdc\x86\x11\x1f\x24\xff\xec\xf4\x1a\x64\x4c\xd6\x32\xe2\x88\x78\xc9\x30\x15\x0e\xef\x86\x1a\x05\xf9\xb2\x10\xbb\x2f\x4e\xe6\x2f\x36\x11\xa7\xa4\xeb\xde\x55\xbb\xbb\x00\x21\x13\x0e\xbb\x65\xec\x76\xdf\xa2\xb9\xbb\x5d\xda\x0f\xe4\x4f\x41\x6e\x6b\x74\x84\x73\x3b\xf0\x12\xce\x55\x85\x3e\x3b\x96\xd1\x1c\xa0\xff\x1c\xb2\x3d\xcb\x26\x5b\x64\xbf\xfa\xb0\xb6\x80\x34\xa2\xe4\x23\x8e\x4b\x04\xbd\x25\x01\xe3\x41\x64\x70\x8c\x51\x59\x61\xfc\xed\x94\xfb\x01\x8a\x47\xef\x45\xd8\x19\x51\xda\x2d\x49\x39\xda\xa5\x16\x7a\xb9\x34\x70\x19\xd4\xa1\x40\xf5\x0b\x4a\x3c\x30\xb9\xff\xab\x42\x54\xec\x91\x4f\x6e\x33\x9b\x24\xac\x48\x1a\x02\x0c\xa5\xbb\x19\xe8\x4e\x61\xe9\x6d\x31\x41\x95\x9b\xb1\xf3\x6e\x3b\x3f\xf4\xea\x03\x32\x90\xd4\x87\xb8\x72\x84\x12\x52\x2e\xb2\x86\xc0\x08\xfe\x3f\xc5\xbc\xfd\xb9\xb0\x3c\x84\xbf\xb0\x6b\xd5\x2b\x0b\x42\x47\xe1\x6a\x41\xce\x61\x18\x81\xbe\xe3\xa3\xfc\x6e\xed\x66\xe1\x10\xff\x02\x9e\x65\x05\xd7\xde\xb2\xe4\xe1\x61\x0a\xcd\xc3\x64\xe9\xc0\xb9\x50\x8d\x3a\xeb\xdc\xf1\x1d\x5e\xcf\x1b\xd8\xc6\xdf\xc9\xdc\xfc\x07\x79\xb1\x5b\x6f\x58\xb9\xc0\xb0\x23\x68\xe5\x76\x76\x20\x30\xf1\x27\x33\x7b\x79\xb5\xec\xa9\xa4\xf7\xf7\x9b\xf7\xef\x87\xfd\x44\xed\xb6\x39\x88\xf7\xef\x87\xbd\xe3\xf1\xf0\xe1\xfb\xf7\xc3\x9b\x7e\x02\xde\x51\x3d\xfb\xfb\x0f\xfd\x24\x60\x23\x28\xd7\xa3\x8b\x7e\xf5\x60\xbc\x5b\x8e\x3a\xd8\xf9\xf1\xb7\x43\xdd\x19\x90\xfa\x8b\x0c\x48\x95\xfc\x1c\x7f\x75\xaa\x7e\xf1\x59\x66\x70\x5f\xf4\x02\xe2\x74\x73\x23\xf6\xf1\x91\xd0\x16\x0c\xdd\x63\x4b\x2b\x68\x97\x78\xc9\xde\x7e\x18\xde\x63\xc1\xc7\x74\xf7\xc9\x0f\xed\xa4\xda\xa5\x58\x2c\x89\x37\xf3\xa5\x3d\x39\xe8\x47\x1f\xb9\x05\xb7\xfc\x86\xd3\x69\x04\x4d\x6d\x2c\x92\x3c\x7c\x08\x86\xec\x8e\xa2\xfd\xd6\xbd\x2c\x6e\xc2\x5f\x38\x31\xab\xe4\x4c\x3a\x2b\x71\x6c\x49\xf7\xe5\xe9\xf3\xa2\x7e\x94\x55\xf1\x16\x25\xe5\x89\xa8\x26\x7c\x73\x0b\xe3\xb1\x99\xa5\xf1\x9b\x0b\x3c\x5f\xb2\x49\xc4\xa9\x02\x8f\x4a\xae\x51\xa9\xaa\xcb\x85\xe1\x14\x9f\xa9\x15\x11\x17\xe8\x45\x4f\x67\x04\xfc\x7b\xb9\xda\x9e\xbe\x2c\xb3\xb4\x56\xcb\xb2\x31\x45\x63\x0f\x30\xd0\x74\x5b\xb4\xae\x39\xc9\x72\x59\xa8\x74\x05\x91\xe9\xd0\x84\xce\xed\xbd\xda\x2d\x01\xf6\x3d\xa9\xf2\x7b\x7e\x67\xc7\xed\xb0\x76\x44\x4d\xc8\x87\x36\x46\x57\x69\xb9\x2e\x24\x2b\xca\xcf\x42\x4f\x24\xc9\x87\x46\xea\x97\x6e\x5e\xd4\x81\xc4\x3a\x98\xe7\xd0\x13\xb0\x55\x4b\xec\x46\x4d\x2e\x52\x21\x85\xe9\xc4\xf3\xfa\xc9\x3b\xa9\x71\x30\x2d\xc3\xc2\x16\xa5\xca\xcb\x62\x66\x2a\x60\x85\xee\x7d\x76\x2b\xe6\x92\x23\xe8\x51\xd4\x76\xd4\x55\xec\xc3\x26\x47\xa0\x04\x6b\x49\xda\x68\xf2\xa4\xde\x09\x58\xa0\x4b\xb0\x71\x22\xaf\x8f\xdf\x97\x45\x7e\xfd\x3d\x6f\x9e\x80\xed\xc9\x06\x6a\xb2\xaa\x90\xe1\x51\xe7\x60\xee\x78\x87\xf2\x77\x81\x53\x3a\x27\xb6\x9d\xd9\x1d\xcf\x15\xfd\xa8\xc1\x1f\x11\x9d\x06\xc0\x4d\x8a\xf1\xc4\x29\xba\x8b\x6e\x87\xb9\xae\xdf\xfa\x95\xc7\xce\xa1\x29\x0f\x22\x36\x49\x4d\x85\xb7\x04\xbe\x6e\x5f\xd7\x9d\x75\xb8\x12\xb2\x22\xcf\x29\xe0\x8d\x6e\x85\x47\x35\xc6\x1b\xc4\xd6\x3b\x59\x55\x78\x85\x70\xd8\xd9\x51\xab\xff\xb1\x2e\x3b\x2d\x79\x15\xed\x9d\xcf\x99\x5a\x03\x0d\xf6\xbd\xcf\x36\x86\x8c\x3d\x66\x93\x76\xf8\xf8\xab\xdb\x79\x33\xb0\xef\x8c\xce\xf3\x55\x65\x8f\xfe\x12\x43\xd8\xc9\x02\x34\x2a\x57\xcd\x21\x3b\x1a\x75\xa5\x15\x5f\x50\xfa\xf0\xa2\x5c\xbb\x8e\x09\x83\x12\x91\x79\x62\x1f\x36\x68\x0b\x6f\xe3\x1d\x9d\x13\x88\xf7\xfb\xb6\xb3\xfc\x8d\x0c\x08\x1b\x8d\xd4\x1b\x5e\x8a\x54\x51\xbd\x87\x0e\x6a\x42\x55\x66\x66\xae\x96\x76\x54\x70\xd9\x12\x0d\x62\x36\x08\x77\x1d\x65\x3b\x09\x76\x02\x34\xeb\x97\x36\xe0\x43\xc4\xb5\x1f\xf8\x85\xca\xe7\xcc\xd9\xd1\x81\xc7\x6d\xce\xf5\xba\xe1\x8c\x93\xbe\x7a\xaa\xf6\x2d\xd9\x4b\xca\x22\x21\x2e\xeb\xf0\x56\x3b\x03\xcf\x24\xda\x8a\xd8\x91\xf1\xad\x77\x68\x44\x17\xe9\x42\x0e\xd5\x47\x3d\xb3\xbd\x08\xfe\x3d\x8d\x71\x3d\xcf\x48\x65\x8b\xa5\xd0\x7b\xcd\x32\x3f\xb2\x49\x96\xb6\x49\x41\x4c\x15\xca\xb0\xb4\x9d\x1d\x7a\xda\x91\x86\xe0\x3c\x6b\x16\xba\xbe\x18\xab\x1d\x75\x80\xa0\x9d\xba\xc9\x2e\xfd\x9d\x73\xa8\x76\xd4\x23\x78\x41\x9a\xe7\x1e\x79\xf3\x5a\xfe\xb2\xef\x46\x30\xcc\x6a\xae\xf1\x28\x24\x3b\xc7\xea\x91\x1a\xab\xc7\x87\xbe\xa8\xb4\x55\x76\xe9\x7c\xba\x8a\x7e\xa8\x0c\x4f\x92\xf8\xfe\xd8\x4d\xc8\xbf\xcf\x0d\xf2\xec\x7a\x60\x66\xbb\xde\xb9\xd1\x05\x3b\xe1\x92\xde\x1e\x11\xca\x30\x20\x1c\xfd\x82\x55\x65\xf8\x46\x60\x7e\x1d\x42\xcf\x62\xcf\x27\x92\xe1\xf0\xc4\xe9\x6a\x66\x9a\xd0\x28\xc1\x0f\x8f\xbc\x2b\x8c\x30\x71\x81\xc5\x1f\xd2\xa7\x14\x93\x72\x01\xe8\x71\x1c\xce\xbc\xac\xcc\xd2\x10\xe4\x1c\x51\x49\x38\x70\x8c\x8b\xe1\xb2\x35\x54\x33\x97\xb8\x3c\xc4\x04\xa0\xac\x90\xd0\x97\x53\x1a\xe9\x19\x4d\x49\xcb\xcf\x9e\xee\x18\x5f\x4e\xec\xab\x67\x08\xbd\x1f\xea\xb2\x9a\x52\xa5\x95\x5e\xab\x72\xd5\xd4\x59\xca\x39\xcd\x0b\xa4\x9f\xbf\x5b\xfc\xc0\x69\x0c\x36\xd9\xce\x8e\x67\x39\x68\x1b\xb6\x1f\x85\x06\x0e\xf2\x81\x6d\xb3\x1b\x9d\x74\xd9\xa1\x39\xd3\x98\x97\x55\xb9\xd4\x33\xc4\xcc\x00\x2c\x0d\x4b\x09\xd2\x4b\x5d\x58\x79\x70\x69\x2a\xf5\xf3\xe3\xe7\xce\x0c\xb2\x34\x13\xd5\xbb\xff\xf5\xd7\x9f\x1f\xf4\xa9\x3a\x74\x30\x80\x8d\x55\x8a\x8c\x21\x0d\xf8\xe0\x30\xc0\xff\xa1\x5a\x03\x89\x44\x80\x5b\x54\xa8\xa8\xc0\xa3\x49\xd9\xab\xbc\x77\xff\xeb\x2f\x1f\x3d\xe9\x6f\x9e\x19\xc7\xa1\x15\x25\xb5\x6b\x1f\x3a\xb6\x05\xbd\x77\x9c\x1e\xc2\xfb\xca\x7b\xb6\x40\x1d\x75\x8b\x77\x81\x24\x47\x09\x31\x5a\xf7\x8d\xa8\x66\x97\x3d\x3d\xbd\x21\x03\xae\xe5\xc9\xaa\x1a\x2e\x75\x65\x8a\xe6\x4d\x99\x1a\xc1\x97\x39\x40\xf1\xc9\xaa\x82\xff\xb4\x0a\xfb\xaa\x1c\x73\x42\x5a\x2f\x5b\xba\xef\x9d\xfa\xf0\xcb\x96\xfe\x0b\xd4\xb2\x3a\x4d\x69\xce\x89\x1f\x9f\x95\x8d\x5c\x19\xd5\x33\xc3\xd9\x70\x80\xee\x04\x6c\xa8\x56\x60\xd8\x68\xf4\x64\x6e\x52\xf5\xe2\xed\x6b\xc1\x3f\x43\x73\x47\x47\x18\x33\x1b\x3a\xa1\x49\x86\xa3\xbf\xb9\xf3\x56\x2a\x63\xb7\x96\xcc\xac\x59\x50\xc3\x71\xe3\x8a\xd9\x67\xd4\xe9\x6e\x68\xda\xef\x32\x29\x3b\x94\x85\x20\x62\x76\xcb\xc2\x86\x21\x2d\xb5\x97\x60\x7b\x38\xc9\xae\x3f\xa7\xd9\xee\xee\x19\x68\xa7\xb6\x99\xd0\xff\xe8\xf7\xfe\x49\x53\x5a\xd1\xb5\x27\xb7\x8d\x60\xec\x8e\x54\x86\x79\xf5\x70\x90\x62\x27\x10\x2c\x47\x4b\x3b\xd0\xb6\xd3\xd0\xb5\x23\xcc\xf4\x5b\xce\x54\xdb\x8b\x55\x66\xc0\xd3\x7a\xae\x19\x89\x86\xea\x9f\x4a\x6e\xf3\xac\x43\xd5\x86\xdf\x61\xbd\xa1\xdb\xa8\x93\x4b\x02\xa1\x9e\x49\x09\x7c\x27\xa3\x89\xc4\xce\x7a\x13\x5c\xa4\x61\xc7\x89\xfd\xd8\xd9\xb1\x35\x9c\xf2\x9f\x67\xed\x76\x9d\xb8\x8c\x2d\x0a\x3b\x8b\x87\xed\xa6\xad\x1e\x6d\x26\x7f\x09\xdd\xd1\x65\x62\x60\x83\x6f\x3a\x64\x30\x2c\x40\x11\x32\x2f\x70\x6b\xf6\x3a\x62\xa8\x3e\xfa\x6b\x50\xb0\x58\x11\xc8\xf5\x79\x99\x5e\x73\xb4\x8d\x49\x39\xed\xa9\xad\xd2\xa5\x99\x4f\x01\x73\x45\xb2\xb2\x6d\xc2\xc6\x3b\x92\xba\xf3\x23\x57\x18\xec\x47\x54\xb2\x38\x22\xf8\x81\x1b\x12\x62\x2a\x3f\x73\x37\x84\x3f\x8d\xe5\xb2\xd7\x6f\x5f\x16\x5e\x29\xd2\xb1\x1a\x2d\x42\xca\x9c\xa3\xd2\xcc\x5d\xbd\x78\xfb\x9a\xd1\x43\xe9\x5c\xd2\xd5\xef\x61\xdc\xf4\x82\x5c\x31\xe1\x3f\xba\xf6\xa7\xd7\x47\x9e\x3a\x39\x25\x9c\x3c\x38\xec\x48\x1a\x30\x3b\xcc\x03\xc6\x53\xa5\x4b\xe4\x52\x57\x99\x06\x0f\xb7\x73\xa3\x7a\xf7\xbf\x38\xf8\x72\xbf\x2f\xf6\x82\xdf\x9d\x1d\x89\x35\xec\xe8\xdc\xa5\xdc\xff\xc4\xab\x44\xf4\xb6\x32\x7b\x8d\x4b\x81\xa5\xca\xe2\xbb\xb7\x6f\x89\x28\x81\x7f\xc4\x1a\xfd\x8d\xc1\x6e\xfd\xdd\xdb\xb7\xbd\xbe\xcb\x28\xb5\xe5\x09\x39\xf6\x41\x9c\x1a\xa9\xce\xb1\x45\x22\x0b\x95\x2f\x1b\xe7\xf0\x96\xfd\xa3\xed\x23\x7a\x48\x38\x8e\x6e\x3d\x88\xb7\xaa\x01\x0b\x71\xed\xb3\xac\x21\x61\x4b\x21\x19\xd1\xb9\x43\x3c\xdc\xda\x20\x62\x49\x0f\x79\xee\x1f\xf6\xce\x9d\xa7\xcd\x9f\x86\xbe\x8b\x9f\x3e\xea\x66\xb1\xdc\xa4\xa7\x8a\x43\x68\x24\x29\x90\x58\x40\xe4\x27\xd2\xd2\x39\xf8\x75\x66\xd7\x25\xad\x1c\xbc\x7c\x20\x1c\x39\x98\x00\x3a\x06\x46\x88\x4c\x52\x18\x0a\x46\x3f\xcd\xae\x7a\x91\xfc\x42\x1a\x8c\x5f\x06\xaa\x32\xcd\x80\x10\x29\xd2\x96\xa9\x86\x48\xef\x7f\x53\x38\xcf\x29\xa3\xcf\x54\xb3\x3b\x53\x07\x0b\xb5\x74\xeb\x92\xc1\xf8\x96\x3b\x6f\x19\xd0\x5f\x07\x36\xa3\x8d\x2c\x6e\xfc\x9d\xcc\xaa\xce\x30\x75\xd3\xec\x6a\xcf\xa4\xe1\x7c\x56\x1a\xa0\xab\x9b\xb9\x46\x22\xd2\xb3\xdb\x11\x5c\x48\xfa\xc1\x14\xdb\xaa\xec\xa8\x4f\xf7\xcf\xf8\x6e\x17\x42\x96\x63\xe9\x58\xfa\xa0\x7c\x91\x42\xe6\xa5\xa0\x4d\xf3\x82\xf6\x00\x44\x39\x39\x53\x07\xea\xaf\x49\x0c\xb5\xf2\x48\x6e\x20\x87\xd8\xb9\xce\x72\xcb\x50\xa5\xa6\xce\x2a\xa1\x31\x63\xb2\x2b\x2b\x14\xec\xba\x78\x4c\xcb\x83\x33\xce\x9b\xed\x77\xb3\xec\xd2\xcb\x22\xda\x13\xc1\x7a\x38\x45\x67\xab\x55\x6f\xed\x93\xb2\xce\x4f\xab\x42\x58\x79\xc1\xc1\xe0\xd0\x4e\xc8\x35\x98\xcd\xd6\xba\x60\xb0\x84\x65\x20\x2f\x9c\x9b\xc2\x58\x91\x61\x55\x6f\x60\xc1\x68\x3f\x7b\xb3\x01\xf4\xf6\x14\x92\xe9\x7c\x32\x2f\xe6\xae\x6c\x8a\xa1\x74\xab\x4b\xb5\x0f\x49\xc6\x44\x11\xcf\x75\xc2\xf7\x42\x9a\x2f\xf8\x1b\x61\xc6\x68\xf7\xe5\xd5\x62\x61\xd2\x4c\x37\xe6\x0e\x06\x51\xa8\x1f\x0c\xfb\xd0\x01\x6e\x39\x02\x2a\xab\x83\x3e\x9a\x9e\x8b\x52\x1a\xd9\xca\xca\x7d\xfc\x88\x0b\xf0\xdb\x5e\xdd\x57\x5a\xd5\xab\x73\x06\x6e\xfe\xe7\x4a\xe7\x68\x9f\x2f\x6b\xb4\x69\xce\x0d\x65\x5b\xc4\xf6\x7a\x80\x45\xeb\x00\x93\x65\x53\x7d\x09\x72\xb0\xdd\xa1\x87\xb8\xb9\x89\x15\x11\x1f\x2a\x73\x87\x0d\xc5\x5f\x84\x72\xab\x49\xdb\xd0\xdb\xf3\x5f\x0e\x83\x22\x24\xa0\xfb\x1a\x53\x4e\xd1\xb2\x45\x6e\x81\x40\x9c\x7a\xdd\x24\xa5\xc3\x6e\x44\xa4\xa5\xcf\x5a\x72\x67\x31\x12\x3e\x10\x3e\x11\xf0\x16\x33\x43\x72\xbf\x80\x5f\x60\xdd\x32\xc6\xd8\xbe\x6c\x82\x7b\x20\xfe\x2b\xe2\x49\x2b\xd3\x74\xab\xfa\xef\x60\x34\xdd\x7b\x7b\xaa\xc4\x3e\x13\x05\x3e\xde\x75\xcd\x05\x34\xad\xac\x9b\x3b\x89\x5a\x9b\x70\xc9\xaf\xb8\xef\x5d\x2f\xbb\xe8\x57\x47\xd0\xea\x86\x1b\x97\x4f\x5b\x87\x96\x7f\x1e\x68\xf5\xdd\x8d\x48\xd8\x4c\x60\x07\xfe\xd4\xeb\x30\xf6\x5a\xea\xb6\x9d\x51\x58\xa3\x17\x0e\x49\x59\x75\x28\xc4\xcd\x22\x75\xe4\x30\xa0\xb9\xa3\x91\xfa\x36\xd7\x93\x8b\xbd\x79\x99\x1b\x75\xf2\x97\x3f\xaa\xa7\xab\xda\x7c\x03\x69\x95\x34\xe6\xa7\x34\xa6\x56\xbd\xfb\x07\x8f\x0f\xbe\xda\x67\x1d\x09\xc2\xa0\x16\x65\xb1\x97\x9b\x69\xb3\x07\x31\x12\xc8\x69\x01\x2a\x6a\x01\xf2\xed\xb4\xbc\x52\xbd\xfb\x8f\xbf\xfa\xe2\xc0\x2b\x40\xc2\x01\xa1\x8c\xe5\x95\xf0\x3b\x3b\xaa\x47\xa7\xfa\x7c\xd5\x34\x65\xe1\xcf\xb3\x0f\x6c\x84\xc6\x12\x79\x70\x85\x22\x02\xb3\xcc\xda\x3b\xb2\x5b\x23\x61\x65\xd8\x79\x56\x47\x14\x0f\xb9\xdf\x65\x55\x42\xaa\x07\x68\x00\xf8\xf4\x34\xab\x35\x30\x8f\x2e\x06\xb3\x77\xff\x8b\xaf\x0f\x0e\x06\xea\xfe\x57\x07\x5f\x7c\x3e\x50\xf7\x0f\x0e\x1e\x7f\xf5\x08\xfe\xfd\xf2\x8b\x27\x92\x4f\xb7\xed\xba\xcf\x5d\xea\xdb\x8d\xc3\x11\xa7\x8c\xf6\x89\xf4\x62\x73\x89\xff\xec\x4d\x00\x09\xdc\x82\x79\x8c\x52\xb9\x6d\xb2\x6e\x67\x92\x1d\xf7\xc3\x9e\x94\xc5\x34\xcf\x26\x24\xdf\xb8\x9c\x5c\x9c\x64\x4a\x60\xd9\xd8\x4d\xf0\x68\xff\xb1\x23\x43\x35\xc0\x70\x77\x58\x7b\x77\x55\xa2\x12\xd1\x16\xcc\x08\x8d\xeb\xd4\xee\x7f\xcb\xf6\x6e\xa2\x49\x5b\x71\x41\x49\xb8\x85\xd7\xa2\x07\xb2\xf6\xe9\x73\xe1\x68\xe1\x02\xa3\xe1\x80\xe5\x6f\xb0\x83\x8c\xe3\x0f\x86\xd3\xac\x48\xc5\x57\x8c\x52\x73\x0a\x5f\x9d\xa9\x7e\x04\x0e\xe8\xc1\xee\xba\x46\xd4\x31\x86\x4d\x4e\x5e\x1d\x70\x79\xb2\xc6\x96\x35\x37\x24\x10\x58\xeb\x6f\xb0\x2b\xc7\xa8\x34\xf0\xe4\x88\xb7\xcf\xc7\x8d\xb6\x6f\x49\x6c\x39\x7f\xb9\xcf\xd0\xde\x43\x58\xcd\xfc\x7a\x0f\xee\xe4\x7e\x40\x2d\x3a\xce\xf0\xd3\xd8\xeb\x22\x0e\x61\xe8\xe8\x32\xce\xb5\xef\xb3\x77\x2b\x40\xaf\x82\xb0\x85\xbe\xea\x04\xdc\x93\xd5\x1f\x06\x5e\x6b\xaf\x8a\x49\xbe\x4a\x4d\x0d\x26\x7b\xa1\x14\xae\x55\x3d\xd7\x94\x14\xf7\x4f\x1c\x19\x66\x79\xe2\xd7\x2e\x20\x0c\xe3\xc9\x97\xf5\x58\x25\x3a\x6f\xfe\x64\x58\x7e\x04\x40\xc7\x89\xc9\x41\x6e\x9a\x34\x15\xc0\x5b\x85\xdc\x1b\x2a\x26\xe6\xba\x86\xc4\x75\xda\x16\xa8\x4c\xae\x1b\x93\x52\x01\xb0\x7f\xd9\xc7\xa4\x4f\x68\xb2\x85\x39\x69\xf4\x62\xa9\x2e\x33\xb3\x46\xff\xbe\x84\xed\x68\x2a\xe9\xe3\x78\xa6\xd9\x15\xa1\x6a\x70\xa0\xd2\x85\xb9\xe6\x27\x76\x3a\xb8\xbf\x93\xb9\xae\x94\xfd\xcf\x73\x4b\xe8\x2e\xcc\xb5\xfd\xbf\xfd\x1d\xd5\xb9\xb5\x85\x11\xc2\x1d\x37\x97\x65\x47\xb2\x42\xe7\x6d\x50\x16\x74\x3e\xb4\x64\xc8\x56\x2c\x5c\x70\x84\x82\x0a\xcb\xb0\xbd\x22\xd2\x78\xd1\x4b\xd7\xc4\xd0\xf5\x74\x9b\x0d\x1c\x1d\xef\xc6\xfe\x19\x0d\x26\x54\xe5\xc9\x3b\x3a\x36\xc3\x43\x4c\x5f\xd7\x44\xd1\xd5\x82\xff\x00\xb9\x37\x45\xf3\x57\xfa\xf7\x6f\xaa\x9c\x4e\x6b\xd3\xfc\x95\xfe\xfd\x1b\x84\x7e\xfc\x15\xfe\xfb\x37\x55\x4f\x2a\x63\x8a\xbf\xd2\xbf\x7f\x53\x4d\x49\x91\x71\xff\xea\x1c\x13\xaa\x05\xf2\x53\xe5\x64\xa0\x52\xfb\x9f\xf3\x32\xbd\x26\x1f\x6c\xea\xac\x98\x38\x7c\x22\xb4\xb0\xcf\x75\x3e\x59\xd9\x8d\x86\x5d\x1d\xfd\xcd\xca\x75\x8b\xac\xae\xd9\x57\x85\x46\x38\xfa\x9b\xd2\x97\x3a\x83\x3d\x1c\xaf\x1d\x0e\x92\xd7\x6e\x67\x47\xac\x05\x4d\xcf\x76\xe7\xba\xbe\x28\x27\x11\xd3\xb1\x59\xa5\x4e\xf4\x28\xf5\x9f\xbc\x28\x27\x43\x7e\x2b\x42\x0c\xed\xb0\x4b\x48\x48\xef\x4a\xd9\xbf\xdd\x85\x12\x74\xb9\xdd\xd3\x5d\xcc\x57\x0d\xaa\xe4\x72\x32\xac\x27\x55\x99\xe7\x3f\x98\x29\x74\x06\x2a\xde\xd9\x81\x7f\xa3\x57\xfb\xaa\xaf\xf6\xc2\x6f\xb1\xca\xce\x6f\xc3\x57\xfb\x8e\xb2\xfb\xce\xfd\xad\xdd\xb9\xbf\x75\x77\xee\x5d\xb9\x54\x1b\x3a\xc7\xaf\x36\x76\xae\xf3\xdb\xf0\xd5\x7e\x87\x06\x3c\x3c\xd4\xc0\x84\x8c\xd5\x01\xdc\xca\x96\xa5\x3b\x54\x8f\xe0\xf7\x22\x4b\xd3\xdc\x1c\xaa\xc7\xf0\x17\xb8\x30\x70\x0d\x6f\xca\xc6\x8c\xe9\x14\x31\xde\x68\x51\x56\x0b\x48\x03\x92\x0e\x54\x5d\xaa\x14\x18\x0c\x4c\x73\xe1\x77\xdc\xb6\xa4\x08\xb6\xc7\x58\xc5\x06\x21\x25\x24\x1f\x3d\x2e\xbd\xa3\x0e\xd4\xb1\x3a\x80\xdc\x15\xee\xd1\x23\x75\xac\x1e\x87\x8f\x9e\x90\x91\x7b\x3f\xca\x4a\x7b\x27\xf9\x98\x66\x57\x1b\xb4\x69\xf2\xe0\x74\x78\x05\x44\x20\x39\x41\xe5\x2c\xe2\xb0\xc7\x85\x53\xc5\x79\x8c\xbf\x50\xf3\x46\xbe\x66\x34\xab\x78\xa1\x85\x59\x8b\x48\xba\x80\x2c\x82\x50\x4d\xe0\xe8\xe3\xb9\x4d\x7c\xcc\xfb\xf1\xa5\x74\x6d\x20\xc8\x32\xbc\x68\x18\xd9\x84\xef\x1d\xe1\x91\xe5\x86\xbe\xcd\x65\x9d\x5b\x70\xd7\x17\xea\x48\xb9\x3a\x71\x2d\x45\xe4\xb5\x74\x78\xe9\xab\x63\x6c\xd3\x93\x6c\xe6\xd5\x5c\x04\x77\x67\x79\xbe\x09\xb9\xb4\x0c\x3c\x84\x19\x75\x3d\x18\xe2\xfd\x4f\xdf\xc1\x1f\x2e\x01\x4d\x58\xa4\xcf\x89\xae\xe0\x4f\x1a\x35\x2b\x3f\xdb\xfe\x1d\xe1\x84\x3a\x8f\x70\x2b\x79\x94\xcb\xeb\x2e\x77\x6a\x09\x9e\x02\x59\xf3\xb0\x28\xf3\xe7\xbc\xe5\x45\x86\xbd\xa0\x8d\x20\xd5\x9e\xc0\x44\xe6\x18\xff\xe7\x65\x95\x96\x97\x5a\x3d\x1a\x7e\xae\x7a\x88\x69\xd0\x47\xce\xfd\xf3\xcf\x9d\xf8\xe6\x7d\xa6\x29\xa9\x2b\x68\x5a\x34\x71\x26\x87\xae\x92\xd4\x5c\x66\x13\x83\x8a\x74\x02\x46\xb8\xf7\xbb\x9c\x25\x02\xda\xdf\xd1\x5b\xc2\x6a\xf8\x62\xb8\xbf\x3b\x50\xcf\xe7\x95\xdd\xdf\x4f\xd5\xa3\xaf\xee\x71\xb2\x37\xe2\x9c\x38\xf3\x2c\x45\xe9\x59\xf6\xbf\x80\xa4\x1d\xf7\x3f\xdf\x7f\x62\xe5\xaf\xc7\x07\x4f\x1e\xf7\xc3\xb3\xc9\x17\x52\xe4\xfa\xb5\xc9\xad\x43\x7e\x12\x19\xbc\x43\xc6\x93\xf7\x0b\x01\xad\x1c\x47\x0f\x5a\x37\x3d\x6d\x0d\x76\xa5\x13\xbc\x2a\xa9\x25\x88\x3f\xc9\x4b\x9d\x8e\xbd\xab\x16\x9b\x3c\xbc\x85\x21\x5b\xe8\x99\x19\xda\x62\x41\xf8\x85\x93\xbb\x9d\x77\x02\x94\x81\x7a\xd8\xad\x60\x0c\xf2\x27\x8c\x05\xd9\x93\x72\xb2\xaa\x45\x63\x60\x8f\x0e\x34\xff\xd9\xd4\xa7\x29\xab\x4b\x75\x9e\xaf\xaa\x11\x7c\xa5\x6a\xf3\xcf\x15\x00\xca\x66\x35\x23\x62\x20\x11\x68\xf9\x3d\x86\xde\xa8\x20\x97\x41\x70\x6c\x07\x08\xc1\xce\x0e\x91\x1d\x68\xc2\x0b\x3e\xfe\xa1\x57\x23\x45\x08\x07\x42\xb8\x09\xb5\x26\x18\x7e\x97\x30\x48\x84\x1f\xbd\x1d\x0c\x0f\xfe\x93\x7a\x7d\x74\x47\xaf\xc1\x29\x30\xea\xb4\x7d\xf6\xef\xf5\xb9\x5c\x35\xa2\xd3\x74\x47\xfb\x25\xb3\xf7\x36\x01\x81\x0c\xd4\xb4\xb5\x80\x75\x19\xa1\x97\x30\xd6\x8f\xbf\xc5\x3f\x65\xec\x43\x0f\x76\xc6\xad\x25\x6e\xdc\xa8\xf8\xf1\xc6\x48\x7b\xd4\xde\xe8\x85\x03\x1a\x73\x30\x37\xf1\xe4\xc0\x87\x9f\x38\x3b\xc1\x80\xab\xb2\xae\xf7\x28\x41\x35\xc0\x17\x42\x5c\xdb\xe4\x7a\x40\xcc\x86\x9c\x07\x6e\x45\x95\x85\xca\xb3\xe2\x02\x25\x16\x36\x28\x6f\xbc\xdd\x63\x90\x23\x3f\x28\x49\x23\x06\x2a\xd1\x49\xe8\xdd\x41\x7d\xc5\xf4\x62\x18\x28\xce\xeb\x25\x15\x8f\xb7\x18\xe9\x42\xe2\xc8\x4a\xb4\x47\xfb\xbb\xee\x25\x3f\x63\x98\x1a\x9d\x9b\xaa\xe1\x30\x45\xec\x37\x82\xc1\x4c\x33\x93\xa7\xcc\x97\xd5\xa6\x91\x9a\xf3\x40\xe1\xbb\xdd\x4a\xa4\x03\x6f\x63\xea\x15\xfa\x1a\x04\x6f\x87\xb2\xdd\xa3\x96\xc6\xb4\xed\x83\xc0\xe4\x2f\x5b\x80\xdc\xd2\x86\x6e\x23\xec\x2b\xa4\xa3\x28\x81\x0b\x18\xac\x1f\xb3\xd9\xec\x1a\xf2\x4e\x97\x85\xd2\x76\xe1\x5d\xe0\x5b\x53\x2a\xae\xd5\xbe\xc9\xa6\x00\x7e\x0d\x20\x95\x9c\x1a\xf6\x3b\x7d\x61\x22\xda\xdc\x94\x0a\x1c\xf6\xb1\xaa\x07\xb5\x8a\x34\xd8\x08\xe9\x8d\x93\x4c\xb5\x70\x2b\xa9\xd3\x2f\x10\x49\x66\x73\x7f\x43\x16\xf3\xb4\xf4\x36\x6a\xf2\x27\x80\x56\x5c\xf6\x57\xd3\x0a\x29\x46\xca\x1d\xb3\x1a\x7d\xe1\xe7\x8d\x3f\x37\x85\x1e\x67\xf5\x09\xf7\x0e\xe9\xbe\x08\x49\x76\x83\x1e\x53\xfa\xb3\x2d\x9f\x04\x0d\x37\x47\x38\xdd\x9d\xd6\xee\x9e\x32\xac\x2a\xf3\xb0\x5d\x61\x9c\x63\x37\x8c\x81\x0c\x35\x10\x18\x91\xbc\x2d\x6f\x71\x17\xb9\xdd\xf8\x20\xf2\xa8\x39\xb4\x17\x11\x91\xd0\x81\xab\x26\x3d\xe9\xa9\x05\xef\x2c\x2e\x3e\x8d\x03\x6b\x37\xbd\xef\xa9\xd0\x37\x5f\x84\xd4\xc6\x1d\x6b\x77\xa9\xae\x26\x03\xc5\xec\xe7\x6f\xa8\xc4\x42\x67\x4d\x54\xc3\x37\x19\x5a\x27\xd7\x59\x33\x2f\x09\x5c\xfe\x41\x61\xd6\x0f\xd4\x85\xb9\x5e\x97\x55\xca\xbd\xdf\xee\x21\xa8\x07\x29\xef\x1d\x26\x05\xb6\xd9\x8f\x70\x1c\xdb\xdc\xac\xec\x08\x75\x1d\x7b\xf3\x32\xf4\x06\x40\x8b\x4b\x05\xa2\x68\x5d\x4d\x86\x32\x7c\x0e\xe8\x7b\x2c\x67\xd4\xd5\xe4\xd0\xbd\x24\xd9\x84\x3f\xf4\x66\x8a\x97\x78\x84\x1c\x43\x43\xce\xbd\xce\xd5\x6f\xa1\xaf\x45\x4a\xa0\x85\xae\x00\xf9\xac\xf6\xde\x4a\x54\x0f\x40\x5a\xb8\x88\xdf\x72\x6d\x2a\x05\xd1\x2f\xe0\xcc\x53\x19\x73\xa8\x2a\x33\xcd\xad\x78\x05\xa8\x0a\xc8\xc3\x20\x7c\xf9\xd0\xf5\xb2\xbd\x17\xa9\xcf\x69\xfc\x98\xd3\xf6\x76\xbe\x8c\xf3\x94\xb5\xc9\xbc\x48\xac\x3f\xdc\xf7\x35\x05\x44\xd5\x59\xe3\x8e\x85\x6c\xf9\xce\x67\x08\x13\x30\x50\x87\xe1\x9a\x91\x91\x4c\x1e\xce\x68\x11\x82\x85\xfe\x71\xd5\x28\x73\xb5\xcc\xb3\x49\xd6\xe4\xd7\x2e\x76\x32\x4c\x27\xce\xd1\xd5\x1d\x9b\x42\xee\xe2\xae\x5c\xe6\xdd\xdb\xcb\x09\xc4\x4d\xb6\x30\x35\xe8\x44\xb3\xa9\x77\xa6\xc6\x86\xf8\xca\x83\x1d\x80\xa8\xc3\x38\x12\xa7\x47\x3d\x0a\xf6\xa4\x7b\xec\x61\xcd\x8b\x72\xdd\xeb\x0b\x78\xb5\xea\x02\xfc\x82\x6a\xcb\xc2\xc3\xee\xc1\xbc\x23\x2d\x99\xde\x85\x48\xe3\x41\x76\xae\x8f\x74\x96\xb3\xda\x63\x54\xbc\x78\xfb\xfa\x31\x6f\x64\x99\xdb\xda\x6e\x4a\x3b\x69\x2f\x9f\xbf\x7e\x76\x32\xa9\xb2\x65\xa3\x7e\xd0\xc5\x6c\xa5\x67\x46\x7d\x9b\x15\x29\xc4\x1c\x8c\x46\x6a\xde\x34\xcb\xf1\x68\xb4\x5e\xaf\x87\xeb\xc7\xc3\xb2\x9a\x8d\xde\xfd\x34\x7a\xb4\xbf\xff\x78\xf4\xf3\x8b\xbd\x17\x6f\x5f\xef\xfd\x60\x2e\x4d\xbe\xf7\x78\x0f\xdb\xd8\xb3\xaf\xf6\x1f\x3f\x3e\x18\x99\xc9\x42\xef\xd5\x50\xf3\xde\x39\x56\x38\x9c\x37\x8b\x3c\xa4\x3b\xc2\xb2\x73\x84\x54\xaf\xb5\xcd\xc7\x12\x54\x6c\x00\x45\xda\x5e\x03\x1d\x85\x6e\xf1\x31\x88\x4b\x83\x9a\x5d\xd2\xf1\x36\x0b\xca\x57\x63\x9b\x9c\x10\xbd\xd8\x7c\x48\xfd\xe9\x08\x20\xfa\x81\xb7\x89\xee\x0f\x7f\xb9\xdc\x72\xb1\xd8\xe1\x45\x1c\xc1\xbf\xde\xdf\xf6\xe4\xdc\xd5\xe3\xa8\x69\xd1\xe5\x6e\x43\x7b\xd0\xe7\xae\x45\xf9\xd7\x3b\x7f\xcb\x12\x7f\xca\x28\xba\x3e\x8f\x86\xd3\x55\xa4\x17\x98\x7f\x30\x0b\x77\xd7\xc8\x3f\x8a\xf3\x49\x14\x05\x34\x4a\x76\x5f\x54\xa3\xdc\xe8\x4b\x07\x7f\xb4\x02\xe5\x38\xbc\x2d\x2f\x4d\x35\xb2\xb7\xaa\x66\x0f\x94\x3d\x4b\x3a\x50\x78\xaa\xa1\x32\xaf\x5c\x41\x0d\xc5\xc1\xe7\xbb\x1e\x54\x4e\x4f\xe6\x00\x02\xe3\x9b\x1a\xab\xc4\xd5\x9c\x0c\xf8\x15\xb4\xef\x5e\xad\x1a\x78\x43\x90\x83\xfc\x19\xfd\xe9\x3e\xa4\xbf\xf9\x53\x7e\x0d\x72\xe1\x47\x99\x65\xca\xae\x99\x15\x02\xaf\x68\x3a\xbb\x1d\x4f\x6c\x29\xcc\xa0\x6d\x27\x32\x14\x39\xa7\xd9\x15\xca\xc6\xe4\xee\xcd\x4f\xee\x39\xc7\xac\xcd\x02\x13\x60\xb5\x1a\xe2\x4a\xb7\x1a\xe9\xab\x36\x60\x89\x0a\x99\x65\x2f\x1d\x08\xcb\x58\x80\x83\x83\x56\xeb\xc8\x13\xe7\x30\x94\x02\x61\x0a\xc5\xa2\x4e\xd8\x65\x44\x44\xee\x72\x8b\x59\x1d\x84\xb6\x90\x82\x87\x6b\x7b\xf3\xed\x58\xbd\x29\x23\x43\x1d\x49\x53\xd0\x0a\x68\xc3\x47\xd0\x18\x39\x43\xb3\xf0\x89\xaa\x96\x7b\x5e\xad\xcd\x2d\xde\xdc\xa8\x1e\xff\x06\xcb\x3f\xd6\x2a\xbc\x71\x3d\x12\x2e\xcb\x92\x5c\xbe\xdf\x72\x15\x77\x11\x9b\xb1\xcf\xd0\xa1\x93\x55\x83\xd7\x1c\x68\x4e\x1e\x42\x78\xe7\x0a\x1f\xca\xc3\x8e\xca\xa7\xd9\x95\x0c\xec\x20\xf6\xb0\x32\x42\x29\x7e\xe8\xc0\xec\xfd\xe1\x4a\x98\x51\x4b\x30\x0c\x12\x4e\x10\xa8\x42\xd8\x40\xd8\x21\xcd\xb2\x9a\x6f\x40\xba\xbf\x7b\x9f\x51\xa8\x72\x37\xcc\x67\xb8\x9d\xe1\xac\x29\x52\x5e\x39\xc5\xce\x40\xa1\x42\xc7\x6b\x4d\xd4\x6d\x87\x83\x95\xa0\x08\x87\xe8\x72\x10\x4f\xf4\xb2\xc1\x70\x6c\xde\x45\x4e\x5c\x23\xf6\x13\x35\xb8\x75\xb9\x30\x65\x61\xc0\x87\xb0\x76\xf1\x9f\xdc\xf4\xbd\x00\x0c\xb2\x0a\x25\x8f\x50\x94\x0e\xcf\x28\x49\x6c\xa0\x8e\x1e\x44\x9a\x86\x8d\x3e\xb7\x21\x94\x04\x7b\xa6\x76\x1f\x7e\x3b\x7e\x77\xf6\xb7\x00\x88\xa8\x4b\xf1\x03\xc9\x9d\xc0\x44\x87\x97\x41\x6c\xcd\x13\x87\x7a\x0b\x41\xd2\xc0\x57\xa5\x9d\x8f\x01\x2c\x99\x30\xe9\x11\xfa\x8f\xfb\x4a\x40\xa0\x97\x93\x0e\xa4\x22\x5c\x37\x87\x9f\xd1\x85\x9a\xb1\xb9\xd9\x01\xe6\x58\xc4\x96\xc8\x80\xb6\x4b\x60\x05\x5e\xed\xc6\x41\xf0\xff\x4b\x33\xa1\xf6\xd4\xc1\xa7\xcd\x46\xa7\x88\x79\xdb\x84\x74\x04\xaa\x77\xac\x40\x94\x78\xe7\xb6\xe9\xf3\x1d\xeb\x50\xe2\xc0\x75\xdb\x8f\x72\xe0\x06\xf9\x2d\xee\x7d\xb6\x15\x70\x1a\x0c\x00\xe4\x51\x50\x30\x52\x71\x5a\x0c\xd4\xe8\xe1\xab\x37\xef\x5e\xfe\xf4\xe6\xd9\x0f\x0f\x47\x96\xb3\x97\x9e\x73\x76\xcc\xdf\x15\x83\x28\x52\x05\x01\x39\x28\xc9\xa6\x56\x0b\xbd\x54\x84\x7e\x5f\x8f\x5a\x0e\x2b\x02\x1b\xbf\xee\x4e\x0a\x39\x1a\x31\x66\xce\x1e\x07\x07\x87\xfd\x54\x32\x82\x0c\xab\x73\xde\x4e\x9d\x70\xfb\x5d\x55\x8a\x8a\x82\x10\x4f\x01\xc6\x41\x53\x2d\x20\x49\x63\x78\x47\xf8\x6f\x08\x50\xd3\x78\xe8\x24\xa7\x60\xf5\xba\xb4\x78\xc2\x19\x9b\x06\x6c\x74\x03\x9c\xee\x0e\xea\x4f\x8e\xe6\x61\x80\x79\x10\x91\xba\xb3\x83\x19\x81\x42\xbf\x00\x3f\xee\x01\xa4\xf7\xc1\xfe\x16\x56\x36\x0b\xc6\x48\x13\xb0\x71\xa4\xb4\x53\x7d\xe2\xa1\xb0\x99\xce\x95\xe8\xcc\xb5\x1d\xf4\xc8\x4f\x86\xeb\x1b\x76\x4e\x24\xf8\xeb\xcc\x00\x1d\x9d\x1c\x59\x27\xef\xe3\x3b\xea\xfb\x7d\x4b\xec\xb5\x62\x94\x75\x29\x74\xc6\x85\x36\x42\xa1\x3f\x9c\xb2\xed\x69\x11\x5b\xa2\x3b\x57\x14\xa0\xca\x65\xae\xf4\x2d\x3c\x70\xf6\xe2\xa2\x0c\x85\xd3\xe2\xb6\x5b\x0c\x1c\x50\x0a\x44\xcf\xe3\xc4\x9f\xb5\x71\x91\x38\x58\x9a\x19\x1e\x84\x66\x2e\xa6\xa5\xbc\x01\x7b\xfd\x61\x39\x9d\xf6\x02\x1f\x5c\xd7\x69\xec\xcd\x1d\xdc\x0c\x41\x1f\x51\x44\x06\xa8\x5a\x01\x54\xa7\x2e\x11\xc7\x15\x51\x01\x08\x43\x06\x59\x7f\xac\x97\xc6\xc7\xe8\x72\xd4\x18\xfc\x65\xb9\xb8\xe0\x41\x04\xc2\x2b\xb5\x97\xad\x3c\x2c\xed\xdb\x24\xb8\x93\x21\x7b\x85\x4f\xc5\x52\x23\x15\x8c\xb1\xa5\xb1\x7e\x9f\x4f\xa5\x2c\x5a\x9a\xf2\x4e\x7a\xda\x95\xad\xe5\x0e\x02\x7c\x20\xd2\xb6\x94\xd3\xe9\xad\xcd\xf8\x06\x02\xd0\xeb\x81\x8f\x9c\x72\x67\x13\x22\x01\x11\x57\x2c\x12\xbb\xdd\x73\xe1\x1a\x29\x09\x08\x6f\x32\xc5\xaa\xe3\x28\xbc\x06\x4a\x4a\x81\x21\xaa\xed\x50\x4c\x3a\xf5\x25\x8e\xa5\xc1\x5d\x17\x89\x1e\x12\xc0\xa0\xcb\x4f\x7f\x17\xd0\xc8\x76\x3b\x63\x09\xc6\x1d\x1f\xc4\xa2\xcd\x30\x82\xec\x6c\xf1\xed\xf0\x98\xb6\x75\xc7\xb9\xfd\x57\x6e\x34\xf2\x24\x39\xf5\x8b\x78\xc6\x64\xf9\xee\x6b\xc4\x1e\xcc\xf8\x1e\x09\x6e\x90\x3b\x2f\x8f\x18\x56\xd1\x13\x33\x0a\x28\x6e\x51\x70\xde\x7c\x5d\xa3\xb1\xc3\x98\x16\x67\x9b\xef\x95\xcd\x17\xca\xbf\x42\x51\x3b\x4f\xf7\xed\x87\x3b\x4c\x42\x29\xce\xf7\xc6\x93\xdd\x8d\x19\xd4\xb4\xd2\x81\xfd\xce\x8e\x38\x63\x8d\xaf\x89\x9d\xa3\x63\xd2\x42\x45\x29\x80\xf7\xee\xa4\x64\x32\x4b\xf3\xfe\x99\x3f\xf4\x41\x1a\xcc\xd0\x8a\x7a\x4b\x9f\xc8\x22\xe3\xb9\xd9\x8f\x51\xb6\x4e\xca\xe6\x70\x35\x6f\x16\xf9\x3b\x3d\x53\x47\x6a\xf4\xb4\x77\xbc\xad\x2b\xa3\x6f\xce\xab\x9b\x49\x99\xdf\x98\xc5\xb9\x49\x6f\xe6\xd5\x4d\xb6\x98\xdd\x80\xd5\xf9\x26\xcf\x8a\x8b\x9b\x85\x69\xf4\x0d\xa4\xab\xee\xf7\x7a\xa7\xef\xd7\xe3\xb3\xdd\xfe\xe9\xdf\xbf\x39\x7b\xd8\x7f\x3f\xfa\x66\x34\xcb\x30\x4b\x83\x9e\xbd\xc1\x3c\xe9\xa3\xa7\x5c\x08\xf3\x37\xd8\x16\xe1\xf1\xcd\xce\xfd\xe3\xf7\xeb\xdd\x43\x7c\x5c\x94\xaf\x8a\xc2\xf8\xb7\xbd\xe3\x31\x6a\x5e\x6f\xea\xe6\x3a\x37\xd0\x74\x7f\x94\x51\x16\x2c\x32\xc3\x1f\xf9\xc4\x27\x6c\xba\x07\x9d\x73\x35\x71\xf9\x34\x46\xf4\xf3\x7d\xfd\xb0\x77\x3c\x3e\xfd\xfb\xd1\xd9\xcd\xd1\xfb\xfa\x21\x27\x06\x19\x52\x9d\x15\x36\x46\xf0\x0f\xa3\xbf\xff\xe1\xe6\xfd\xa8\x77\x3c\xfe\x45\x5f\xea\x1b\x33\x59\xe8\x3e\xbe\x6f\x15\x7e\xad\x6b\x6a\xe7\xef\x76\xb6\xdf\x8f\x7a\xc3\x87\x34\xd0\x49\x6e\x74\x41\x7a\x69\xfb\xfe\x7d\xfd\xf0\xe9\x76\xef\x78\xfc\xfe\xf4\xf9\x8b\x67\xef\x9e\xbd\x3f\xbd\xd9\xdb\xeb\xdf\xd8\x07\x67\xef\xcf\xec\xef\x6f\xde\xd7\x0f\xff\x30\x9a\x39\xa7\xeb\x9f\x5d\xea\x5e\x35\xc9\x4b\x0c\x8c\xb4\xff\xd5\x33\xc0\x18\x21\xf1\x5e\xfd\x15\xd2\x8d\x60\x24\x01\x84\x93\xac\x2b\xbd\x7c\xad\x97\x2e\x2d\x43\x94\xb0\x44\x7d\x6d\x9f\x95\x4b\xd4\x5b\x9e\xaa\x83\x81\x4a\x9e\xe2\x49\x72\x98\xe6\x47\x0f\xf8\xd7\x83\x6f\x12\xfb\x7e\x84\x05\xbe\x49\x00\xf6\x0a\x95\x86\x46\xa7\xee\x7b\xf0\xb9\xa3\xa2\xf4\x9b\x00\xb2\x26\x65\x6e\x4b\x3d\xf2\xa5\x9e\x4e\xca\x7c\x56\x95\xab\x25\x95\x77\x7f\xc6\x9f\x36\x55\xfc\x65\x73\x5e\xa6\xd7\xdc\x0c\xfc\x6e\x7d\x03\x7d\x7a\xdc\xfa\xe6\x69\x53\xf1\x77\xd5\x37\xdd\x1f\xdb\xcf\xbd\x2b\xc3\xa9\xda\x1f\xa8\xc4\x7e\x92\xa8\x33\x97\x43\xa9\x3d\x95\x34\xdb\xc3\x72\xd9\xc0\x28\xd4\x91\x12\x8f\x32\xf2\x2b\xe6\x47\x0d\xb9\xe1\xba\xbf\xa7\x65\xd9\x88\xbf\x79\x2e\xe4\x23\x8d\xd9\x24\xc5\x47\x76\xea\x0f\x45\xa5\x73\xf9\x32\x6d\x75\xf4\x60\x78\xa5\x26\xe5\x62\xa9\x9b\xec\x3c\xcb\xb3\xe6\x1a\x5e\xbf\xd6\x45\xb6\x5c\xe5\x84\x9b\x83\x01\xf2\x95\xf9\xe7\x2a\xab\x20\x5d\x25\xf4\x54\xe4\x39\x59\xb8\xe2\x65\x81\xf7\xbd\x4b\x07\x5e\x16\x8d\x67\x60\x37\x7a\x7a\x20\xc6\x1b\x34\x94\x38\x9c\xc5\x56\x31\xaa\xcc\xbb\x98\x59\x59\xf0\xe0\x40\x1d\xbb\x66\xc6\xae\x0c\xc4\xa0\x42\x52\x1c\x5b\x71\x05\x00\x69\xe4\x5d\x98\x9b\xc5\x70\x66\xd8\x05\xba\xfe\xf6\xfa\x1d\x12\xa4\x5e\x02\xe3\x4a\xfa\xa7\xfb\x67\x6c\x65\x44\x54\x67\x99\x08\xa9\x0d\x64\x12\x65\x9b\xe2\x5a\x18\x48\x89\xa2\x4b\x3f\xd2\xcc\xff\x64\x96\xb9\x9e\x98\x51\x65\x30\xe3\xb4\xcb\xb3\xe7\x13\x74\xdb\x2b\x1a\x69\x83\x8b\x84\xb2\xbc\x43\xad\xa7\x84\x97\x20\xa6\x5b\xac\x02\x05\x40\x21\x59\x09\x6e\x07\xe8\x33\x43\x95\xf2\xf8\x7d\x02\x28\xc4\xa2\xc3\xb4\xd5\x56\xec\x03\x3c\xa8\x91\x65\xbc\xdc\x87\x87\x7e\xf5\xfc\x78\x44\x5a\x1c\x18\x4b\x47\xcb\xf6\xfa\x42\x78\xb3\x23\xd5\x22\x8d\x04\x65\xeb\x7b\x47\x9a\x13\x1f\x9c\x13\xf8\x01\xd0\x00\xe0\xc5\xa9\x3a\x40\xa7\x4c\x29\x28\x0a\x6f\x81\xd6\xe0\xbc\x01\xb4\x35\x0c\xda\xf1\xd5\x05\xcd\x3a\x58\x12\xe7\xfa\x12\x1c\xfa\x19\xd7\xc0\x98\x42\x99\x4b\x9d\xaf\x34\x18\xbe\x7d\x8a\x1f\xd3\xfc\x11\xa0\x24\x5e\x5e\x6a\x72\xb6\xa8\x07\xaa\x32\x53\xde\x5e\x62\x22\x20\xa2\x0c\x28\x51\x4e\xd0\x0d\x02\x3b\xf5\xde\x67\x2e\xb2\x2e\x53\x4f\x55\x1e\x84\x99\x79\xcd\x51\x6d\x9a\x9e\xdb\x99\x9c\xf1\x2f\x99\xb9\x2e\x24\x03\xb5\x2d\x5b\x0f\x92\xb7\xc2\xc1\x14\x6f\x3b\x3e\x47\x56\xcf\x19\x78\xee\xc9\x74\x46\x90\x79\xea\x79\xb9\xbc\x96\xfe\x0b\xa9\xa9\x1b\x39\xc6\x81\xca\xd9\xdf\x63\x69\x5b\x7e\x6b\x4f\x20\xfc\x7a\xbe\xaa\x06\x6a\xe5\x9e\xad\xdc\x33\xd4\x5f\x8b\xb5\xb7\x75\x46\xa7\x3c\xe4\xca\x02\x73\xf6\xc1\x50\xd9\x4e\x29\x3b\x44\xdd\x60\x42\x7f\xf2\xfe\xac\x25\x38\xb5\x69\x26\x43\xd7\x42\x1b\x7d\xba\xae\x26\xde\x73\x8e\xbb\xde\xa9\x61\x84\x92\x87\xae\xd8\x73\x08\x7d\x0c\x97\x08\x86\xe0\x67\x40\x09\x28\xb7\x5a\x1d\xb9\xe7\x43\x39\x74\xe1\x2d\x56\xc7\x60\x99\xdc\x50\x00\x96\xe9\x1e\xba\x7a\x7d\xce\x85\xdb\x41\x95\x45\x84\xe3\x40\xe5\x2d\xc4\x61\xde\x95\x1d\x3b\xb1\x53\xb8\xc6\xc1\x36\x1e\xea\xde\xd5\x04\x3b\xac\x53\xa7\x29\x57\xf0\x11\xad\xe0\xaa\x36\x15\x4c\x64\xb0\x4c\x90\x6c\xbe\x7b\x99\x56\xd1\x32\x41\xd1\xf6\x32\xad\xfc\x32\x45\x4e\x12\xbf\x7d\xf4\x5b\xd2\x29\x6e\xa3\xbc\xfc\x38\x3a\x57\x47\xf7\xd9\xb0\x04\x35\xcf\xe9\x8e\xba\xb2\xb3\xa1\x67\xe2\x58\xa0\xdd\x88\x5e\x76\xde\x3e\x7c\x8b\x6d\x78\xdd\x83\x0a\x6f\x6e\x54\xf2\xd0\x43\xf4\xf1\x07\xff\xb4\x63\x3a\x21\x81\xe7\x19\x44\x77\x6d\x7a\xd5\x59\x0f\x63\x83\xb2\xc8\x63\x99\xfe\xc0\x91\xc6\xca\x8e\x7a\xd6\xe9\x7a\x1a\x0d\xf8\x58\xdc\xdc\x0b\x53\xcd\x4c\x4f\x9d\x72\x19\x4b\x6b\x2a\xf0\x5e\x1f\xd3\x51\x16\x04\x58\xb2\x4e\xdf\x1c\x59\xee\xc9\xcd\xed\x34\xbb\x7a\x65\x65\x8c\x6e\x8a\xc3\x5d\xb1\x7b\x80\xe9\x86\xfd\x7b\xd8\x94\x3f\x94\x6b\x53\x3d\xd7\xb5\x11\x6e\x28\xdf\xe9\x2c\x07\x1e\x79\x69\xaa\x3a\xab\x9b\x20\xaf\x23\xba\xee\x62\x92\x5c\x48\xe9\xe7\x7c\x7e\x21\x1f\xb7\x4e\xb3\x92\x82\x5d\x1c\x25\xf1\xcd\x53\x32\xe2\x15\xe2\x4c\x86\xd9\x34\x39\xe9\x87\xf7\xde\x62\xca\x6e\xbb\xec\x45\x12\x5b\x20\xce\x4b\xe8\x7a\xec\x24\x52\x43\xd2\xad\x49\x15\xf2\x91\x9c\x81\x81\xdd\x21\xdd\x6b\xf2\x45\x9e\x1b\xa4\xde\xa0\x8b\x83\x2f\x6a\x7f\x77\x6e\x1e\xc6\xcd\x4d\xf4\x9c\x13\x15\x26\x41\xf7\x83\xb4\x88\x81\xd7\x16\x27\x22\x74\xe7\xa5\x9d\xcd\x05\xe6\xb9\x9d\xc0\xc0\x9e\xb6\x67\x05\xda\xa8\x6a\xbb\xe6\x66\xf9\x42\x3e\x8a\xc2\xfd\xf3\x81\x6d\xf6\xa5\x4b\xe4\x6b\xfb\xe5\xfe\xc2\xb3\x42\x79\x22\x81\x49\x68\xe5\x50\xa4\x44\xc3\xc5\x8f\x7a\x26\x3c\x44\x3f\x31\x87\x6a\x87\x1c\x85\x3b\x98\x7c\x88\xaf\x00\xb2\x12\x62\xf5\xeb\x7a\x25\xb0\x72\xb7\x37\xa4\x7a\xdc\xd9\xe9\x04\xd2\x3d\xe8\x06\xd2\x3d\x38\x10\xd0\xe4\x1e\x82\xea\xaf\xaf\x7f\x78\x51\x4e\x3a\x20\xa8\x50\x7c\x34\xf5\x64\x6e\xd6\xea\x24\xfb\xf5\xd7\xdc\x28\xc0\xc4\x82\x54\xf5\xa6\x9a\x96\xd5\x02\xc0\x08\x2a\xa3\xeb\xb2\xa8\xc7\xec\x25\xf5\x4b\x6d\xdf\x0e\x27\xe5\x62\x34\x33\x8d\xce\xf3\xbd\xcb\x7a\xaf\x86\x0a\x46\x8f\xe8\xb6\xf2\xd3\xae\x8e\x3c\x51\xcc\x85\xdd\x43\xac\x93\x28\x12\x4c\x66\xfb\x7e\x12\x1f\xdd\x7a\x39\x05\xa4\x22\x62\x73\x64\xe7\x82\x7b\x29\x86\xc4\xb0\x57\x91\xf3\xb8\xab\x3d\x56\x93\x0b\x26\xa5\xd3\x06\xc3\x0a\xac\x35\xad\xed\xc9\xfc\xcc\x86\xdd\x1b\xcf\x86\xfc\xeb\xe6\xa6\x3d\x39\x5b\xed\x39\x0e\xfe\x14\xdf\xf8\x39\xdf\x70\xe5\x7f\xea\x94\x6e\x75\xb0\x7d\x9f\x3a\xb3\x7c\xe3\x07\xd6\x9c\xb8\x3e\x92\x14\xf3\xd8\x36\xe6\x57\xe4\xc7\xca\xd4\xa6\xba\x34\x4e\x2c\x42\x46\xdc\x12\xbe\x79\x66\x45\x8f\x6b\xa6\x45\x9b\x36\xdf\x40\x25\xf8\x2d\x07\x11\x38\x3e\x33\x9a\x03\xf5\x8d\x80\x70\x8e\x98\xfb\x80\xa8\xa8\x6d\xa2\x16\x3b\x3b\xc1\x3a\xc9\x96\x42\x88\x13\x10\xfe\x1c\x05\xa7\xfb\xa5\x36\x8d\x50\x36\xc2\x43\xa1\xa8\x3c\x5f\x65\x79\xca\xe9\x92\x63\x22\x59\x0f\xfc\xe5\x4b\x92\x0b\xab\x3d\x85\xa7\x17\x2b\x10\x09\xe1\xbc\xd1\xb3\x01\xe8\x03\x06\xce\x4c\x34\x50\x04\x8b\x22\x32\x37\x33\xfb\x70\x6b\xe2\xe6\x2d\xcc\x5d\xe9\x01\x54\xbc\x80\xb3\x41\xc2\xb9\x45\xc4\xd9\x12\x58\xe4\x21\x7c\x86\xd7\x75\x12\xf9\x03\xaa\xb7\x1f\xc5\x71\x3c\x4b\x53\xca\xa5\xc9\x90\x0a\xf7\xbc\xdd\x9f\x88\xa2\xbd\x7a\x1d\x41\xec\x54\xe4\x87\x84\xfc\xbf\x1b\x0c\xe9\xf3\xaf\x24\x67\xa3\xce\xcd\x44\xaf\x6a\xa3\x96\xab\x9a\x73\x06\x7e\x18\x28\x5d\x55\xfa\x3a\xcf\x2e\x4c\x5f\x35\xf3\xaa\x5c\xd7\x21\xdb\x4c\x4c\x11\x74\x75\x10\x51\xf3\x63\xc6\x92\x3f\x53\xe3\x88\x22\x22\x61\x2a\x2e\x4d\xd5\x00\x12\x0c\x28\x43\xb3\xa2\x29\x65\x80\xde\x3d\xe9\x75\x40\x6e\x52\xb6\x20\x71\x1f\xf2\x26\x80\x2e\x41\x27\x18\x24\x36\x58\xf1\x77\xe6\xaa\xc1\xfb\x91\x3f\xea\xea\x88\xef\xc4\x8b\xb7\xaf\x3d\x0e\x7c\xcb\xf1\xc1\x65\x2d\xb1\x2b\xd8\x9d\xe8\x3b\x6c\xde\xe9\x52\xd2\xec\x32\x91\x8d\x23\x9c\x59\x6d\xaa\x0c\x43\x74\xb5\xe5\x70\x8a\x54\x57\xa9\xaa\xcc\xd2\x92\x89\xa2\xf1\x79\x98\xb6\xb6\x80\x95\x55\x3d\xc5\x4a\x67\xa1\x72\xf0\x69\x79\x50\x8f\xa7\xfa\xa0\x54\x68\xb1\x8d\x50\x8f\x3d\x31\x5e\x91\x76\x0a\xcc\x2e\xa0\x48\xb1\x6a\x8d\x95\x83\x87\x7e\xc8\x41\xc2\x67\x5b\x0e\xea\x67\xad\x4a\x85\x7a\xa0\x9e\x72\x8a\xf6\x81\x4a\x9e\xfe\xe1\xe0\x9b\xa7\xa3\x3f\x3c\xfa\x26\x01\xff\x19\xfc\xe8\x91\x44\x92\xc1\xf1\x4f\x10\xe3\xba\x2a\x57\xb3\x39\x94\xb2\xcc\x2c\x5f\x4b\x08\x7d\x4f\x8a\x30\xde\x7c\xae\x0b\xfb\xca\xe1\xdc\x74\xe6\x6a\x11\xab\xe5\x13\x4b\x77\xa2\x44\xfe\x2f\x1e\x13\xdb\x99\x89\xed\xc8\x1b\x38\xe1\xe1\x7e\xf8\xc9\x2c\xcc\xe2\x9c\x32\xb4\x37\xe5\x72\x2f\x37\x97\x26\x67\xf2\x46\x46\x3e\x1e\x96\xdb\x7d\x5e\x41\x18\x54\xf6\x5d\x76\x65\x6a\x75\xff\xe0\xd1\xe3\x27\x5f\x74\x0c\xf5\x67\x73\x7e\x91\x35\x03\xf5\xea\xa5\x58\x67\xbb\x71\x9f\x93\x06\xf2\x48\x25\x49\xa7\xb4\x7b\x2f\xc8\xaa\x41\x6b\x86\xbc\x05\xf7\x09\x08\x24\xf7\xaf\xa3\xd2\x7b\xdd\x20\x79\x44\x38\x61\xaa\x1c\x34\x5e\xc0\xee\xdd\x7f\xb2\xff\xd5\x97\x6a\x4f\xbd\x9a\x12\x0f\x03\xbe\x83\xf6\x3a\xcb\x0a\xbc\x46\x9d\xa2\x51\x93\x4a\xb2\xd6\x0b\x82\x30\xa4\xc4\xb5\x5c\x17\xe4\xe1\xa5\xe2\x80\x4d\x5b\x94\x00\xbc\xaa\x8b\x6b\xc8\xd7\xe2\x49\xb6\xbf\x8a\x04\x7e\x6a\x41\xc0\xe9\x78\x25\xc9\xdb\x6a\xfb\xe8\x48\xed\x1d\x08\x40\xec\xce\x14\x4d\xce\xb7\xe1\x5f\x61\xd2\xe1\x9e\x58\x22\x40\x7c\x19\x4c\x3b\xed\x0e\xbe\xc8\xbb\x69\x14\xd6\x15\xb1\x12\x5c\xef\xa7\xf1\x28\x04\x57\xc5\x83\xf0\x6c\x60\xc8\x69\x00\x86\x69\x0b\x45\xe2\x39\xf8\x4c\x1a\x65\x69\xd8\x0a\xb5\xf2\x62\xb6\x49\x77\xe9\x1d\x1e\x3d\x92\x61\x6b\xaf\x34\x8b\xa5\x03\x2e\xf4\x27\x1f\x11\xec\xbc\x96\x56\x5c\x1b\x28\xb5\x52\xaa\x30\x49\x2c\xa8\x59\xba\x44\x02\x46\xf5\x4e\x78\x55\x9e\x65\xc1\xf0\x80\x61\xec\x05\x28\xf0\x22\x66\x47\xf2\x33\x81\x21\x13\xb4\x4e\x17\xe6\xfa\x53\x00\x46\x05\x9b\x12\x31\x24\xbd\x16\xfb\xd1\x0f\x63\x35\x43\x66\x45\x72\x15\x9b\x10\x8f\xed\xd8\x2f\xcc\xb5\x43\xe9\xf5\x1a\x42\x17\xea\x12\x7a\x27\xda\xc2\x56\xf4\x4b\xe3\x0c\x79\x13\x3d\x99\x9b\x53\x78\xdf\x5e\xb0\x54\x64\x83\x16\x0b\x13\x2a\x00\x37\x14\x0a\xc0\xfc\x04\x96\xb1\x2f\x70\x67\xfa\x35\x41\x8b\x29\xcb\x2f\xe6\xb9\xd6\xaa\x9e\x97\x55\x33\x59\x89\x80\xcf\x8e\xba\x1e\xd4\xaa\xbc\x34\xd5\xdc\xe8\xd4\xd5\x12\x71\x0f\x9f\x90\xf6\x28\xed\x48\x79\x24\x01\xc4\x3a\xe1\xbf\xba\xe7\x57\x8e\x5e\xe4\xba\xd6\xc5\xb5\x80\xed\xfa\x07\xe9\x9a\xff\xc1\xda\xca\xad\x2d\xaf\xab\xed\xae\x77\xf3\xa1\xb8\xa5\x99\x55\x6d\x2a\xd1\x86\x6c\x00\xf4\x93\xd4\x80\xd8\x5f\xf0\xd8\x87\x52\x9d\x75\x58\xf8\xbb\xfc\x47\xb7\x30\x8b\xad\x3f\x73\x10\x9e\x17\xb9\x42\xb0\x62\x15\x7d\x2d\x36\x94\xe5\xc2\x97\x2e\x94\xce\xab\x11\x09\x43\x8e\xb9\x71\x73\x45\x18\xc2\x4e\x11\x89\x6e\x30\xe0\xd6\xd6\xeb\x6f\xf0\xba\x90\xd1\xf2\x6d\xf5\x48\xc7\xe3\x0d\xcf\xbf\x0e\x78\x1e\x08\x6d\x0b\xae\xdc\x4b\xd6\x5d\xc9\x55\x23\x81\x8e\xe3\x71\xa1\x8c\x70\x91\x73\xa0\x6c\x82\xa4\xe1\x15\xd2\x76\x79\x96\xfe\x25\x69\xb9\x00\x93\xab\xc0\x5f\x1e\x44\x04\x30\xf2\xc5\xfc\x0f\x8e\xde\x52\xd4\xc6\x63\xe2\xb6\x4d\xb9\x04\xda\x29\x69\x3b\x05\x76\x74\x5c\x8f\x52\x80\x97\xd3\x40\x99\x59\xfe\xdf\x39\x0f\x59\x51\x9b\xaa\xf9\x16\xa0\x08\x1c\x65\xc2\x57\x9e\xcf\xdc\x3c\x37\x88\x61\xf0\x3f\x31\x35\x5d\xe9\x41\xa2\x17\xdd\x9d\xf7\x8e\x4b\x1d\xfd\x85\x3c\xfd\xff\x77\xeb\xee\xb0\x30\x57\xcd\x49\x86\xb1\xcc\x1b\xbb\xde\x4e\x98\xeb\x3d\xed\x2e\x48\x4d\xa7\x46\x0f\xd5\xab\xa2\x31\x55\xa1\x73\xf0\x71\x85\xd4\x28\x0f\x47\x2d\x95\x8a\xd3\x5b\xd4\xd2\xb7\xfa\x58\x39\xbc\x4b\x44\xa8\x11\xbe\x7c\x44\xec\x44\x34\xc3\xdd\xcc\x48\x06\xac\x08\xa2\xf5\xb7\x99\x90\x6d\xd7\xeb\x9d\x9d\x4e\x9d\x71\x1c\x01\xe3\x58\xac\x5e\xa4\x5f\x8c\x39\x4e\x1f\xa1\xdf\xb5\x2c\xc4\xb1\xf8\xb6\x7f\x07\x3b\x2e\x28\x6f\xc4\xf8\xde\xa1\x49\x73\x84\x38\xea\x16\x71\x06\x1b\x09\x51\xc0\x76\xb2\xbb\x24\xed\x08\xb8\x6d\x36\x04\x69\xba\x45\xbe\x6d\x95\xc0\x2f\xef\xf6\x45\xda\xb8\x2e\x4e\xa5\xc2\xf8\x43\x0b\xb3\x28\xab\x6b\x95\x1b\x4d\x00\x2a\x77\x2c\x9b\xc3\x3e\x08\x35\x34\x24\x66\x86\xec\x84\x50\xd0\x20\x4f\xdf\x29\xb7\xde\x3d\x63\x2d\x93\xcd\xa7\x1a\x6b\x42\x15\xf9\x51\xa4\x32\x77\xb9\xb7\x68\x48\xe3\xf0\x3d\xf4\xae\x5d\xf5\x51\x47\x73\xbe\xa6\xb0\x85\x71\xbb\xec\x61\x6b\xa0\xc3\x85\x5e\xb6\xb9\x8e\xd0\x75\x09\x66\x80\x2f\x84\xbb\x47\xdf\xf6\x40\x9d\x37\x8b\xfc\x3f\xc3\x6e\xc5\x0e\xa2\x6a\x9f\xe1\xcd\x19\x9f\xc4\x2b\x65\x41\x2b\x0b\x63\x0c\x94\xb2\xb8\x47\xbb\x18\xb6\xbb\x48\x8a\xf0\xa5\xf1\xda\xae\x96\xdc\x7a\x62\x0c\x65\x93\x9a\xe8\x42\x35\x98\x17\xc3\x49\x07\xba\x48\x31\x31\x20\x20\x17\x72\x25\xe2\x62\x40\xa7\x65\xdf\x3d\x17\x73\xb2\xb3\xa3\xb6\xa5\x73\x28\xc9\xab\x3c\x3f\xce\x24\xe6\xb4\x76\x2d\x3d\x20\x17\xbd\x5b\x11\xc8\x82\x01\xb3\x0a\x68\xea\x44\x10\x8b\x3b\x55\x79\xee\x64\x36\xd5\xb5\xa3\x7c\xb7\xa8\xc2\xbd\x36\x1c\x97\x34\x8b\x92\x61\x84\x87\x9c\x94\x31\xa4\xfd\xa6\x2c\x78\x1b\x88\xc9\x5d\xf4\x28\x94\xb7\x3e\x89\xe6\x6c\xf9\x0e\x07\x1a\xcf\x80\x7f\x96\x12\x18\xfd\xa2\x11\xee\x4b\xb2\xf5\x6a\x4a\x01\x23\xbe\x22\x54\x0e\x42\xb4\xcb\x95\x95\xb3\x01\x20\x68\xc5\xa9\x40\x74\x9e\x03\x34\x91\x4c\x8d\xf3\x51\x4d\x30\x03\x3b\x1c\x92\x8f\xdd\x77\x5a\xc4\x5f\xb0\xc8\x81\x0c\xad\xdb\x18\x01\xde\xd4\xef\xe0\xf9\x69\x47\xfc\x9c\x35\xf3\xee\x9b\x45\x57\x33\x75\xe4\xeb\x60\xb5\xec\x3d\x91\x3a\x06\xfd\x12\x74\x31\x33\xe0\x50\x66\x2b\x04\x74\x0e\x3d\x99\x3b\x87\x0a\x5e\x7a\x97\x2c\xa9\x30\x6b\xa9\xf9\xfd\xdd\xac\x18\xf6\x2b\x62\xb9\x5c\x6e\x8c\x8d\xbb\x82\xf8\x9a\x7e\x40\x50\x6c\x5d\x6e\x96\x75\x35\xe3\x73\x22\x6e\xe9\x4d\x8c\x26\xcd\xc3\x77\x65\x35\x31\x2e\x5f\x33\x06\x8a\x57\x46\xad\x35\xa4\x20\x16\x63\xe5\xb4\x74\xa0\x4e\xc5\xa8\x28\x37\xd6\xbe\x24\xa9\x15\x38\xb1\xf4\x6c\x6f\x68\xd9\x6e\x6e\xec\x53\x77\x18\x18\xed\x92\x71\x29\x49\xe3\x21\x17\x17\x53\xdd\x75\xb1\x90\x5d\xa1\x03\xac\x32\xe9\xca\x47\xcf\x15\xd2\x02\xc9\x2a\x75\x35\xab\x07\x10\x4f\x05\xfb\x5b\x86\x52\x7f\x97\xeb\xa6\x31\x05\x5c\xee\x85\xa9\x1b\x93\xa2\x32\x1d\x8e\x38\xa5\xf4\x41\xb4\x4d\x0e\xe4\x3a\x3d\x8b\xd2\x55\xd8\x2d\xc8\xda\xb7\x01\xe6\x6b\x11\x36\xc4\xb9\xae\x4f\xf8\xb7\x9d\x17\xc4\x49\xf6\x7c\x90\xb7\xf0\x89\xbb\x84\xd4\x6f\x11\x14\x41\xf6\x06\x3d\x1b\xd4\x91\xca\xd5\x9e\x3a\x18\xd0\x9d\x85\xe4\x13\x32\xf1\xd8\xad\x4f\x85\x5d\x72\x2d\xaf\xbe\x93\x09\xb7\xfc\xa1\xa4\x99\xf8\x19\x6e\x94\x07\x8d\x72\xfe\x1c\x6e\x54\x35\x2a\xaa\x89\x1b\x65\x07\x9f\x81\xca\x0a\xe5\x8d\x15\xb0\x4d\x45\xab\x0c\x2d\xd4\x53\x39\x64\xeb\xa3\xb8\xa9\x4d\xb7\x0f\x11\x32\xe7\xc5\x01\x8d\xe0\x70\x9d\x03\x90\x49\xa3\x5b\x29\x4e\x2b\xdc\x15\x60\xa2\x00\x4d\x3f\x94\x4c\x6b\x93\x4f\x41\xca\x68\x86\xe6\x9f\xae\xc4\xa1\x60\xc6\xc5\x40\x3c\x2d\x77\x53\xec\x6e\x2b\x99\x88\x03\x6a\x01\x35\xfc\x14\xd0\x6b\x7a\x2d\x46\x1b\x5e\x05\x14\x24\xd8\x96\x74\x70\xfb\xad\x48\x47\x1f\x3b\x2a\xac\xca\xb4\xa6\x81\x55\x9b\xeb\x74\xcc\x4b\x2c\x32\xc0\x5d\x13\x12\x0a\xd8\xb0\xb7\x1b\x73\x30\xf4\x88\xdf\x7b\xdb\x11\x1f\xfb\xe8\xce\x13\x9d\xc4\xec\x45\xed\x5b\x03\x1b\xf5\x1a\x7b\xd2\xb7\xbb\x51\x59\xb6\xb1\x65\x40\x90\x32\xcc\x20\xf4\xd0\x76\x33\xed\x8f\x9b\x5d\x5f\xd2\xa7\x87\x0c\x9a\x4c\x7f\xe5\xbc\x50\x5c\x9f\x39\x51\x4b\xae\xeb\x46\x65\x8d\x59\x00\x24\x99\xd1\x29\x63\x1c\x63\xd7\xd9\x0e\x97\x35\xc0\x87\x99\x22\x55\xab\xa5\xab\x1e\xf3\xf7\x5a\xda\x99\x99\x14\xc0\xa0\x2a\x34\xa3\x43\x9e\x5f\x53\xc1\x31\xaa\xb3\x06\x6d\x1a\xb5\xea\xdd\xff\x6a\xff\xcb\x7d\x4e\x11\x74\x2b\x33\x03\xd8\xb1\x47\x52\xdd\x7f\x4f\x28\xf2\x32\xd0\xb3\x3b\x42\x21\xd8\x10\xfa\x2e\xe4\xb9\x91\x20\x01\xce\x9e\xa7\xa4\x82\x29\xfa\x93\x31\x4b\x55\x19\x40\x22\x9c\x98\x9a\x22\x64\xc0\xd5\x82\x26\xd9\xf6\x35\xd7\x8d\xa9\xc8\x6f\x5d\xda\x8b\x39\xe5\xa4\x5b\x11\xc9\x15\xdd\x62\xf3\xfc\x77\xad\x9e\xb1\xdd\xd3\xd1\x62\xde\x50\x38\xec\x0e\x81\xb8\x8b\xb5\xe2\xf3\x29\xce\x3a\x79\xea\x60\x35\x99\x3c\xe5\x82\x82\x74\x8e\x1b\x41\x19\xa8\x43\xa7\xd1\x06\xb5\x34\x3d\x3e\xb2\x91\x71\xd6\x14\x80\xb9\x4d\xdf\xd1\x1b\x79\x66\xdc\x58\x83\x30\x82\xc8\xc8\xfb\x92\x7c\xef\x85\xf1\xcb\x2d\x28\xb8\x88\xda\x1d\xee\xb0\x43\x50\x47\xe4\x97\xb5\x95\xd1\xc5\x8f\xb4\xc5\x79\xd3\xae\x73\x03\xce\xbc\xee\x7e\x93\x85\xcc\x7e\x12\x5a\xc8\xdc\xe5\xb0\xb5\xb5\xdd\x76\x20\xa7\xc5\x0c\xdc\xee\x3b\x55\x28\x80\x0f\x51\xa0\xde\x45\x88\x1f\xdc\x13\x68\x17\x1d\xa2\x85\xb1\x64\x34\x52\x6f\x81\x4f\xd6\xb9\x7a\xf6\x7f\x9e\xfd\x55\xa5\xa0\x79\x45\xdc\xd6\xf3\x55\xa3\xd6\x98\x7e\x72\x55\xb8\x19\xcc\xa6\x98\xd1\x17\x1d\x28\x7c\x55\xd2\xcc\xf5\xc1\x5c\xea\xfc\xcf\x55\x1e\x36\xb6\x15\xbd\x95\x9d\xf2\xc2\x81\xb7\xc4\x6c\x36\xee\xcc\x84\x1a\x08\x27\xd4\xab\x27\x84\x88\x25\x42\xe7\x06\x64\x8d\xbc\xdb\xe0\xb3\xd1\x04\xe9\x34\x1b\xb1\x75\xc4\x01\x4d\xa1\x44\xf0\xae\x1c\xab\x04\x7f\x22\x54\x14\x6a\xb3\xe1\x31\xfd\x86\xe7\x52\x39\x39\x56\x09\x2a\x76\xc5\x9b\x67\xa8\x39\x4d\x40\x83\x0a\xcf\x69\x64\xcf\xf2\x7c\xac\x12\x21\x37\xc4\x98\x53\x05\x18\xe4\xa3\x7c\x16\xce\x94\x73\x8a\xc9\x51\xcf\x42\xa0\xcb\x88\x2d\x65\x55\x01\xf1\x66\xe8\x93\xee\x7c\xb7\xa0\x7f\x8e\xdc\xca\xaf\x89\xdf\xd3\x70\xe7\x62\x39\x71\xfc\x37\x2b\xc8\x32\xf5\xf4\x08\x2e\xa5\xb6\xa3\x57\x0d\x19\x91\x21\xff\x81\xad\x36\xe4\xb9\x59\xbb\x22\x00\x57\xb8\x53\xd8\x3a\xf9\x18\x9e\xfa\xe9\x38\x73\x56\x62\x61\x92\xef\x26\xd6\xa3\x91\x82\x40\x98\xfe\xef\x22\xd1\xa2\x0c\xa6\xda\x44\xe7\x36\xac\xa8\x2b\x61\x0e\xca\x50\xab\x7a\x7e\xd2\xe8\xc9\x05\x66\x86\x43\xa6\xff\x30\x8c\xb5\x55\xd9\xb4\xb2\x6b\x4b\x71\x5a\x69\x56\x2f\x73\x7d\xed\x83\x39\x46\x0f\x1f\xde\xfb\x4c\x3d\x54\x3f\x99\xa6\xca\xcc\x25\x32\x01\x7a\xd2\xac\x74\xae\xb8\x30\x78\xac\x93\x30\x08\x85\xff\x7f\x10\x84\xab\x7e\x3b\x01\x66\xf5\x23\xe5\xcf\x65\x5f\x6e\x4e\x7d\xd0\xf1\x01\xa2\xa7\x7c\x04\x28\x1e\x07\xbf\xc3\xa0\x93\xea\xe1\x08\x11\xa9\x74\x9e\x03\xfe\x62\x7e\x8d\x22\x97\x95\x3f\xb3\x82\xdd\xcf\x5f\x60\xaf\x84\x07\x3f\x76\x97\x9e\xf3\x5e\xb6\x4d\x78\x37\x7e\x08\xe5\x85\xbd\x44\x8a\x01\x5e\x72\x48\xbe\x11\x78\x85\xe1\x68\xfa\x8a\xc5\xf5\x77\x25\x96\x82\xf8\x49\x4a\xe4\x63\x97\x79\x66\x18\x01\xe1\x79\xb9\x58\xae\x1a\x93\x9e\xd8\x46\xd4\x02\x1c\xa4\xce\xad\x64\x99\x67\xfa\x3c\x87\xc0\x13\x1a\x8e\xed\x6c\x43\xa9\xcc\xdd\xfc\x6c\x6d\xf9\x55\x21\xcc\xf7\x4d\x75\x83\xeb\x36\x8c\xe5\xce\xb2\x9c\x41\x78\x1f\x74\x4b\x2e\x3e\x91\x79\x3d\x58\xa4\xac\xe6\xec\xc8\x60\x52\x6f\xcc\x62\x59\x56\xba\xba\x06\xa0\xa1\xde\xa2\xac\x8c\xb2\x5b\x55\x95\xcb\x66\x91\xfd\x0a\x9c\x4c\x5f\xad\x8a\x26\xcb\x01\x39\x0b\x3c\x72\xd4\xb9\x69\x1a\xc0\xef\x5e\x98\x5a\xe9\xbc\x2c\x66\x03\x6e\x08\x61\x43\xb2\x06\x64\x6a\x14\x55\x53\x5c\x52\x82\xd2\x9c\xa0\x0b\x8b\x2e\x52\x0e\x2a\xe6\x99\xca\x0a\xf5\xdd\x77\x28\xf4\xd9\xd1\x0c\x79\x8a\xc6\xee\x1a\xab\x6b\x31\xc4\x81\x4a\xa8\x84\x53\x88\xa1\x04\x87\x48\xe2\x98\x12\xa1\xb8\xc6\xe0\x77\xe0\x03\x5c\x46\x68\xf6\x36\xc2\x4f\xea\x12\xd4\x3f\x09\x8a\xe1\x09\xcf\x8f\xae\xd5\xd4\x92\x92\xb5\xbe\xb6\x3c\xdf\xcc\x34\xaa\xca\xd2\xd6\x56\x47\x3d\x15\x7e\xcb\x51\x21\x74\x62\xa9\x7b\x2e\x26\x85\xce\xdd\xbb\x0a\x2a\x4c\x5d\x12\x55\x19\x68\xc1\x83\x46\xe9\xce\x1e\xc3\xe2\xf6\x73\x48\x47\x90\xce\x92\x8f\xdd\x0c\x4e\x8e\x08\xc7\xf0\x07\x04\xf9\x30\x66\x71\x06\xe1\xae\x14\x94\xe3\xd4\x7f\x7c\x26\x62\xea\xb6\xb9\x30\xeb\xe2\xdd\xb7\xf1\xe1\xa4\xaf\xe9\x80\x06\xf9\xca\xc1\x33\x2c\x5b\x2c\x73\x03\xf3\x3c\xd5\x59\x0e\x7c\x9b\xa6\x4d\x93\x15\x00\xfd\xa7\x0b\x22\x6a\x4e\x1c\x74\xad\x59\x09\xba\x28\x0b\x03\xc1\x25\x61\x9f\xe4\xe6\x07\x1a\x87\xb1\x97\x7b\x78\xf8\x53\xaa\x52\xa6\x4a\x20\xe1\xac\xc2\xe8\x9f\x1e\xfd\x72\x00\xb4\x3d\x95\x3c\xa5\x67\xf0\xdf\xf3\xb2\x4a\x4d\x75\xf4\x60\xff\x81\x5a\x67\x69\x33\x87\x5f\x73\x63\xa9\x81\xfd\x39\xfa\x26\x51\xfd\x98\xa6\x44\x09\x93\x42\x57\xb2\x7c\xad\xaf\x6b\x48\x2b\x63\x94\x06\x7d\x14\xa8\x2c\xeb\x0b\x93\x9b\xa6\x2c\xec\x56\x45\x87\x41\x38\x3f\x1e\x4c\x1e\x54\x16\xf3\xf2\x02\x30\xca\x2b\xb3\xaa\x71\x24\xb8\xc2\xd8\x63\x14\x85\x49\xbd\x15\x73\xd6\x61\xb0\x09\x7f\x3b\x84\x8e\xb0\xcf\x2a\xe6\x2c\x2a\x7d\xec\xd3\xef\x5a\x72\x37\xaf\xf2\xa8\x04\x39\x45\x5c\xf0\x32\x03\x3a\x47\x47\x82\x29\x79\xc7\xae\xb4\xdb\xd8\x9d\xb5\x30\x2a\x37\x38\x83\x10\x38\xb7\xd0\xd5\x2c\x2b\xec\xf2\x8e\xfe\x8e\xbf\x47\x38\x20\x78\x5b\xac\x16\x45\x59\x2c\xaf\x28\x5b\xcc\x4f\x66\xf6\xf2\x6a\xd9\x53\xc9\xdf\x7b\x89\xda\x55\xcb\x62\xb5\x50\xbb\x2a\xe9\xf7\x8e\xb7\x97\x57\xfd\x53\xbd\xf7\xeb\x7f\x9d\xed\xfe\x21\x19\xa8\x24\x63\x2a\x64\xab\x99\x99\x06\x28\x72\xdd\x82\x2e\x8f\x34\x7a\x1d\xc1\xdf\x1c\xe9\x94\x19\x20\xf4\x1d\x14\x7e\x40\x58\x5a\x87\x0e\x29\x20\x8c\xaa\x5d\x55\xcf\x4f\x4e\x5c\x51\x58\x86\x09\xd5\x22\x8e\x3f\xec\xd8\x81\x5a\x64\xc5\xcf\xf4\x4b\x5f\xd1\x2f\x06\x03\xe5\x6b\x07\x7a\x09\x7f\xe0\xca\xbb\xda\x8e\x7c\xc5\x18\x29\x82\xa3\x0e\xa3\x6f\xc2\xcd\xf5\x35\x3e\x99\x99\xe6\x47\xc4\xa4\xbe\xc6\x30\xaf\xac\xc6\x5b\xa0\x30\x26\xb5\x57\x46\x59\x29\x20\xf8\x0f\xd0\xe8\xfd\xa0\x6f\xef\x87\x57\x2f\xbf\x1e\xa8\xda\x18\x75\xff\xe0\xd1\xe7\x8f\xbf\x64\x52\x14\x8d\x6e\x8b\x83\x23\xf1\xe9\x30\x6e\xcb\xdd\xf7\x37\x37\xae\x10\xf3\xbb\x7e\x03\x75\xd4\xec\xa8\x0f\x34\x60\x29\x4f\xd2\x8d\x0b\xfa\x09\x96\x6a\xec\x23\x7d\x59\x07\x8b\x0b\x9d\x8b\x8f\x07\xcf\x60\xf6\xf6\x44\x3d\x55\x5f\xd0\xe3\x67\x8a\x63\xfc\xc9\x57\x3b\xd1\x6b\x03\x69\xa6\xe6\x7a\x72\xa1\xce\xaf\xd5\x0b\xa3\x0b\xf5\x32\x5d\xeb\x2a\xad\x13\xfa\x8a\xea\x50\x3d\xdd\xa8\xdc\xe8\xba\xe9\x53\x28\x60\xad\x96\xa6\x9a\x98\xa2\xd1\x33\x8c\xde\xd2\x2a\xd7\xd5\xcc\x54\x0a\xd2\x3f\x93\xda\xb2\x26\xa9\xcf\x6e\x16\xbb\x1a\x0b\x50\x8a\x48\xf6\x67\x99\x5d\x99\x9c\x13\xd4\x36\xec\xc0\x37\xb3\x93\x83\xf1\x91\xcf\x4f\x4e\xde\xbe\x56\x69\xa5\xa7\x0d\x30\x06\x2e\x24\x2c\x35\x97\x0c\x9c\x3d\xa9\xeb\x35\xfc\xb7\x5c\x8c\xee\x57\xa6\x2e\xf3\x4b\x93\xee\x61\x0f\xfc\x4a\xf0\x81\x25\xc9\x19\xc3\x41\x77\x76\xf8\x9c\xb3\x40\x4d\x0c\x9e\xbc\x16\x02\x37\x6f\xc7\xf8\xfb\xfa\xb7\x70\x80\x47\xc8\x7d\x0d\xe1\x2f\xa4\x64\x7c\x66\xdc\x3b\x7e\x40\xaf\xe9\x20\xf9\xd7\xf4\x40\x7a\xf7\xae\x1a\x4e\x9e\x6d\xe9\x0c\xb6\xca\x7c\x86\xf6\xfb\x8e\xf8\x00\x44\x26\xdd\x0a\x5b\x6b\xd5\x1f\xf6\x15\x01\x91\x0e\xc5\x6e\x73\x27\x62\x1d\xf5\xe6\x27\x03\xe1\x17\xde\x42\x94\xca\x79\x08\xeb\x14\xf3\xd0\xea\x4e\x38\x0f\xad\xce\x89\x79\x90\x01\xdb\x1e\xb0\x36\xca\x66\x72\x1c\x6f\x7e\xbc\x9b\x2c\xeb\xf0\xd2\xed\xd8\x5f\x5f\x81\xe6\x1a\x27\x4a\x83\x61\x2f\x2b\x1a\x33\x33\x98\xa3\xc3\xd6\xba\x6b\x0f\x6a\x1c\x22\x2c\xa5\x89\x34\xfd\xa3\x69\xbe\x2f\xcb\x8b\x57\x53\x70\xa6\x4e\x33\xfb\xfc\xbb\x62\x00\x89\xab\xbf\x63\xfd\x37\xc4\x4a\x4c\x99\x65\xb3\xaf\x06\x6a\x6d\x1e\xe4\x39\x9a\x03\x98\xbd\x44\xdd\x51\xb5\x2a\x00\x05\xbf\x79\x60\x19\x61\x9d\x3b\xda\x36\xf4\x43\x06\x52\x30\x33\x1d\xf8\xe9\xce\xaf\x9b\xbb\x22\x32\x69\xd8\x7e\x40\x5e\x36\xc8\xd9\x87\xf4\xb2\x57\x56\xd8\x14\xa8\x5d\x38\xf3\x53\x53\x52\xfa\x3e\x95\xae\xe0\x2f\xce\x2b\xe9\x35\x38\x24\x8c\xdb\x3a\x09\x61\x2f\xe3\x64\x33\x76\xe6\x81\x9d\x47\x2b\x99\xae\x20\x9b\x7b\x09\x99\xe4\xe7\x90\xb8\xcd\x92\x08\x3c\x67\x3f\x59\xa6\x67\xc0\x55\xd8\x59\x58\x43\x4a\x6a\x94\xf4\xa8\x42\x72\x37\x05\x49\x76\xc6\x5b\x53\x20\x30\x04\x46\x7e\x1c\x21\x8c\xee\x50\x55\x06\xf7\x84\x1d\x4a\x5d\xa2\x29\x06\x78\x47\xc2\x25\xb2\xa7\x9c\xb3\xe5\xa0\x42\xcf\xa4\x48\x70\x86\x54\x23\xcd\x78\x8f\x1b\x57\x47\xb4\xb6\xfd\xdb\xd1\x09\x1d\x7c\x32\xee\x99\xd8\x91\xc3\xde\xa4\x40\xed\x7e\x2c\x6b\x58\xa9\xbf\xe8\x7c\xa0\xce\xcb\xab\x93\xec\xd7\xac\x98\xfd\x84\x14\xd1\xfc\x85\x5c\xc5\xd3\x12\x42\x1d\x05\xdf\x1d\x33\x84\x84\x63\x44\xa1\x26\xb2\x60\x24\xb3\x42\x28\x13\xe9\x52\xd2\xec\xf2\xee\x92\x21\xef\x7e\x89\x97\xce\x26\x18\x0c\x57\x60\x78\xae\x27\x17\xb3\xaa\x5c\x15\xe9\xf3\x3c\x5b\xaa\x23\x95\x10\x13\xb9\x77\x5e\x5e\x81\x8b\x8f\x2d\xdb\x0a\x80\xde\xf8\x35\x7c\xe2\x2c\x5c\xb9\xd1\x15\xe8\xe9\x4f\x88\xd7\xd8\xdc\xf0\x51\xbb\x69\xe0\x45\x68\xaa\xe8\xab\x49\x5d\xbf\x33\x57\xe0\x7f\x84\xec\xf9\x78\xff\x10\x48\xd6\x78\xff\x10\x59\xf3\xf1\xfe\x61\x53\x2e\xc7\xfb\x87\xb9\x99\x36\xe3\xbd\xaf\xbf\xfe\xfa\xeb\xe5\xd5\x21\x6e\xe3\x3d\xfb\xe6\x60\x79\x75\x98\x28\x48\xda\x94\x2c\x69\x59\xc7\xfa\xbc\x2e\xf3\x55\x63\xa0\xfb\xbe\xd1\xc0\x61\xd5\x2e\x83\x67\x7a\x5e\xc2\x3e\x04\x79\xb9\x6c\xe6\xe1\x2e\x51\x3b\xed\x3d\x02\x9b\xd8\xc1\x22\xb1\xf6\xc0\xa8\x5c\x5f\x23\xfd\x47\x59\xb5\x99\x9b\xeb\x07\x2e\x68\xc3\x6e\xf3\xc6\xa7\x28\x02\xe8\xfb\xa6\x54\xb5\xa6\x53\x58\x1b\x4b\x43\x88\xf2\x83\xe8\x6d\xcf\xa2\xe7\x15\xf1\x46\xf8\x51\xf6\xed\x59\x91\x7e\x1b\xf7\xad\xe7\x84\xbc\xcb\x78\x9e\x5b\x02\x04\x89\x25\x4f\x1f\x7d\x3d\x70\xc9\x51\x1e\x0d\x1f\x73\xb9\xbf\x98\x22\x2d\xab\xbd\x65\x65\xa6\xd9\x95\x9d\x85\xbd\x1a\x9a\x82\xf7\xc9\xde\x1a\xe4\x9b\x3d\xff\x7c\x8c\xcb\x68\x9f\x1c\xee\x2d\xca\x5f\x37\xbc\xa2\x05\xdb\x4a\xba\x5f\x93\x1c\x30\x3e\xcf\xcb\xc9\x45\xb0\xd8\xff\x75\x48\xff\x88\x1a\x60\xdf\xd8\x6d\xb0\xd4\x69\x6a\x6b\xb2\xbf\x71\x17\x3d\xb1\x4f\x3b\x37\x05\x4c\x8e\x74\x58\x21\x07\x38\x3a\xf3\xed\xf0\x44\x3c\xe1\xd2\x84\x9e\x66\x97\x27\x2d\x55\x4f\x24\x01\xa4\xd9\xa5\x14\x00\xb6\x62\xea\x83\x67\x08\x0a\x0f\x9b\x72\x89\xf8\xc6\x07\xff\x85\x7d\xe9\x22\x4c\xf2\x03\xba\xe4\xed\x27\x4f\x96\x7c\xc4\xdc\x08\x02\xa7\xc8\x70\x04\x1e\x7b\xc5\xed\x03\xd0\xb9\xff\x52\xab\x5f\xea\xb4\x5c\xd0\xed\x09\x92\xaa\xae\xeb\x95\xdd\xa6\x96\x88\xc7\xe3\x43\xb5\x14\xa5\xab\x71\x39\x55\x51\x95\x1f\xe5\xaa\xd9\x30\x43\x4c\xd1\x22\x60\x16\xa2\x38\x03\xba\x43\x83\x59\xeb\x82\x0f\xe7\xc8\x13\xbe\x59\xdc\x71\xa3\x73\x39\x31\xc8\x04\x1b\x55\x37\x59\x9e\xab\xb4\x04\xef\x28\xbf\x95\xbd\x36\x8c\xfc\xd4\xd8\xc7\xa8\x7d\xf0\x97\x95\xd9\xc3\x93\x98\x15\x33\x7f\xf9\xbe\x29\xe1\xfe\x03\x8b\x23\xf0\x17\x94\xd9\x00\xba\xb4\xb6\xac\x0e\x81\x49\x11\xc6\x82\x49\x07\xaa\x99\x97\xab\xd9\x9c\xea\xf8\xf4\xd3\x1d\xa2\xf6\xc6\x5b\x8a\xee\x66\xe4\x14\x5a\xdd\xdf\x98\x7f\xb0\x7b\xb3\xc5\x89\xa8\x7f\x7f\x2f\x3f\x06\x9d\xed\x6a\x25\xe8\x30\x49\x25\xe6\xb5\x67\x54\x36\x2c\x78\x2b\xa7\x13\x93\x2d\x08\x96\xe3\x25\xb0\x54\x1e\xfc\xa3\x38\xd1\x12\x49\x42\x98\xeb\x97\xf8\xa1\x3d\x0c\x9a\x15\x66\x6f\x57\xd1\xcc\x34\xb5\x67\xf0\x83\xe2\x2e\x0d\x11\xd6\x58\x4e\xfd\x29\x1b\xaa\xde\xfd\xc7\x8f\x1f\x3f\xee\xbb\x7a\xd0\x04\xa1\xbe\x5d\xcd\xd4\xc1\xe3\xc7\x4f\x1e\xab\xbd\xf6\x69\x62\x26\x79\x5d\x95\xc5\x8c\x78\x64\xcf\xb4\xed\xf9\x5c\x92\x6e\xbf\x33\x47\xe5\xae\x08\x16\xcc\xc5\x01\x98\x40\x4e\xd1\x42\xec\x78\xe0\xbd\x1c\x77\xdb\xca\x29\xb2\x85\xed\xbd\x40\x36\x25\xbb\x8c\xae\xcd\xdb\xf9\x96\xd8\x11\xd9\x8a\xa2\xcf\x4f\x4e\xc6\xe2\xee\x38\x74\x7a\x1e\x1a\xd9\xa1\x42\x22\x7e\xa8\x88\x82\xe3\xf7\xae\x1b\x2d\x66\x61\xd3\xc5\xf6\xe9\x57\xdb\xdd\x97\x5b\xf7\xf5\x26\x58\x9a\xd6\xfd\x26\xdf\xf1\xf5\x14\x5e\x71\xb2\x44\xd7\x1d\x37\xde\x3f\x74\x6c\x10\x5f\x66\xfb\x1c\x50\x1c\x4f\x87\x60\xe5\x41\x5a\x0b\xdf\xb2\x00\x98\xb8\xef\xd3\xf6\xbb\x03\xbc\x35\xc8\xce\xff\x29\xf7\x1e\x0b\xa7\xdb\x4b\x5d\xd5\xe6\xbb\xbc\xd4\xcd\x46\xda\xde\xf3\x9d\xe2\x3b\x30\xe8\xb4\xaf\xf3\x13\xae\xac\x80\x8a\x38\x49\x59\x46\x78\xdc\xfb\xec\x63\xbf\xc7\x96\x35\xd0\xb6\x90\x6d\xc0\x1e\xa1\x7f\xae\xb2\xc9\x45\x7e\xad\xea\xb5\x5e\x2e\xd1\xc5\x14\xf2\x10\x3d\x3f\x39\x91\xe9\xd6\x48\xa4\x67\xa5\xe6\x84\xb2\xfd\x67\x65\x51\x0f\x9d\x71\xd8\xd6\xd1\x91\xe5\x90\x90\x95\xbc\x7f\x14\x7b\xdd\x49\x18\x30\x52\xf1\xd9\x6e\x97\x00\x5c\xc6\x5e\xbd\x2d\x15\x47\x9e\x3a\xfd\x8d\xa5\x55\x64\xa0\x65\x15\x44\x59\x80\xb8\x8f\xb6\x56\xd0\x97\x64\x05\xf7\x80\xa9\x75\x99\xa7\xc2\x30\xec\xd5\x82\x52\x7b\xb6\xd5\x7e\xac\x8e\xb8\xa2\xb6\x9a\x8d\x34\x13\xec\x60\x42\xb2\x18\x8e\x1f\x06\x7b\x73\xa3\x4e\xcf\x04\x5b\x2d\x74\x15\x7e\x44\x77\x75\xbc\xbb\x4f\x79\x87\xda\x2f\xd8\x0f\x1f\x03\x04\x63\x7b\xa1\xdb\xc5\x86\x3b\x1b\x2e\x02\x54\x7f\x83\xdc\x59\x18\x55\x56\xaa\x6e\x74\xd5\xd4\xe4\x3e\x0b\xe5\xd0\xc9\x98\xb1\x48\x19\x94\x74\x6f\x62\xf2\x3c\x19\xd8\x4f\xf8\x01\x22\xaf\x26\xd4\x8e\x11\x10\x4a\x81\x4d\x88\xd0\x93\x6a\xd4\x95\x99\xdc\x6e\xb4\xe1\xa2\xfc\x35\xcb\x73\x0d\x6a\x33\x53\xec\xfd\xf9\x64\x94\x96\x93\x7a\xf4\xfc\xe4\x64\xe4\xb5\xe7\x15\xfd\xa4\xcd\x36\xfa\x7b\xcf\xf6\xfa\x06\x9a\xef\x1d\x6f\xef\x4d\x4e\x8d\x3e\xeb\x0f\x19\x3b\xb9\x58\x2d\xea\x65\x9e\x35\x77\x69\xc2\x87\x0f\xfb\x4e\x01\x0e\x1f\x56\x26\x7f\xb3\x5a\xb4\x3f\x3b\xdd\xdd\x3b\xeb\x1f\x85\x5f\x8b\x0f\xad\x58\x55\xd7\x27\xf3\x72\x6d\xf7\xb0\x72\x3c\xb6\x4a\x1c\x97\x3d\x50\x97\x59\x4d\xb0\xb2\x63\x95\xcc\xb3\x34\x35\x45\x32\xe0\x09\x1a\xab\x04\x48\x5f\xa2\xe0\xe6\x9f\xd4\xf5\x1b\x48\xbd\xff\xae\xd2\x45\x6d\x19\x24\x4e\x9f\x93\x83\xfd\xf2\x64\x09\x0e\xd0\x63\x4b\xd0\x28\xab\x76\xd1\xfc\x8c\x22\xa2\x4a\x9e\xec\xef\x27\x22\x42\xa5\xae\x7f\x04\x9a\x8e\xf0\x34\x2a\x41\x33\x8c\xed\xfe\x5b\xfb\x9f\xd7\xe5\xaf\xf6\x9f\x45\x9d\x90\x8d\x0c\xd4\x29\xe8\x22\xac\x26\x75\xed\x39\xda\x85\x86\x74\x6b\x80\xb3\xb2\x2c\x2d\xed\xce\x40\x37\x74\x09\x37\x87\xc2\x9b\xc3\x67\x6c\x94\x46\x6f\x2c\xf2\x63\x55\x2e\x11\x29\x0f\x2d\xdc\xac\xdb\xfc\x8d\x0f\x88\x0b\x84\xb0\x7b\x07\xf0\xed\x91\xd5\x46\xfd\x4d\x13\xb7\xe4\x70\xe7\xe8\xe4\x74\xa8\x05\xe0\x5d\xc0\xe4\x23\x3f\x6a\x1b\x88\xfb\x0d\x0d\x12\x75\x9a\xe8\x25\x01\xe9\xd9\xa7\xa7\xfb\x67\xc3\xa6\xfc\xf3\x72\xe9\x42\x20\x76\xe1\xf9\xb0\xce\xb3\x89\xe9\x1d\xa0\x2a\xa3\xac\xb2\x99\xf8\x08\x9e\x41\x3e\x7e\xbf\x02\x81\x2f\x63\x47\x5e\xfe\x02\x3f\x17\x5f\xa0\x7f\xc7\x2e\x77\xc8\x03\x36\x75\x0e\x3a\x1e\x75\x5b\x55\xc9\x9d\x3c\x8c\x51\x1b\x6b\xd3\x20\x0b\x7b\x69\xde\xac\x2c\xe5\x65\x52\x46\x4e\xfe\xf5\xea\xbc\xa9\xf4\xa4\x89\xd1\x6c\x61\x5b\xb9\x23\x17\x06\x93\x08\xa8\x5c\x2e\xcb\x8a\xd1\x3f\xae\x20\xc6\x9b\x14\xeb\x5e\x71\x9a\x70\x3b\xc9\x40\xa1\x23\x3b\x20\xf6\x81\x57\x82\xae\xc1\x01\xb3\xae\xbf\x2f\x4b\x8c\xe2\x78\xad\x9b\xf9\x70\xa1\xaf\x7a\x6a\x7f\xc0\x4d\x20\xb4\xcc\x9e\xea\xf9\x2e\x53\x16\x26\xbb\x6c\x3d\x5f\xec\x11\x86\x92\x24\xcb\x2b\x07\xff\xc8\x81\x1a\xe1\xd4\xe8\x15\x38\x6b\x82\x02\xf8\x6d\xf5\x3d\x9c\xb3\xd0\x48\x65\xae\x9a\x4a\x0f\x54\x56\x7f\x0b\x1c\xcb\xb7\xe5\xd5\x00\x17\x26\xc6\xbc\x85\x82\x20\xa5\xf6\x64\x69\x75\xcc\x3a\x9f\x44\x8d\x9d\xae\x28\x61\x10\x49\xb4\x38\xaf\x9d\x1d\x98\x00\xcf\x1d\xc0\xcd\xc2\xe8\x7a\x55\x11\x0e\x09\xe2\x0b\x50\x9f\x9d\x43\xe7\x13\x1c\xe0\x68\xa4\xde\x36\x73\x53\xad\x33\x88\x30\xca\x1a\x02\x0f\xb2\xe7\x61\x5e\x56\xd9\xaf\x96\xcf\xc8\x15\x9c\x8e\xaa\xc9\x26\x3a\x17\x1c\x81\xdf\xa1\x56\xca\x06\xc6\x29\x51\xc7\xea\x40\x8d\xc1\x11\x9e\x26\xd0\x7b\x3f\x49\x4f\xd8\x27\xf6\x9f\xdd\x23\xf5\x88\xb7\xea\x68\x84\xca\xa5\xf3\xf2\x4a\x2d\xca\xd4\xe4\x56\x50\x9d\xe4\xab\xd4\x10\xa7\x34\xb0\x9c\xba\x4e\x53\x95\x35\x14\x32\xb5\xd6\x45\xa3\x84\xbb\xba\x9f\xcc\x04\x3f\x49\x44\x28\x58\x6e\x5b\x8b\xdd\x2f\x68\xa5\xec\x79\xaa\xeb\x97\x00\x0d\x40\xde\xa0\xe8\x45\xcb\x6b\xd6\xf2\xe1\x96\x6b\xc5\x6d\xc0\x08\x58\x4d\x63\xe5\x25\xdb\xf9\x9a\xd9\x76\xe8\xbe\xd3\x4b\xcb\x11\x48\x38\xa2\x78\x1c\x62\xe5\x9d\xc3\x7b\xae\xf6\xba\x46\x92\x50\x43\xc9\xa7\x8d\x46\x2a\xa8\x41\xef\x96\xd5\x0a\xd2\x3a\xf2\x9c\x64\x90\xe3\x16\x47\xa4\x0a\x27\x69\xc9\x71\xe0\xcb\xb8\xe3\xdb\x5d\x0b\x70\x4b\xbf\x79\xa3\xc7\xdd\xb6\xd7\x2a\x9c\xb1\x64\xe3\x00\x22\x9f\xc9\xdb\x87\x42\x73\xe9\xf6\x91\x94\xa7\x36\xee\x8f\xdf\x35\xab\x9f\xde\x09\x98\x50\xb9\x33\x6c\x87\x6e\x99\x4e\xd7\x8b\x60\x3e\xbb\x7b\xfc\xef\xcd\x67\x7c\x41\x5c\x82\x0e\xa2\x85\xe8\x7b\x17\xf1\x93\xd7\xf8\x89\x65\x25\x91\x93\x2c\xa7\x53\x2b\xf4\x32\x4b\x60\xa9\x79\x36\x99\x83\x56\xea\x9f\xab\xec\x52\xe7\x94\x05\x1f\xb5\x4b\xee\x30\x01\x1d\x26\xb2\x09\xbf\x5f\x89\xf3\x77\xe4\x53\xcb\x23\xb9\xe9\xa0\x49\x68\xc6\x86\xc6\xd1\x84\x37\x96\x8f\x70\x14\xde\x51\x80\x30\x12\x43\x17\x00\xbc\xbf\x83\x76\x3b\x27\x9f\x74\x38\x89\x0b\xcf\x70\x84\x1f\xba\xe4\x47\x95\x38\x41\x00\xcc\xdc\x0e\xba\xce\x01\x4e\xd1\x0a\xf8\xcb\xd0\x12\x50\x31\x08\xd8\x38\x9e\x7f\xb1\x52\xe4\xc8\x15\xa6\x9a\x2f\x67\x6a\xcf\xb1\xd9\xe7\xab\x19\x72\xd7\x92\xcb\xae\xe7\xe5\xfa\xc3\xf9\x6a\x36\x9c\xcc\xb2\xe3\x2c\x3d\xfa\xe2\xc9\xd7\x8f\xbe\xfa\x9c\x13\x53\x37\xf3\xd7\x3f\xfc\xde\x1a\x9e\x7c\x7d\xf0\xc5\x17\x5f\x31\x37\x66\xd7\xe4\xe9\x91\xda\xb7\x77\xeb\x65\x5b\x6d\x06\x28\xbe\x79\xae\x20\x68\xa6\x29\xbd\x3a\xa9\x81\x7b\xbe\x70\x7f\x5b\xde\x33\x9b\xaa\xc2\x4c\x4c\x5d\x6b\xc4\x8c\xc2\xf5\xee\x72\x13\x09\xb6\xb6\xef\xc7\xc6\x6e\x50\x55\x1b\x04\x41\x89\x80\x4a\xdd\x59\x15\x99\xb3\xd3\xa1\x93\xc0\x50\x9d\x34\xe5\x12\x85\x1d\x2b\x95\xe2\xf2\x0d\xef\x6d\x30\xf0\x5f\xea\xbc\x15\xf0\x74\x49\x0a\x3f\xdf\xde\xda\x90\xe6\x94\xa1\x98\x31\xdf\x01\x2a\x98\x0b\x35\xd1\xb5\x51\xda\xa7\x82\x85\xd3\xc4\xaa\xb2\x55\xc1\x0a\x43\x61\x03\x1f\x8d\xa0\x86\x96\x7e\xad\xce\xec\xd9\xcb\xaf\x21\x70\xb4\x76\xcb\x01\x4c\x05\xd7\xe2\x67\xc7\x31\x47\xe1\x41\x94\xc7\x83\xfc\xfc\x9d\xbe\x7a\xd8\x52\x6f\xf6\xfa\x7e\x31\xba\xa6\x5e\x7a\xd8\xa1\xfc\x63\x59\x93\x24\x19\x28\xbd\x6a\xca\x01\xc7\xf3\x2e\x35\x49\x97\x40\x78\xfc\xb6\x90\x5a\x98\x4b\xf0\x0b\xb7\x7c\x5f\xc0\xfc\xb3\x22\x5b\x4f\x2c\x9f\x2b\xb4\x5c\xc8\x82\x80\x6c\x93\xa6\x23\xc7\x38\x66\x56\x24\x34\x97\xf6\xd6\xc6\x0d\xe6\xe9\x24\xb6\x01\x8a\xad\x4e\xfe\xf0\x1e\xfb\x77\x13\x3e\x28\x4b\x04\x5b\x48\x2e\x21\xcb\xdb\xa7\x70\x80\x22\x4c\x50\xcc\x3d\x85\x18\x72\x9f\xb6\xfa\xf7\x3e\xdb\x82\x5c\x15\xa8\xc4\x8a\x58\xfb\x79\xb9\xfe\x3e\x63\x04\x4b\x0c\x7a\xb5\xcf\xa4\x47\x25\xca\xa1\x8c\x24\x86\xf2\xe9\xc0\xad\xba\x40\x36\xc5\x68\x3b\x97\xbd\x81\x42\xc8\x5c\xcd\xdd\x59\x1c\xe0\x9b\xa7\xca\x61\xeb\xda\xbf\xbd\x1b\xbc\x80\xf8\x20\xd8\x5c\x28\x2f\xd2\x3b\x6d\xfb\xcd\xe2\x8e\x50\x00\x8a\xf7\xd1\xb1\x9f\x2b\xe3\x2b\x08\x90\xc3\x44\x2a\x96\xa4\xcc\xd3\xc0\x03\x37\xf6\x1f\x1d\x06\x7e\xbc\xbe\x1f\x62\xd6\x84\x4a\x17\x73\x0b\xe6\x59\x61\xa4\x17\x3a\x70\x04\x1c\x95\xdc\x94\x2a\x37\xba\x22\xbf\x0a\x81\x21\x88\xb1\x66\x38\xdf\xea\xfc\xda\x1e\xf0\x89\x4e\x4d\xaa\xaa\x95\xa5\x67\x96\xcc\x97\x82\x55\xdc\x8e\x47\xb8\xb3\xd3\xe5\x50\xea\xb8\x86\xf6\x60\x42\x78\x0b\xee\xc6\x89\x11\x19\x56\x90\xaa\x80\x8c\x01\xc9\x3e\xca\x4b\x53\x55\xd8\x43\xb8\xd4\x9d\xd2\xa2\x20\xd0\x67\xf0\xcc\x2a\x00\x81\xd4\x6e\xc8\xb9\x31\x30\xe2\xf5\x5c\x37\xe6\x92\x74\x78\xec\x13\xc9\xa4\x8b\x48\x9a\x9b\x08\x20\x73\xab\xc9\x3c\x70\x1b\x0e\x82\xf4\xa3\x61\x38\x27\xb6\xac\xfe\x1e\x3a\xd7\x86\x9c\xbb\x6d\x3b\x70\x00\x52\x7b\x47\x0c\x62\x17\x64\x07\x11\x60\x05\xe7\xfe\x66\x76\x94\x56\xf1\xa8\xd5\xa3\x20\x12\x93\x07\xb0\x1d\xfa\xff\xd2\xc7\xae\xef\x51\x12\x8d\xae\x6e\xd2\x27\xc7\x6a\xb3\xbf\x79\xe0\x6a\xbe\x81\xf1\xa3\xe5\x87\x45\xf2\xdb\x77\x51\xd6\x4d\xe4\x32\x5e\xd3\x22\xa3\x61\x3e\x2f\xcb\x25\x7e\xed\x40\xed\xd0\x07\xb6\xa8\x1b\x4b\x30\x2b\x33\xcd\x21\x4d\x39\x45\x9c\x31\xdd\xf8\x5f\x22\x07\x0e\x57\xde\x1e\x59\x06\x8b\xef\xd8\x42\x6e\x05\x36\xef\x31\x19\xad\xd3\x3a\x4c\x50\xff\xb1\x8a\xb7\x1a\x46\xbf\x8d\xa9\xfe\x6e\x5d\x0c\x8f\xf0\x70\x63\x46\x00\x02\x73\x76\x6a\x1e\xa7\x8b\xf3\x4e\x4c\x74\x38\x21\x3b\x95\x3f\x66\xf8\xed\xb9\x99\xeb\xcb\x0c\x98\x48\xcb\x00\x80\x47\x07\x84\x2f\xf0\xef\xa8\x5a\x54\x17\x82\x76\x65\x4c\x6a\xf3\xa5\x9e\x80\xca\x12\x67\x20\x74\xf8\x62\xb8\xf2\xc8\x87\x75\xab\xdb\xb5\xd5\xc1\xed\xd7\xf3\x72\x95\xa7\x4a\xa3\xcb\x38\x7a\x0d\x16\xa0\x72\x42\x2e\x04\xdc\xe7\xa9\x61\xfa\x50\xe4\x0d\x09\x78\xbf\x84\x8a\x25\x3e\xf2\x4d\xb8\xe4\xd1\xf2\x1d\xab\xe4\xc0\x2e\x85\x33\x94\xb4\x92\xaf\xb8\x5c\x72\x64\xe5\x5f\x35\xe5\x42\x83\xf6\x23\xbf\x06\x49\x0d\x74\x44\xc8\x1d\xd5\x86\x9d\xd4\xae\xf7\x2c\x4f\x98\x1b\xaf\x23\x45\x1d\xc9\xa4\xae\x51\x83\x46\xb3\x96\x4c\xca\x7c\xb5\x28\x9e\x97\xab\xa2\x49\xc6\x5e\x78\x49\xa6\x59\x9e\xbf\xa5\x01\x04\xcf\x73\x73\xf5\xc7\xaa\x5c\xb7\x1e\x9e\xcc\xab\xac\xb8\x08\x1f\x3b\xcd\x6f\xf0\xd8\x5e\x46\xdf\xb7\x1f\x97\x1d\xad\x21\xd3\x11\x3e\x59\xce\x75\x51\x07\xcf\xd6\x59\x5a\xae\xc3\x47\xe8\xbe\x18\x3e\x2a\xcb\x05\x3d\x08\xe6\x95\x36\xb1\x30\x2e\xad\xe7\x65\x6d\x48\xc7\x7b\x5d\xae\xd4\x3a\xab\xe7\x80\x44\x9b\x5d\x29\x0c\x15\x64\x73\x02\x6e\x55\x64\x61\x1b\xde\xe6\x2c\x20\x82\xa6\xb4\x5c\xf2\x76\x1d\x8d\xac\xa0\x4d\x8c\xe3\xd4\xb2\x82\x81\x0a\x9b\x26\xb2\xd4\x76\x56\x92\x49\x5d\x03\xb7\x98\x04\x5d\xfd\xa3\x69\xf8\x8c\xa0\x1b\x52\x78\xf0\x4a\x4b\x01\x5f\xbc\x7d\xad\xde\x20\xc8\x38\xbc\x6e\x9f\x09\x14\x4a\x48\x75\x2a\x04\xe4\x2d\xbf\xcb\x6c\x03\x24\xb5\x94\x05\x02\x97\x6b\xf4\x77\xf2\x10\x36\x21\xc5\xeb\xce\x79\xf1\xb8\xfb\xf1\x57\x70\xab\x74\x10\x4a\xe1\xb4\xf8\x31\x84\x59\xa9\x57\x15\xf9\xb6\xac\xcd\x83\xca\xa8\x75\x59\x5d\xd8\x09\x77\x90\x2a\xa8\x6d\x2c\x28\x9a\xc5\x59\xf1\x10\x78\x14\x48\x12\xf2\xa5\x42\x13\xce\x17\x92\x5e\x98\x1c\x74\xe7\xa4\xf4\x17\x0c\x6c\x87\x9b\x3e\x2b\xc2\xfd\x75\x06\xab\x7c\xea\xd4\xd7\x48\x61\x7b\xb7\x16\x38\xda\x64\x76\x70\x65\xfa\x52\xe2\x00\xe7\x06\x3b\x08\x07\x22\xe0\x2c\x03\x97\xa6\xaa\x49\x8f\x0a\x9c\x4a\x9e\x97\x6b\x93\x5a\x76\xcd\x16\x5b\x15\x5d\x05\x91\x42\xcb\x21\x00\x5d\x75\xb2\x8e\x0b\xcd\x11\xaf\x7c\xe7\x7d\xb7\x9c\xf3\x06\xae\x89\x27\xdd\x7c\x04\x24\x64\x55\xe8\x84\xcc\x2b\x4e\xd9\xe2\x24\x7e\x87\x50\x5e\x4d\x08\xc1\xbe\x32\xb9\x06\xa9\x88\x68\x31\x82\x7b\xd4\xaa\xb7\x7b\x64\x4f\xdf\xde\x51\x1f\x13\xef\x04\xa5\xea\xa1\xba\xff\xe5\xe3\x27\x9f\x7b\xf6\xa6\xe1\x0d\x28\xb1\xa9\x7a\x48\xbc\xc9\xc0\x16\x1a\x09\x62\x7e\x0d\x41\xea\x4d\x73\x7a\x70\xa6\x76\x01\x98\xe2\x21\xfc\xf9\xc8\xfe\x29\x65\xbc\x36\xaf\x53\xf8\x45\xdd\x92\x18\xe6\xe7\xab\x99\xba\xff\xf5\x23\x08\xbb\xf0\xf3\x91\xe0\x10\xda\xcc\x70\x74\x18\x40\x6d\x60\x8f\xe6\x1b\xfd\x86\xdd\xdd\x75\x65\xe8\x0c\x0f\xd5\x89\x31\x63\x75\xff\xcb\x83\x83\x2f\xfc\x2c\x30\x48\x0a\x7e\x8c\x52\x2f\xad\x4f\x88\x59\xb6\xc9\x87\xf8\xd5\xd4\xdf\x8a\x6b\x5d\xab\xa5\xae\x6b\x00\xa3\x18\xc0\x85\xf4\x60\x79\xf5\x80\xc5\xf5\x1e\x19\x6a\xed\xb6\x65\x74\x8a\xd0\x94\xdf\xef\x5a\x1e\x1a\x7d\x10\x06\xc2\x37\x57\x70\x8e\xa2\xe5\xd9\x3d\x62\x29\x33\xec\x31\xc1\xc5\x7f\xf5\xf5\xfe\x57\x03\x06\xd6\x38\x87\x98\x46\xa3\x20\x3a\xd3\xc3\x68\x9c\x5f\x53\x4c\xe5\xb5\xdd\xca\x35\xd8\x34\x03\xdb\x8e\x0b\xca\x3c\x5f\x35\x10\x92\x09\x1c\xc3\xc2\xe8\x02\xe3\x0f\xc1\xa1\x1a\xae\x37\xd5\x03\x4d\xc0\xa5\xa9\xae\xed\x80\xcf\x73\x03\x37\xb7\x23\xd8\x7d\x95\xa5\xa6\x40\x4b\x06\x13\x69\x01\x15\xbe\xbd\xc9\x9d\x77\x67\x47\x02\xdd\xc0\x2c\x81\xc5\x0f\xf8\xbb\xb7\xd3\x9e\x4a\xbc\x93\x6f\x42\xba\xbe\x7d\x01\x89\x12\x19\xec\x93\xac\x98\x9b\x2a\x6b\xda\xd3\x06\x0b\x0d\x64\x07\x96\xb9\x2a\x2f\xb3\xd4\xa4\x8c\xeb\xa5\x1b\xbe\x44\x4a\x67\xb6\x01\x84\x38\x77\x3d\x61\x6c\x2a\x87\x3d\x88\x91\x21\x01\xb2\x97\x40\x2f\xa9\x4d\x93\xd8\xf9\x85\x67\xa0\x17\xe9\xf1\x59\x83\x47\x52\xc6\x08\x2f\xad\xfe\x06\x9a\xd2\x1a\xa1\xc0\x38\xa3\xd1\xc5\xaa\xfa\xee\x91\x02\x03\x08\x9e\x1c\x65\xb1\x17\x05\x8f\x70\xba\xa1\x4a\x8c\x0b\x87\xb5\xb3\xa3\x92\x99\x1c\x94\xa0\x32\x38\x22\x21\xee\x93\x5e\xf6\xae\x11\x75\xf8\xd3\x70\xd7\xdf\x86\x93\xcf\x5d\x0e\x7b\x49\xac\x82\x73\xf5\x74\x35\x76\xea\x17\x85\x7d\x7e\x13\xfb\x40\x56\xc5\xc0\x90\xc8\x2a\xf1\x81\x25\x0e\xbf\xf7\xd2\x3d\xfc\xb7\xee\xfb\xff\x99\x3b\xd9\x5f\xfd\xff\x0f\xbb\x98\xef\xd8\xce\xb7\x6e\xe5\x5b\x77\x72\xa8\xa1\x6e\xed\x66\x34\xe5\xd0\x66\x8e\xd8\x38\xb7\x4f\x07\x96\x63\xd0\x32\x02\xbc\xa3\x4f\xe6\x2a\xab\x9b\xda\x93\x1a\xc9\x4c\x44\xe8\x97\x61\x9f\xee\x54\xc0\xbb\x1e\x31\x73\x91\x20\x5b\x9e\x04\x1a\xff\x16\x07\xc3\x12\x39\x16\x25\x92\x4b\xf7\x42\xec\x10\x13\xf5\xa8\x55\x60\x83\x3e\x1f\xd3\x4e\x0d\x98\xeb\x01\x79\xa2\xe4\x8b\x36\x9b\xda\x2d\x36\x31\xa9\x82\x00\xc2\x7f\xae\x74\x6e\x69\x6b\x15\xae\xb0\x65\x05\x6c\xab\x39\xac\x56\xb1\x5a\x98\x2a\x9b\xdc\xeb\x30\x4a\xa3\x5a\x41\x32\xff\x5b\x05\xb8\x17\xb5\x34\xd5\x87\x92\x5c\xf8\x1a\x20\x1e\xc5\xef\xc7\xcc\xde\xce\xb6\xb1\x9e\x6d\x55\xf5\xd5\x31\xfc\x0b\xde\x0d\x63\x69\x4b\x88\xed\x0b\xdd\x90\x2e\xa7\x2a\xc1\xb0\x92\x64\xe0\x2c\x67\x67\x12\x67\x25\x93\x1e\x3a\x5b\x9b\xce\xcb\x51\x57\x2c\x58\xa4\x1a\x88\x64\xa0\x4d\x0a\x02\xcb\x8d\x12\x03\xe3\x54\x4e\x96\x8d\x00\x55\x64\x9a\x2d\x4c\x51\x83\x5f\x6f\x31\x2d\xc9\xa0\x9e\x15\xe0\x57\x95\x5f\xa3\x1e\xa6\x99\x9b\x85\xab\x6a\x5e\xae\x2d\x5f\x00\xcc\xc8\xc2\x92\x6d\x04\x56\xb0\xbb\xb7\xb2\x12\x16\xeb\x70\x90\x6c\x23\x1d\x04\x3e\xe3\xdc\x14\x66\x9a\x35\x7c\x66\x49\x47\xe9\xee\x07\xe1\x8c\x46\x31\x9a\x77\x68\xdd\x1c\x76\xac\x34\x48\x22\xc3\x40\x69\x00\xb6\x84\x37\xa5\x9b\x3b\x74\x29\x1b\x74\x38\x7c\xbb\xbe\x7c\x92\x61\xd6\x01\xf7\xbb\xd4\x02\x5b\xbf\xe3\x3b\x42\xfc\xc4\x03\x54\x77\x2d\x72\x97\x94\xeb\x71\x4c\x6a\xe7\xf5\x82\xd9\xe1\x5a\x71\xd6\xe2\x9e\xbc\xc3\x05\x09\xab\xa1\x29\xdb\x6c\x74\x91\x66\x17\x69\x78\x21\xd3\xcb\x20\x9c\xf2\x7f\xd5\x98\xcb\xd5\x78\x1b\xcc\xd6\x56\x5f\x8d\xd5\x3e\xfc\x8c\x22\xf0\xfa\xad\x64\xf3\x81\x0f\x76\x74\xb4\x22\x6f\xe6\x30\xc6\x93\x19\xd6\x8e\xd8\x80\x81\x88\x8f\xda\xa4\x9c\xeb\x3e\x79\xff\x69\x9f\x7c\x5b\x5f\x59\x5d\x28\x0d\xfc\x31\xdc\xc7\x04\xd7\x92\xd9\xa3\x4a\x32\x2c\x1b\x47\xf8\x20\x36\x25\x99\x51\xf6\xc0\x19\x52\x6e\x8d\x8e\xf3\xf1\x9b\x3f\x64\x63\xcb\x5f\xfb\x0f\xc9\x8b\x72\x6b\x6b\x0b\x2f\xaa\x01\xe5\x92\x1b\xb0\x9b\x0a\xcc\x56\xe2\x72\x33\x92\x62\xd6\x2d\xd2\x3b\xd0\xf2\xe1\x65\xac\x2b\x83\xce\x67\xe7\xd7\x4a\x17\xd9\x42\x63\xc0\x3a\xa6\x15\x09\xf4\x7e\x31\x5a\x16\x79\xb1\xab\x04\x51\xb2\xc8\x83\x9d\xfe\x24\xcf\x76\x76\xd0\x88\x00\xae\x90\x6d\x19\xa8\x7a\x35\x9d\x66\x57\x9b\xe8\x2f\xb9\xea\xef\x72\x31\x47\x8a\xb1\x73\x1b\x31\xb5\xa3\x04\xec\x5c\xde\xa0\x07\xf6\x40\x44\x2c\x60\xb8\x13\x24\xb0\xc9\x8a\x59\x6e\xc4\x3d\x59\x94\x0d\xa8\x8f\x2b\x17\x22\xb0\x04\xff\xe1\xa3\x5b\x60\x42\x49\x4b\x3e\x04\x4f\xc1\x5e\xa2\x12\x7b\x5e\x4e\xa9\xe4\x59\x98\xf0\xd4\x7b\x8d\x49\x48\x3a\xee\xa9\x18\x7c\xcb\xe7\xc5\xcf\x06\x9d\x50\xe8\x98\x43\x8e\x76\x7f\xed\xb1\x03\x20\x3d\x71\xd9\xe0\x3e\x86\x71\xb7\xdc\x66\x70\xa2\x5d\x38\x6a\x18\xac\x4f\xbd\xea\x47\x91\x5c\xb7\xac\xd9\x10\x61\x62\x5b\xa4\xaf\xf3\xda\x0e\xf3\xd4\x44\x92\x83\x50\x39\x7e\x22\x7a\x7a\x4b\x55\xd9\x41\xbd\x07\x2a\x27\x43\xf0\xd6\xd6\x02\xbc\xaf\x43\x34\xf5\xc0\xb4\xe5\xf8\x14\xca\x6c\x26\xb1\x0b\x3c\xad\xec\x72\xb6\xa1\x3b\x2a\x07\xf3\x19\x08\xda\x11\xea\x67\x80\xaa\x69\x8a\x18\xaa\x70\xa1\x97\xc8\x90\xe0\x3a\x9f\x75\x3a\xeb\xb8\xf7\x2d\xea\x1e\x43\x40\x3a\xa7\xd5\x65\xe7\x96\xe8\x52\xb6\x85\x09\x7d\x5a\xb0\x18\x7e\x86\xc7\x41\xc1\x96\xf6\x0a\xb7\x59\xa4\x41\x6e\x21\x6c\x7f\xa3\x0e\x3c\x6e\xf2\x96\xe5\x7d\x36\xe6\x20\xf1\xd6\x7f\x5c\xff\x10\x73\x79\x6b\x9e\xa5\x9b\xd3\xad\x84\xdf\x8a\xaf\x9a\x72\x36\x0b\xf5\xde\x98\x5e\x5b\xde\x32\x44\x08\xf0\x05\x5d\x9f\x65\x6e\xb4\xf0\x12\x74\x02\xb2\x2d\x82\xc8\x77\x43\xdb\x66\x8f\x13\x83\x0c\x6d\xf7\x7a\x1b\x41\xe5\xba\xd3\x22\x91\xc7\x26\xdb\x60\x19\x91\x9b\x37\x0b\x23\x22\xe1\x73\x6a\x8f\xd6\x39\x40\x64\x8c\x0a\x8a\xae\xb4\x62\x6d\x0e\x23\x5c\x86\x77\x6b\x63\xda\xc1\x30\xf6\xba\x18\x28\x53\x58\x7e\x58\x03\x9a\x01\x76\x8a\xbd\xb6\xcd\x1a\x3f\x1c\x2e\xab\xb2\x29\xed\xfc\x0d\xb3\x22\x6b\x3e\xa5\x1e\xb4\x21\xd2\xa6\x82\x4a\xd4\x11\x56\x06\x5d\x8b\xaa\xa5\x9b\x02\x6c\xb5\xd5\x6a\xd2\x94\xd5\x18\x0b\x23\x3c\x63\xd6\xc1\xe5\x6d\x6e\x7c\x80\xbe\x51\x34\xbf\xb8\x2e\xde\x84\x7b\xe8\x1e\xda\x0f\xad\xf0\x53\x95\x4b\xff\x90\xfa\x7f\xc4\x03\xb9\xb9\x51\x49\xbd\xb6\xd7\x85\x2f\xc3\x11\x31\x2e\x16\xc7\xbf\x82\xa8\x15\x46\xdf\x2e\x20\x00\x03\x71\x13\x57\x15\x2d\x15\xb6\x52\xd8\xcb\xcd\x14\xa9\x7f\x04\x7d\x3e\xc2\xae\x47\x6a\x0b\xd6\x81\x42\x87\xcf\xd4\x31\x59\x72\xc1\x4f\xdc\x9d\x80\xc9\xaa\x23\xed\x8f\xa5\x9b\xac\x5f\x70\x53\xbe\x24\xda\xef\x27\xe1\x2c\x4c\xb5\xe1\x14\x01\x4e\xd6\x27\x6a\x22\x64\xff\x20\x37\x58\x54\xb5\xcb\xb8\x2a\x8b\xba\x8e\x56\x2b\x19\x25\xcc\x30\x39\x01\x10\xa6\xae\x4d\x3a\xf0\x2d\x7e\x5a\xe7\x7d\xaa\x22\x5a\x95\x61\xba\x42\x00\x61\x6f\x78\x80\x8f\xca\x1a\x97\x17\x18\x0c\xc7\x25\xd9\xd5\x3e\x55\x72\x0f\x9c\x11\xfb\x4e\x3d\x1c\x6c\xa8\xfc\xa1\x72\x05\xf6\x07\xea\x60\x43\x31\xc9\x85\xcb\x43\xdd\xd1\x25\xaa\xce\x0b\xcf\x62\x33\xd1\x08\xed\xfe\xd9\x53\x62\xc7\xf5\xd5\x43\xfa\x7e\x57\x3c\xde\x38\x33\x75\x63\x96\xe1\xac\xc8\x37\x02\x9b\x78\x68\x44\x12\x27\x2b\xfc\x09\xac\x6f\xe9\x8f\x1e\x6d\x99\xda\x78\x38\x6e\xa1\xd0\x95\x1f\xcb\x49\xd8\xb8\x7f\x5a\x5f\xdd\xeb\xc6\x87\xed\xa2\x29\x40\xaa\x02\x12\x13\x15\x08\x3f\xc2\xa6\x89\x10\x71\x07\xc6\x9d\xba\x84\x06\xc8\x99\xe4\x4d\x2a\x53\x63\x82\x61\x4f\xef\xa1\xd0\x10\x31\x16\x1b\xd7\x88\x3a\xe3\x54\x44\x0e\x87\xb8\xb7\xed\x8b\x92\x69\xf4\xe6\x46\xc5\xcf\xa2\x4a\xc8\x92\xd3\x6f\x69\x8b\x37\x35\xdb\x52\x21\x2f\x35\xe2\xd7\xe8\x82\xb2\x32\x20\x57\x0c\xb8\x3f\xea\x71\x95\x2a\x80\x47\x34\x8d\xa9\xac\x7c\x61\xc9\x90\x5a\x67\x79\x1e\x3a\x23\x70\x65\xba\xb1\xf2\x94\xe5\xc0\xbd\x2a\x09\xf4\x52\x2e\x0b\x08\x44\x69\x51\x13\x14\x7c\x0f\x45\x11\xa8\x90\xeb\xa9\xcb\x01\x83\x18\x92\x61\x0b\x5d\xb0\x6a\x95\x1c\xec\x5b\x7a\x67\xc5\x1f\xf8\x0e\xe2\xbe\xa0\x9d\xe1\x3d\x67\x38\xb4\x1f\x5e\xb5\xbe\xac\x4a\x7b\x9d\xf7\x0e\x2a\x9d\xf6\xb1\x06\x9c\x2b\x8a\xe0\xa9\x87\x74\xf5\xdb\x25\x8c\xf8\x34\x3f\x9b\x03\x31\x9b\x08\x6e\x7c\xc8\xed\xbe\x14\xd3\x57\x73\x2a\x12\xcf\x88\xd9\x69\x48\xec\xac\x61\xdb\xa4\xe8\xc3\x01\xec\x0f\x25\xdb\xb1\x4d\x7d\xb8\xb9\x51\xdc\x1b\xcb\xa5\xe0\xb7\xc7\xa0\x54\x73\x1b\x8d\x63\xf2\xeb\xdb\xb6\x26\x79\x98\xc2\x69\x77\x0a\x6b\x58\x0e\x3b\x57\xba\x51\x7b\xf0\x9e\xc4\x01\xf4\x05\xac\x09\xa3\x08\x5f\xd1\x86\xc4\x37\x6e\xb5\x2f\x75\x96\x83\x43\xae\x1d\x1b\xc0\xf4\xe6\x3a\x76\xa7\x00\x2f\x64\x2e\xd8\x62\xc9\xa7\x57\x40\x69\xa2\x5d\x1d\xb1\x44\xdd\xa5\xdc\x20\x03\x16\x29\x3a\x73\xd4\x6f\x80\x7c\x6d\x1f\xa5\x96\x45\x20\xe8\x85\x3f\xa2\x5d\xaa\xf7\xa8\xc3\x71\x97\x89\xd1\xde\xb4\x71\xf0\xb7\xa5\xe5\xbb\xf4\x1b\x79\x95\x2e\x76\x6f\x23\x05\x39\xf2\xd5\xb4\x1d\xe8\x3e\xb6\x54\x3b\x80\x14\x38\x1a\xa9\x1f\x75\x91\x4d\x08\x18\x41\x2f\x97\x55\xa9\x27\xe0\xe2\x52\x3b\x3f\x16\xb0\xaf\x97\x00\xf5\x38\x29\x8b\xc2\x4c\xec\x36\x25\xc7\x8f\x16\xa9\x1c\xd6\x93\xaa\xcc\xf3\x77\xc0\x44\x75\xbf\xfb\xc1\x4c\x1b\xa2\xa8\xb7\xed\xd3\x78\xed\x9c\xdf\xc8\xce\x8e\x7c\xdc\x91\xea\xee\x93\xa7\x28\x98\x9c\xe0\xce\xa7\xfe\xe5\x59\x61\x74\x15\x30\x26\x91\xd4\xba\xf4\xe2\xcd\x1a\x34\x27\x9b\x8b\xee\x0f\x3f\x57\x7b\x10\xbc\x30\x9c\x94\xb5\x7d\xff\x10\xff\xfa\xf1\x95\xea\xab\x91\x7a\x74\xd8\xd1\x9d\xe9\x55\xfb\x8a\x82\x3b\x8c\x17\xf4\x5b\x7b\x70\x9f\xe3\xc1\x7d\x7a\x30\xfc\x4a\x81\xec\x0d\x1a\x68\x08\xf4\x11\x35\xe1\x05\xff\x7f\x31\xf7\xee\xdf\x6d\xdb\xd8\xfe\xe8\xcf\xce\x5a\xfe\x1f\x10\xa6\x37\x95\x62\x59\xb2\xd3\xa6\xd3\x2a\xe3\xf1\x4d\xf3\x98\x66\x6e\xd3\xf4\x34\xe9\x69\xcf\x72\x7c\xba\x60\x11\xb2\x18\x53\xa4\x86\xa0\xfc\x68\xed\xff\xfd\x2e\xec\x07\xb0\x01\x52\x76\x3a\xe7\xf1\xfd\xce\x5a\xd3\x58\x24\x88\x37\x36\xf6\xf3\xb3\x7d\x00\xbb\x0c\xbd\x9e\x5f\xfe\x00\xf7\x78\xb1\x34\xcd\x6b\xe0\xb2\x9a\xf9\xa5\x6b\xcb\x62\x24\xf3\xe1\x14\x65\xa9\x6b\x27\x87\x5c\x3b\x19\x63\xf8\xd9\x84\x8a\x55\x7d\xc1\xc8\x87\x53\x8a\x47\xbe\x1e\x26\xf1\xcc\x08\xea\xd9\x09\x6a\x5e\x3b\x51\x60\xf2\xcf\xb5\x59\x1b\xd8\x2c\x58\x3d\x2a\xb3\x8a\xba\x82\x48\xd3\x12\x2c\xf0\x07\xea\x88\x1d\x08\xfd\x53\xcc\x48\x03\xab\x8b\x45\xd0\xa7\xed\x51\x36\x55\x47\x91\xca\xca\x1d\xb7\xae\x16\xa1\x25\x51\x04\xb9\x72\x40\xc9\x20\xd9\x28\xfa\x82\x54\x0a\x3e\xe7\x28\xee\x26\xe0\xe2\x47\xb1\x7a\x09\xa7\x25\x76\x21\xa1\x22\xc4\xd2\x63\xc9\x87\x0f\x59\xb1\xf3\x45\xd7\x30\x79\x1b\x87\x2f\x15\x60\x10\xc9\x54\x78\x5d\xa7\xc0\xa2\x52\x85\xc7\xbb\xc2\x38\x1d\x1f\x11\x8d\x22\xc5\xb2\xb0\x14\x68\xca\xaa\x0f\x14\x54\x6e\xe9\xc5\xf5\x35\x7e\x8a\x01\x60\x97\x60\x00\xdb\xa1\x19\x11\x69\x14\xa2\x09\xd8\x74\x79\x42\x95\x43\x3f\x33\x76\xa6\xc1\xcf\x6a\xdf\x6b\x72\x2e\x5f\xb7\xa6\xd1\x2c\x57\x3d\x8e\xf5\x38\xd8\xd9\x87\x0f\xf1\x0f\x9c\x41\xd4\x76\x14\x6d\x64\xad\x79\xdf\x40\xb6\xba\xaa\x80\xe8\x25\x82\xc4\x3e\xb9\x12\xdd\x8a\x56\x86\x85\xad\x50\xad\xc4\x47\x09\x36\xe9\x0b\xa3\xd6\xab\x1c\x54\xad\x0b\x43\x5b\x48\x5c\x76\x98\xb1\x84\x33\x5a\xf0\xc6\xc0\x7f\x01\x73\x21\xca\xa3\x86\xe3\x3c\x37\xe5\x15\x52\xe1\x4b\x54\xe2\x82\x71\x47\xab\xaa\xae\x7e\x37\x4d\x8d\x5d\x72\x2b\x4d\x47\x5b\xae\x19\x2f\xc2\xf5\xb5\xda\x17\x30\x1d\xd2\xad\xf5\xf5\x1c\x32\xcd\x15\xf5\xda\xaa\x82\x67\x56\xb9\x9a\x4d\xae\xea\x75\x3b\x52\x79\xbd\x76\x37\x38\x02\x92\x5f\x18\xb0\xc9\x3e\xf2\xc0\xe4\x8f\x42\x55\x3f\x43\x84\x0f\xb1\x6e\x00\xa2\xe0\xbe\x84\x1f\x1a\x92\x10\xd8\xda\x7d\x8f\xd0\xc9\x7a\x36\x03\xff\x16\xf0\x54\xb5\xc6\x28\x5c\x69\x6d\xd5\xba\x62\x3c\xcc\x13\x83\x7e\xd8\x72\x23\xe0\xbf\x4e\xd8\x1e\x3f\xc9\xa2\xec\x22\xcf\x72\x70\x71\x70\x9c\x06\x20\x5a\xf0\x87\x34\x17\xf8\xef\x04\x2b\x60\xcb\xd2\xe6\xbb\x18\x0f\x39\x7e\xb4\xa3\xfc\xdd\xeb\x57\xe7\x67\x5c\x66\xa8\x6d\xa4\xda\xba\x84\xa9\xab\x4e\x61\xea\x54\xdd\x80\xcf\x15\xda\xe1\x02\x45\xf0\x5f\x3f\xab\x72\x75\xd2\x18\x7d\xc6\x6e\xa1\x65\x5d\xaf\x1c\x6b\x82\xc3\x2b\xe4\x2c\xb8\x23\x6a\x9a\xb9\x99\xb5\x80\x5d\x81\x0e\x75\xe7\xe4\xd0\xb1\xd0\xb9\x32\x55\xbd\x3e\x5d\x90\x22\x50\x71\x70\x3e\xd6\xe4\x36\xff\x80\xe7\x4e\xf4\x44\x4d\x28\xb7\x31\xd8\xf8\x42\x59\xc8\x97\xb5\xbb\x1b\x1f\xb3\x6e\x1c\x2e\x8d\x3e\xdd\xe0\xe1\x20\xe2\x9e\x16\xfa\x53\xd2\x76\x40\x0f\xfc\xf6\xc4\x3f\xae\xaf\xe5\x46\xdd\x7b\x2a\x99\x1a\x71\xfe\x82\x6f\x1c\x38\x30\xec\x1c\x4c\x76\x0f\x54\x5b\x9f\x99\x2a\x71\x40\x42\x9f\x90\xbc\x46\x6f\x43\xef\xf7\xe7\xef\x8d\x88\x69\x02\xfd\x0a\xd1\xdb\x7d\x47\x51\xa3\x6d\xb3\xc3\x43\xc1\x97\xec\xd5\x47\x8f\x1e\xab\x63\x6f\x98\xdc\x09\xcf\x7a\x35\xaf\x2d\x69\xb4\xdc\x12\x1d\x7b\x5d\x3c\x6c\x05\xea\x96\x55\x0c\x92\x6e\xaf\xaa\xd9\xa2\xa9\xab\x7a\x6d\xcb\x2b\x14\xa6\x20\xd1\x8b\x7c\x2c\xc1\xa7\xe1\xb3\x57\xee\xba\x26\x75\x8e\x35\xed\xfb\x62\x69\xea\x75\xdb\xd1\x31\xc2\xad\xae\x84\xfe\x17\x38\x0c\x09\x78\x30\x50\x5c\x86\x4e\x47\x05\xf5\x0e\x3d\xa6\xfe\x44\xfd\xdd\x5d\xa9\x6e\x03\x78\xd1\x0f\x73\x34\x41\x47\x80\x06\xe8\x2a\xc7\x54\xf8\x7e\xce\x45\x4c\x6e\xf5\xea\x72\x40\xbe\xb7\x14\x7c\x8e\x96\x65\x01\x94\xbd\x28\x66\x0b\x8f\x43\x81\xe6\x1e\xdd\xb6\x78\x8d\x13\xdc\xfb\x14\x5d\x02\x03\xf2\x0e\x1b\xd6\x31\x16\x9f\xb0\xb6\x81\xbf\x39\x67\xb8\xeb\x7d\xf0\xc2\xab\x95\x2e\xcb\x60\x7f\x61\x84\x1e\x59\x0b\x12\xa9\x5b\xeb\x7a\x0c\x2c\xf1\x59\xb1\x82\x48\x06\x05\x2c\xac\xab\xed\x27\x32\x26\x46\x43\x3b\x88\x47\x4a\xd8\x03\x4f\x53\xac\x01\xe5\xc1\x06\x76\xfb\xa6\x66\x0b\x03\x9c\x0e\x12\xdb\xd1\x53\x3f\x3d\x47\x21\x9e\x7d\x87\xa2\xa1\x1c\x8b\xcb\xef\x44\x88\x78\x78\x49\x1a\x0e\x09\xc1\xdd\xd7\x34\xd4\x31\x26\x3f\x7c\xae\xd3\x83\x50\xc5\x95\xb0\xf9\xc6\x15\xe9\x04\xf5\x45\xbc\x14\x99\x09\x90\xda\xfa\xdd\x22\x76\x42\xcb\xca\xdd\xad\x59\x5d\x96\x86\x33\x0b\x12\xb1\x36\x8d\x95\x5c\xc8\xd1\xb1\x1a\x8e\x31\x6d\xa2\x2c\x90\x3d\x02\x93\xe9\x6d\x51\x80\xa1\xf2\x60\xbf\xf9\xd4\x28\x40\x98\xb2\x01\xf3\x8b\xa1\x26\x1f\x53\x43\x6a\x32\x3f\xbc\x51\xcc\x42\x26\x18\xd9\x4c\xbe\x2a\xc3\xfe\x6c\x45\x1c\x08\xd0\x43\x52\x48\x4a\x88\xe6\x39\xe5\x87\x59\x1f\xee\xaa\xb2\xa0\x16\x67\x02\x3d\x79\xa4\x3e\xda\x45\x51\x81\xcb\xa6\x5b\xd0\xc2\x62\x28\x04\xe4\xb7\x40\xbc\xdd\xd0\x61\x77\xdb\x39\xbe\x9f\x64\x54\x76\xe5\x53\x75\x99\xcf\x8b\xc6\x8c\x42\x48\x26\x84\x01\x53\x2c\x1a\x1e\xe1\xaa\x58\xca\xd4\x92\x75\x53\x9c\x06\xc3\x5c\xd7\xa7\x1e\x1e\xfb\xe0\xb4\x8e\xc8\x97\x46\xab\x21\x2e\xaf\x6e\x35\x21\x1a\xf5\x87\x50\xce\x2f\x9d\xc0\x22\x13\x98\x2c\x74\x95\x97\x46\x81\xa0\x31\xa5\xbc\xb8\xab\xa6\x5e\x16\x16\xae\x34\xb4\x97\xba\xf9\x1a\x43\x11\x5e\xf7\xc4\x1f\xef\xb7\x20\xa8\x88\xb6\x32\x19\xd9\x8d\x1a\xce\x75\x05\x25\xf3\x4e\x64\x77\xfa\x9a\xef\x42\x9a\x59\xef\x53\x07\x6a\xb8\xb1\x7b\xf4\x54\x7c\x17\x9e\x4a\x58\xb3\x38\xb4\xe9\x7e\xd2\x44\xb0\x43\x52\x1b\x09\xe0\xe3\x4d\x50\xa6\xc6\x5f\xee\xec\x10\x33\xe4\x96\x74\x8c\x11\x51\x5d\x7b\xd6\x64\x42\xd7\x30\x26\xc1\xd1\x67\xa0\x6d\x63\xdf\x4d\x76\xec\x03\x80\x6a\x5c\x83\x06\x6f\xbb\x13\x03\xe8\x64\x26\xe7\x5a\x30\xb0\x06\xab\xe1\x4f\x90\xdb\xb8\xb5\xfd\xa4\xd3\xbb\xbb\x4f\xe5\x5c\xd0\xba\xc1\xbb\x78\xc5\x7c\x3a\x60\x3f\x3d\xe9\x14\xa7\xf3\x14\xa5\x07\xf7\xfb\x0a\xee\xa9\x09\x01\x4b\x9e\x9b\x66\x5e\xd6\x17\xa0\x4f\xe5\x5d\xd5\x8d\x7e\xd9\x47\x55\x14\x3b\xb8\x71\xf0\x11\xc8\x07\xec\xeb\xe6\x9f\x0d\x45\x6c\x4e\xea\xfb\x5f\x63\xde\x20\x5b\x19\x7d\x66\x19\xcd\x1e\xfc\x08\x67\xb5\xbb\x99\xcb\x52\x7d\x11\x3a\xe5\x48\x35\x24\x35\xb0\x3e\xa3\xd6\xeb\x97\xdf\xec\xee\xef\xb9\xdb\x92\x02\x79\x01\x83\xca\xf1\xa4\x08\x04\xd7\xf9\x14\x01\x8f\xf8\xf9\xaf\xee\x32\xa4\xcf\xf8\xd9\x7f\x80\x62\xd3\x1a\x8f\x9c\x01\x00\xca\xde\x9b\x12\x8e\x98\xaf\xd7\xc9\xf4\x18\xb3\xc8\x8f\x46\xc9\xef\x5f\xd3\x07\xff\x21\xdd\x5c\xdf\x99\xe0\xa0\xe3\xa3\xa0\x12\x4f\x1d\x84\x0f\x12\xcb\x44\xdf\xea\xc0\x94\x81\xdb\x1e\x84\x48\x7b\xcf\x3e\x0f\xed\xb5\xd0\xe7\xe8\x76\x9c\xb7\x8b\x09\x56\xc3\xbe\x36\x30\xf4\x10\x6c\x79\xab\xa3\x5d\xe8\xf3\x7b\x63\x3b\x49\x58\x12\xd8\x3b\x72\x02\x2c\xaf\x28\x42\x13\xae\x46\x41\x68\x43\x62\x16\x19\x26\x8a\x6c\xed\x27\xc4\x94\xbb\x7d\x96\x26\x32\x8a\xc2\x88\xd5\x50\x4d\x45\x8a\x17\x4f\xdb\xe2\x3e\x1c\x1c\xb0\x67\x53\x26\x93\x22\x8a\xe1\x63\x34\x1b\xfb\xa7\xc5\xd1\xdf\x9d\xb8\xef\xc8\x49\x2a\x89\x49\x85\xd6\xe3\xad\x43\xf5\xc4\x9b\xc3\xd5\x43\xf0\x75\x4f\xef\xa4\x5c\x9d\x4f\xa3\x06\x84\xcf\x4d\xb2\x23\xbb\x25\xf7\xfb\x4b\xfe\x47\xb7\x24\x8b\x0e\x09\x15\x71\xb7\xd5\x64\x51\xe4\x86\x29\x07\xb2\x25\xc0\xf5\x08\x4a\x40\x46\x51\x8c\x8d\x58\xa1\xb6\x5a\x58\x74\x10\xd8\x83\x14\x78\x49\xe6\x7c\x1e\x34\xe5\x0a\xe8\x7e\x4c\x5e\x13\xee\xea\xc6\x3f\x7c\x5c\x10\x2c\x1e\x3e\xa4\x08\x91\x28\x8a\xc8\x31\x6a\x3e\xd8\xdb\xcd\xbe\x01\x75\x15\x5d\xc0\x32\x1d\xa6\xcf\x4d\xd5\x00\x73\xed\x6f\xf1\xd2\xb1\xd5\xc0\x60\x93\xde\xc3\xb6\x35\xa0\xf9\xc1\x8c\xd4\x0d\xba\xcf\x3a\xbe\xfb\x02\xd3\x25\x9c\xd6\xe4\x1a\xbd\x6a\xea\x99\x31\x39\x32\x51\x16\x1c\x52\x2f\x7c\x0c\xef\xaa\x31\xad\x93\xfd\x30\x89\x0a\x76\x51\xdc\x0d\xd2\x07\x0c\xfa\xfa\xf0\x61\xe8\x92\xf8\xdb\x33\x9f\x1b\x22\x33\x02\xf3\xe2\xd8\x29\xbe\x32\xe2\xec\x99\x51\xfc\x77\x14\xe2\x0b\xfc\x91\x6f\xe2\xe0\xf6\x1e\x04\x13\x44\xe4\xc2\x83\xfa\xb4\x40\x61\x9e\x55\x57\x10\xb0\x32\xe7\xf4\x1d\x6e\x3e\xad\x5a\x5b\x9c\x5f\x4c\xdf\xca\x5a\x09\x9f\xa1\x25\x82\xc3\xdc\x4e\xad\xb2\xe1\xa0\x46\x52\x65\x7a\x46\xef\x7b\x2f\x2b\x30\x84\x61\x96\xc2\x01\x34\x12\x36\x21\x22\x0d\xf0\x40\x23\xc7\x18\x3e\xbd\x6e\xd7\x77\x4a\x84\x99\xe6\x57\x63\x7c\xb2\x09\xf3\xa0\x97\x4f\x4c\xb0\x15\x88\x55\x1c\xa9\x3f\x6e\x3a\x11\x0b\x90\xde\x8e\x1c\x80\xd8\x1e\x86\x87\x63\x57\x61\xba\x5c\xab\xc6\x6e\x72\x07\xc3\x31\xbe\x18\x40\x1c\x62\xd6\x98\x73\xd3\x58\x24\xdc\x68\xd0\xc0\xcf\x86\x49\xc7\xc6\x7e\x44\xf7\xc5\x48\x02\x40\x40\x82\xbb\xc0\x3e\x3f\xc8\x0a\x4b\xe7\xa0\x68\xd8\x40\xf5\x9c\x70\xd1\xc3\x2d\x25\x55\x44\x6e\x43\xc2\xac\x7e\x4b\x15\x2c\x2a\xf8\x6c\x65\x7e\x66\x39\x85\x7e\x0f\x13\xee\x9d\xe4\x98\xa4\xd1\x8e\xe8\xb5\x97\x49\xed\x5c\x74\x3c\xba\xfe\x4d\xb7\xd5\xea\xa5\x35\x29\x8c\x06\x58\x8a\xf4\x70\x4d\xd5\x9e\x14\x52\x13\x60\x8c\xfb\xa1\x11\xb1\x2f\x23\x40\x8c\xa8\xb6\x48\x0f\x26\x59\xd2\x14\x4a\x23\x52\x52\x75\xbf\xd9\x8a\xd5\x69\xe8\xa6\x24\xd0\xc4\xae\xaf\xc5\x33\x66\x28\x85\xea\xa1\x2f\xa9\x2e\xd3\x61\xca\x1f\xa5\xaa\xba\x5e\x61\x7a\x4a\xda\x0f\xf4\x8f\xcf\xf4\xac\x34\xf2\x7c\x17\x4d\xd1\xb6\xa6\xea\x90\x0a\x69\x76\x1d\xf4\x71\x26\x9f\xce\x6e\x0c\x63\xbe\x22\xba\xe5\xf3\x94\xfb\x79\xda\x27\x13\xbb\xe9\x78\x45\xd2\x30\xc9\xc1\x10\x87\xa8\xcb\x97\xd2\xad\x0d\xfc\x8c\x31\xad\x3e\x05\x16\x90\xbf\x18\x09\xc0\x20\x0d\x78\xf1\xd1\x47\xab\xa5\x95\xb9\x5b\x89\xfc\xad\xd9\x72\x1e\x5d\xe1\xa8\x1e\x48\xef\xf0\x6a\x53\x28\x1c\x16\xc7\xad\xed\x4d\x92\x51\x8b\x51\xe8\x50\xc2\x0b\x74\xb0\x48\x52\x9f\xd7\x94\x1b\xf0\x4d\xc0\x0b\xc1\xc8\xf4\x57\x1c\x0a\xee\xc5\xb1\x4b\xa4\x51\x72\x85\xdc\x2d\x29\x02\x73\xb6\xb6\xa8\x8a\xbe\x58\xcc\x98\x19\x91\xbd\xa7\x7a\xef\x08\x87\x4b\xa4\x6e\x08\x57\xc3\xc5\xe8\x8f\x58\x13\x31\xa5\x58\x2c\x02\x83\x4d\xfb\x53\xc9\x98\x3a\x44\x6f\x68\xd5\x3f\xd7\x45\x6b\xd4\x67\xe4\xea\x4c\x2e\x50\x17\x75\xd5\xfa\x03\x62\xd4\x99\xb9\x12\x49\x24\x30\x57\xb7\x77\x4c\xd1\xa5\xad\xd5\x2e\x64\x93\x74\x53\xff\x39\x8c\xfa\x73\xe2\x7c\x4e\x00\xc8\x92\x84\xb3\x0b\x13\xa0\x54\x19\xe7\x3c\x73\x9d\xca\x04\x3d\xf5\xfb\x2b\x89\xdc\x66\xa2\xd5\xd9\x7f\x81\xf0\x6c\x5a\x5b\xb9\x0e\x8e\xa7\x8d\x77\x5f\x28\x8e\x9b\xa7\x87\xc8\xc8\xbb\xa8\x77\xef\xc6\x1f\xf7\x6a\xb6\xbc\xca\x5c\x5e\x07\x68\x81\x18\x25\x28\xe4\xc1\xe7\x8a\x54\x4c\xc0\x3c\xde\xa6\x09\xec\x31\x2f\x93\x3a\x00\xd5\x4b\x66\x6e\x9a\x46\x7a\x04\xbe\xa0\x27\x83\x21\x4b\x13\x5d\xed\x0b\x28\x42\xaa\xcf\x5b\xc4\xf0\xc5\x0b\x96\x52\xd1\x4d\x59\x60\xf4\xc9\xba\xe5\x76\x6b\x8b\xd9\xd9\xd8\x7b\xa3\xde\xa0\x8a\xcb\x3d\xec\xd3\xf1\x90\x09\x14\xf9\xe3\xd4\xdf\x0b\xd4\x5a\xe2\x8e\x44\xb4\x68\x14\x26\xdf\x17\x40\x72\x50\xef\x7f\x7d\x1d\x5b\x14\x46\x5c\xcd\x52\x17\x15\x52\x84\x08\xbd\xd8\x4f\x18\x5e\x44\x50\xd7\x8e\x78\xea\xfd\x1f\x77\xa3\xe6\x44\x12\x34\xdd\xcc\x16\xba\x98\xa9\x59\xa3\xed\x02\x30\x0f\x30\xbb\xbd\x2e\x9d\xec\xb5\xb6\x9c\x53\x6d\x1f\xc0\x91\xf7\xc6\x4f\x18\x17\x79\xf0\x60\xff\xf1\x97\xdf\xfc\x85\xec\x6a\xad\x59\xae\x20\x01\x1f\x77\x74\xd2\xd7\x0b\xf7\x29\x5b\xe6\xc9\xa3\xf4\x00\x6a\x76\x9f\x73\x80\x40\xb4\x35\xfa\x36\xc7\x18\xae\x5e\x9b\x38\xfb\xf7\x2b\x8c\x55\x47\x63\xbc\xb5\x95\x56\x14\x74\xc5\xcd\x5a\xfa\xba\xc6\xb6\x24\xde\x7c\xe3\xaa\x6e\x8b\xf9\xd5\x2f\x45\xbb\xe0\x23\x70\x14\xa9\x97\xd9\xcf\x34\xcc\xc5\x71\xcc\xb2\x70\x03\x7f\x45\x85\x53\xaa\xef\xf2\x11\xe5\xf4\x79\x9f\xd7\x91\xef\x0c\xe5\x89\xdc\xd0\x9b\xc0\x9a\x6d\xda\x89\x37\x5e\x37\xac\x49\xbb\xef\xab\x26\x2d\xec\x80\x6e\xa4\xd2\x2c\x11\x0e\x75\x14\x6e\x0f\x0f\x1d\xc6\x59\x87\xfe\xb8\x91\x04\x81\xf7\x99\x93\xb5\x3b\x45\x31\x22\xf9\x8f\xf8\x12\x9d\x3a\x6e\xff\x46\x10\x92\x10\xa5\xee\x64\xa1\x1f\x7d\xd5\x53\x49\x77\xa2\x32\x6f\xf1\xd3\xa9\xf7\x3d\x27\x05\x00\x1d\x8f\xe9\xad\x27\x8d\x77\xaa\xff\xda\xef\xdd\x51\x60\x5d\xed\xd4\x27\xfd\x17\x2c\xec\xb4\xe3\xd7\xe2\x58\x47\x01\x83\x11\xdc\x5a\xa4\xc3\xbd\xcf\xfd\xe0\x37\xa5\x9b\x2d\xe9\x30\x4f\xe4\x7e\x2b\x2e\x31\x4e\x08\x78\x90\x44\x93\x72\xc2\xd7\xbf\x6f\xf3\x43\x8a\xfd\xc4\x5b\xaf\x6b\xe4\xe0\xdc\x42\x8e\xc0\xc9\x81\x9e\xd6\x6d\xfd\x32\x1d\x66\x7a\x82\x83\x65\x2f\xd2\x11\x00\x46\x5c\x05\x36\x63\x84\xb8\x6e\x6b\x30\xb5\xea\xb2\x0c\x1e\x1c\x36\x54\x11\xb0\x2c\x2e\x0c\xda\xfe\xd0\x3a\xa3\x1b\xf2\xbc\x08\xa4\x82\xbb\x75\xb8\x89\x68\x08\x2e\xbc\x9f\x70\xa7\xfe\xcb\x21\x0d\x13\x17\x8d\xd4\x0a\x9f\x4e\x7c\xee\xa2\x3e\xfb\xdd\xb8\x22\xc8\xad\x00\xc7\x1c\xb5\xbc\x17\xe0\xca\x79\x45\x78\xaf\xa5\xb6\xad\xf2\xc9\xc2\xe3\x99\x72\x44\xc8\xe3\x4a\xe0\x48\x3b\x2b\xf6\xa9\xb4\x64\xe4\x3f\x0d\x44\x25\xd1\xa6\x88\x9a\x5c\xab\x7f\xa6\xa2\x78\xdf\xf9\x49\xbf\x11\x37\x2f\x32\x4a\xf2\x1e\x80\x27\x48\x5a\x7b\x84\x8b\xdb\xce\x0b\x0b\x91\x9f\xba\x6e\xde\xef\xb8\x87\x43\xb9\xc5\xd4\x18\x19\xfd\xe2\xfe\x48\xd3\x14\xd5\x9e\xc4\x37\x49\x2f\x62\xaf\xcc\x21\xd2\xb1\xd4\x2b\x3f\x4e\x41\x83\x22\x33\xae\x08\x38\xf4\xe2\xc6\x2b\x7f\x72\xd3\xd9\xa1\x00\x05\x36\x38\xf7\xbc\xa5\xe1\x25\xe4\x4a\x66\xc3\x0b\x9e\x8d\xe0\xb8\x08\x91\x19\x29\xd5\x2f\x66\x67\x9c\x93\x2e\xbd\x52\x5c\x9d\x53\x31\x7d\xf0\x90\x0c\x83\x49\x87\xe0\x29\xee\x8d\xed\x7b\x5b\xc1\x9a\xa8\xdb\x56\xcf\x16\x3e\xbd\x8e\x65\x58\x40\x06\xf0\x61\xe3\xb8\xdc\x42\xa7\x0d\xa8\x9d\x92\x16\xf8\x85\x02\x06\x07\x55\x2e\x69\x19\xf7\xb0\xb3\xcf\xbc\x55\x0d\x3f\x9c\xeb\xa2\xec\x7c\xe8\x1e\xd2\x7b\x66\x5b\x93\x12\x84\x73\x38\x4c\x50\x1e\x9f\x89\x8b\x3a\x99\xd9\x67\x61\xdb\xa1\x62\x97\x6c\xf0\xe9\xbd\x24\xd2\x2b\x45\x7a\xbf\x9e\x3d\x92\x8a\x26\xfe\x3b\x92\x3f\x9f\x06\x4e\x00\xb3\xc4\x3c\xca\x58\x4c\x94\x84\x81\x0b\xc0\xbf\x22\x8e\x57\x0a\x94\xde\xce\x8d\x6c\x52\x7c\x83\x78\xba\x8e\x35\x44\x7c\xdf\x27\x53\x5e\x11\x48\x96\xc8\xb4\x5b\x1d\x77\x86\x83\x0d\x1e\x0e\xfd\xc5\xc7\xeb\xca\x2e\x8a\x79\x3b\x10\x13\x1b\x8e\xed\x88\xe8\x13\x91\x0b\xb9\x1c\x21\xcd\xd5\xaa\x81\x04\xc5\xd1\x82\x24\xcf\xfa\x7c\x6f\x37\xb7\x9c\xaa\x1d\xd3\x0f\xf1\xd6\xef\xeb\x6f\x1a\x3e\x6c\x57\x06\x6e\x3b\x11\xb4\xe9\x9e\x04\xbd\xcc\x5c\xba\x8c\xd4\xab\x16\x15\x23\x26\x07\xc7\x70\x8a\xe6\xc4\x3a\x0e\x0e\x54\x86\x40\x47\x99\x3a\xec\x63\x1d\xb1\xdc\x50\x51\x44\x0f\x1f\xa5\xa9\x6b\xe3\xfa\x5a\xdd\x9f\x57\x80\x8a\xc1\x41\x7f\xdb\x41\xf7\x1a\xed\x5b\xae\xe6\xe1\x43\xea\x2b\x08\x8f\x9e\xb5\x0b\xcf\x0c\x31\x9d\x49\xbd\xfc\x97\x00\x39\x93\xd5\xfb\x28\x4c\xff\x4d\x88\xef\xae\x57\x6d\x10\x77\x0e\x44\x20\x45\x3d\x9f\x53\x74\x08\xcd\x49\x5c\x52\x62\xab\x1d\xc6\xef\xc0\xcb\x2d\x7a\x52\x54\x32\x42\xc3\x8d\xc6\x86\xf9\xf4\x8f\x8e\xe2\x6a\x8e\x03\xd0\xaf\x2f\xe2\x63\xb8\x3c\x01\x0d\x40\x98\xee\x63\x74\xb9\xd8\x05\x4e\x27\x24\x0d\x98\x80\xe3\xc4\xee\xdf\xc0\x60\x2f\x8c\x80\x54\x5c\xe0\xd7\xc9\x87\x04\x4c\x43\xbb\x59\xbc\x81\x6a\x22\xab\xdb\xbf\xb9\x17\x38\xad\xae\x1c\xa6\x79\x73\x7f\xf1\x86\x08\x73\xed\xa9\x6d\x57\x24\xdf\x44\xd5\xb8\xca\x40\xd7\xe8\x89\x88\xa8\xeb\x09\x9e\x0b\x3d\x8e\xb5\xfe\xe3\xdc\x90\x17\x03\x46\x4a\x8b\x72\x69\xf0\x3f\x67\x53\x5a\x85\x5c\x6b\xbd\x31\xfa\x73\x9d\x9b\xf7\xf5\xb4\x7b\xe4\xda\x3a\x1c\xbb\x98\x88\x6f\x93\x61\x04\x0d\x72\x57\xac\xcd\xf6\x66\x73\x3d\x6f\x4d\x13\x70\x51\xc9\x93\xac\xad\x11\x79\x44\x46\x47\xb3\xc3\x12\x3b\xf8\xa8\x21\x9a\x8e\x3d\x0c\xec\xc8\x89\xff\x64\xe3\x08\x3a\x38\x01\x73\x11\x40\xce\x3c\xce\x1c\x94\x1a\xbb\xf1\x0d\xc7\x54\x72\xf0\x87\xf2\x38\xc1\x6d\xad\xf8\xf4\xf7\x0d\xd0\xc7\x74\xd0\xa7\x5d\x51\x6b\xe3\xa7\x22\x5e\x15\x02\xc0\x0e\x54\xbf\x21\x0c\x4d\x75\x5e\x5c\x75\x32\x88\x2f\x0a\x95\x77\xc8\x5e\x68\x83\x44\xc7\x5a\x5e\xce\xbd\xf9\x56\xdf\xae\xd0\x73\x13\xe0\x60\x67\xf5\x0a\x20\xb3\xa1\x65\x5b\xab\x95\x69\x76\xbd\xab\x04\x91\x18\x54\xc5\x9c\x18\x55\xd6\xb6\x0d\x02\x16\xb9\x72\x09\x55\x1c\x6e\xbd\x0d\xc2\xb8\x1a\xc2\xae\xd4\x94\x42\xd9\x77\x07\x43\xe2\x82\xbb\x05\xb8\x38\xcf\x8b\xaa\xb0\xe0\xbd\x42\xe2\x80\x55\xc5\x72\x69\xf2\x42\xb7\x86\xfd\xba\xd1\x7d\x06\xbe\xbe\xbe\x4e\x3d\xbd\xb0\x2b\x19\xd6\x93\x45\x8a\x4d\x30\x5e\x81\x59\x4e\xe0\x09\x24\xfe\x4e\x72\x1e\xc7\x58\x09\xa4\x7a\xf7\x0f\xe3\x28\x68\xdf\x0b\x1c\xa0\xa0\x36\xe8\x4a\x86\xbe\x17\x21\xec\x5f\xd6\xe4\x23\xa3\xe1\x35\x1d\x62\x59\xcf\x28\x2e\x1d\x42\x8b\x12\x29\x18\xdd\x69\x01\x0c\xf2\xdf\xf0\xbb\x44\xca\x42\x64\x8c\x7a\xf5\x6f\x44\xf1\xc2\xa7\xa9\x2a\x1c\xcb\x05\x84\xc5\x96\xc2\xde\x59\x27\x99\x3e\xc6\xd9\xf4\xcd\x21\xc5\x89\x22\x8a\xf1\xb6\x01\x77\xdd\xfb\x12\x57\x85\xdb\xe4\x6f\x0f\xc4\x00\xb0\xee\xf0\x5b\x38\x99\x7a\x20\xd4\xae\xb9\x99\x7c\x51\xc2\x57\xc4\x00\x40\xbb\xb8\x1c\x51\x34\x33\x93\x4d\x57\xe4\xfa\x1a\xae\x81\x11\xe7\xbe\xfc\x13\xc0\x0d\x90\x89\xc2\xf0\x65\xe2\x61\xa5\x03\x17\x49\x7d\xe0\x80\x5e\xfc\xbd\xa3\xb2\xe0\x33\xc8\xb8\x4c\x20\xb6\x08\xbb\x06\xfe\xa6\x97\x6e\x9f\x77\x1d\x1b\xfd\x6d\x11\xf4\x7b\x64\x2b\x8a\x34\xfe\xee\xab\x38\xff\x82\x7c\x00\x0b\x2a\x0e\x8a\xdf\x2b\xe9\x87\xc9\x89\x89\xc4\xef\xc4\xee\x00\xdd\x0d\x55\x7e\x72\x2f\x1e\x3e\x54\x4d\xb3\x66\x6c\x1a\x1e\x8b\x40\x11\xbb\xb3\x73\x2c\xcd\x7b\xd3\xc3\x76\x6a\x16\x39\xc0\xc8\x36\xcf\xca\xe3\xe3\xdd\xdd\xa7\xc9\xac\x61\xa9\xd0\x41\x44\x88\x38\x40\x2f\x56\x70\xd6\x23\x64\x5a\xcf\x71\xa4\x5f\x08\xee\xe3\x6a\x65\xe4\x38\xd2\x92\x82\x38\xc5\xc7\x09\x0e\x1f\x6f\x2f\xa1\x3f\xe5\x2a\x40\xa2\x99\xb1\x8d\x70\x14\x6b\x70\xe2\xd0\x0d\x94\xb2\x31\x03\xed\x65\xcb\x56\x08\xac\x9b\xe2\xad\x41\x9d\x03\xce\xee\x17\x1a\x72\x81\x21\xb6\x20\xd7\x40\x3b\x34\x38\xa2\x81\xcf\xe6\x8c\x74\x66\x45\x13\x9c\x3a\xbd\x0c\xcc\xe9\xb3\xa0\x24\x8d\x84\xab\x3b\x59\xb7\x98\xed\x1a\x5b\xbf\x52\x17\x06\x54\x74\x30\xfe\xb0\xa3\x79\xfc\x8e\x07\xef\x28\x90\xfa\xd9\x20\x58\x98\x1e\xdc\x13\x80\x1b\x03\xb2\x9e\x52\xd0\x0e\x0c\x4c\x1f\xdd\x08\xa0\xd4\x4c\x32\x7a\x21\x07\x6e\x21\x15\xb8\x4a\x77\x1f\x69\x2a\xc2\x0b\x8f\x5b\x3d\x22\x1d\x99\x22\x2d\xb0\x37\x87\xf6\x14\x42\xfa\xe2\x4b\xde\x4a\x61\xbc\x9c\x8b\x8d\x1e\xe2\xbf\xb1\xca\x92\x57\x0e\xdd\x5c\xc4\x75\x3d\x2f\xf5\xa9\x02\x33\x7b\x71\xee\x98\x0c\xd7\x17\xbc\x39\x74\xab\xc3\x4d\x4a\x4a\x4b\x5f\x0d\xdc\x9f\x61\x17\xce\x8b\x86\x38\x8d\xd8\x43\x37\x2c\xea\x48\xa4\x27\xde\x80\x2b\x11\x11\xb3\xf0\x4c\xf0\xd7\xa3\x88\x01\x10\x27\xa4\xe4\x00\x78\xc7\xc4\x52\xc2\x25\xc9\xa1\x00\x5c\x01\x8e\xc5\xc3\x36\xfe\x8f\x50\x96\xdb\x09\xc9\xa7\xd1\x91\x88\xc9\xf9\xf3\xd4\x22\x9e\x8b\xe0\x15\x4b\x64\xc3\xc9\x30\xd8\xab\xbb\x27\xe5\xee\xfc\x29\x34\x2f\x50\x61\x74\x45\xc4\x4f\x78\x23\x85\xf1\xf7\xbe\xef\x8a\x52\x3d\xe3\x43\x61\x68\x3e\x4f\x36\xb1\x64\x77\xc4\xde\x8d\xdd\x33\xfb\x91\x49\xc9\x19\x72\x44\x9e\x83\x23\x76\x7b\xbc\x05\xa0\x14\x2c\xb1\xd6\xbe\x92\xd2\x7a\x25\xfd\x18\x3a\x0f\x6f\xd3\x85\xa4\x82\x07\x43\x55\x91\xfe\x23\x5c\x53\x1d\xbd\x88\x47\xb9\x42\x8e\x15\xba\xc4\xd9\xc1\xf1\xc4\x78\x38\xaf\x98\x6f\x65\x71\x8a\x63\xbb\xd0\x69\x06\xb7\xde\x5d\x32\x55\x84\x32\xe9\x03\xcb\x38\xa1\x32\xa6\x8a\x99\xad\x6d\x5b\x2f\xc5\xfe\xeb\x82\x16\xda\xb2\xc8\xcd\x8b\xfa\xa2\x9a\x52\x27\x70\xfa\x81\x84\xc2\xbb\x9f\x57\xfe\x0d\x2c\x48\x78\xf3\x9e\x20\xc1\xe8\x2d\x2d\x20\xbc\x77\x52\xf0\xeb\x6a\xaa\x84\x9c\x48\x0e\xa1\x37\xfc\xfa\xed\xba\x8d\xdf\xe3\x72\xfb\xf7\x5c\xbb\x2c\x42\x4d\xa8\x9b\x04\x3e\x11\xe7\x4d\x7a\x03\xfd\x77\xac\x7c\xbc\x44\xc1\xed\xe9\x93\x16\x25\xba\x23\x20\x99\xda\x53\x09\x1f\xd0\xef\x8a\x00\x86\x46\xf7\x45\x12\xc2\xd7\x7f\xf3\x90\x19\xa4\x27\xe8\xb0\x9b\x8d\x37\xa5\xac\x81\x78\xc0\x1b\x4f\x7b\x43\x5c\x1c\x67\xa2\xb0\x68\xd0\x83\x52\x0b\x8d\xe9\x10\xd9\x0f\x07\x92\x85\xa1\x87\x62\xee\xaf\xff\xfb\x68\x40\x18\x46\x94\x18\x10\x75\xa8\x91\xc0\x11\x24\x54\x75\x77\x37\xd0\xd4\xd4\x07\x36\x1a\x40\x82\xb6\x08\x70\x0c\xf5\x6a\xc0\x04\xa6\x37\x58\x33\x81\x82\x18\xf3\xb8\x05\x23\x23\x3a\x17\x4d\x34\xdb\x59\xf1\xfd\x53\xee\x13\x8f\xb3\xa7\x33\xba\x69\xa9\x37\x82\xcd\x4f\xea\x14\x1d\x4e\xfb\x56\x54\xad\x69\x10\xe7\x7a\xff\x8b\xe4\x1d\x7b\x2d\x26\x5b\x47\xcc\xd2\xeb\x3c\x5a\xdb\xd7\x39\xc2\x4d\xbe\xa6\x4a\x25\x44\x0c\x9a\x74\x7a\x1a\xde\xd4\x33\x92\x70\x93\xc6\x41\x6e\x0c\xf5\xfb\x5e\xb8\x4a\x42\x1f\x1c\x01\xed\x59\x08\x52\x82\x12\x8a\x49\x59\x5f\x4c\xd5\x57\x7b\x7b\x48\x06\x6c\x3b\x55\x8f\xf1\xc7\x64\xa2\x5e\x50\x80\x07\x7c\x11\x81\x48\x7d\xb9\xb7\xc7\x15\x13\x92\x87\x35\x39\xdc\x4f\x94\xd0\x6c\x55\xae\x4f\x0b\xc8\xb7\xf7\xbc\x2c\xaa\x56\x7d\x67\xca\xb9\x63\xde\xd0\xcb\x7d\x65\x9a\x65\x61\x6d\x51\x57\x63\xf8\x7c\xd1\xb6\xab\xe9\x64\x72\x52\x16\x55\x6e\x8b\xd3\x4a\x97\x60\x1b\x9a\xc0\x45\x39\x5e\x2d\x56\x93\xc7\x7b\x7b\xdf\x4c\xf6\xfe\x32\xf9\xf8\x4f\x37\x8c\xdd\xdc\x94\xfa\x6a\x22\x55\x82\xf0\xa4\xb3\xbd\x46\x92\x03\x69\x0b\xe9\xb0\x38\xbf\xec\xd5\x03\x43\xa1\x63\x16\x8f\xd4\x14\xfe\x81\x79\xed\x65\xa7\x83\xa6\x32\x15\xd3\x23\x7a\x69\x2e\xdb\x51\xac\xbf\x60\xd2\x53\xaf\x09\x9d\x94\x03\xa1\xa9\x30\xb4\x8e\x47\x53\x70\x8a\x3d\xca\x32\xd8\x0b\xfe\x63\xae\x32\x68\x37\x90\x0f\xe0\xb5\x4a\xf9\x7c\xe4\xf2\x57\xd0\x89\xbc\x9e\xc1\xa5\x49\x28\x22\x2f\x51\x1f\x3a\x50\x19\x14\xe0\x4c\x99\xe8\xfd\x75\x5b\x71\x2c\xc1\xe5\xc9\xca\x01\xcf\xdc\x25\x6d\xaa\xfc\xf9\xa2\x28\xf3\xc1\xe6\x0a\xd0\x06\x99\x85\x24\x05\xd0\x81\x31\x67\x95\x81\x08\x9e\x28\xdd\xaf\x47\x06\x2a\xde\xbe\x53\x4f\xc6\xfb\x23\x8f\xfe\xfc\xe5\xf8\x72\x14\x43\x41\x87\x94\x3f\x32\x69\x22\xd7\x39\x69\x74\x5e\xd4\xa4\x92\x1d\x64\x99\x93\x12\x1c\xf3\x88\xe0\xcd\x4f\x55\xe6\xfa\xe5\x48\x0c\xe0\x41\x0d\xdd\x09\xe2\xfc\x26\xae\x86\xb7\x90\x9c\x10\x7a\x1b\x20\x4c\xb3\xd0\xd1\x37\x80\xfc\x00\xce\xfb\x8c\x18\x46\xc9\x2b\x97\xfa\x0c\x5d\x94\x61\xec\x34\x5f\xe4\xb8\x03\xba\xc4\x04\x00\x69\xa4\x5e\xbf\xdc\xdf\x13\xed\xd7\xab\xf6\x1d\x7c\x64\xd8\x02\x60\xe9\x67\x68\x3d\x0e\xbd\x03\xc6\x78\xc5\x7c\xb2\x2d\x72\x48\x4f\xe8\x44\x25\xf6\xf1\xf3\x69\x78\x96\xba\x39\x43\x74\x31\x2e\x81\x35\x0e\x08\xd4\xda\xbd\x87\x11\x2d\x65\x19\x98\x1e\x5c\x78\x5f\x71\x70\x05\x11\x1d\x7f\x11\xde\xde\x07\x43\x0c\xfd\xf6\x3d\xf7\x39\x9a\x74\x45\xdb\x75\xa9\x8b\xaa\xd5\x85\xeb\x7a\x6b\x69\xbd\x50\x71\x7f\x62\x66\xf5\x92\x30\x15\xdc\x62\xde\x32\x77\x9f\xbc\xf3\x9f\xfa\x4d\xc8\x1e\xb8\x19\x66\x9a\x89\x77\x26\xb4\x97\xc9\xc1\xc1\x93\x7f\xa7\x6f\xa2\x1a\x0e\xb8\x8e\x9b\xe1\x80\xd1\x4d\xdd\x69\xac\xea\x1c\x04\xe1\x91\x72\x6c\x2e\xfc\xb5\x7d\x0f\xa2\xda\xbf\xc3\xf0\x5f\x61\xcd\x5e\x35\xe3\xf0\x62\xb3\x8d\xc4\x95\xf9\x57\x80\x8c\xa9\x32\xf7\xf9\x9f\x82\xcb\x05\xa2\xe8\x98\x94\x67\x3d\x0d\xf7\x31\x7d\xfd\x1a\x08\x6a\x3e\x54\xc5\xfd\x92\x38\xbe\x1b\x84\x9c\xcd\x83\xdf\x88\xc9\xec\xa1\x45\x47\x90\x74\x0d\xba\x50\x61\xbc\x6b\x1c\xff\x1a\x82\x94\xd0\x57\xf6\xd4\xb4\x13\x6b\x5a\x19\x9b\x4a\xf9\xe6\x46\x3e\xd9\x1c\xa0\xbd\xf8\x00\xd4\x0d\xa9\xe7\xaa\x38\xe5\x5c\x15\xa7\x9a\x0b\x3f\x1f\x27\xee\x2f\x49\xc4\xcf\x2b\x01\x51\x08\x36\x0d\xf0\x84\x12\xbd\xd3\x8d\x01\xb6\x92\x36\xa9\xe0\x25\x49\xd6\x82\xe1\x9e\x9a\xf6\x99\xef\xb1\x6b\xd6\xb6\x4d\x37\x74\x2c\x86\x8f\x77\xcd\xf5\x4e\x71\xd2\xc5\x67\x65\x99\x76\xa8\xac\x2f\x4c\x33\xd3\xd6\x50\x91\xbf\x37\xfa\x24\xe4\x26\x47\xb4\xbf\x62\xae\xea\x0a\xe3\xee\x7c\x4e\x76\xec\x38\x4e\x0e\x22\xc3\x5c\x5f\x0b\x53\xf4\xaf\x6f\xbe\x7f\x51\xcf\x3a\x99\x6b\x29\x78\x01\x80\xb0\xdb\xfa\x7b\xd7\x36\x04\x2f\x0c\x45\xa4\x7a\x38\x69\x70\xc8\x92\x1c\x36\x28\xa8\x0f\xa2\xc3\x08\x5e\xd3\x63\x77\x6e\x49\x25\x4c\x1b\xfe\xd0\x9f\x65\x35\xf5\x07\xbc\xc7\x6e\xba\x31\xc7\x5c\xd0\x1f\x05\xea\x11\x85\xe4\xf7\x1d\x96\x04\xf4\x5a\xaa\xc1\x93\x78\x03\x7b\x6b\xa2\xa7\x6e\xea\x2a\xac\xf3\xd3\xf2\x3c\xf5\x68\xdf\x11\x38\x41\x6c\xaf\x98\x24\xed\x08\x34\xca\x08\x10\x3c\xd2\x80\xf5\x8f\xe4\x93\x53\x56\xc9\x21\x44\x33\xd9\xe9\x7c\xd4\x77\xac\x8d\xa9\x6c\x51\xe5\xb0\x37\xfa\xe7\x1a\x92\xac\x57\xbb\x90\x04\x08\x68\x40\xd8\xf0\x8c\x47\x0d\xc8\x9a\x17\x46\xb8\x12\xb4\x75\x98\xd1\xa4\x3f\x5e\x29\x42\xd8\x3f\x61\xe6\xa7\x7e\xae\x52\x5f\x9a\x7e\x3a\x2c\x16\x53\x52\xbf\x20\xd6\xff\xe0\x73\x7a\x88\x34\x06\xae\xff\x3f\x40\x3e\x51\xce\xb1\xc7\x39\xdc\x70\xe3\x0f\x54\x53\xd5\xed\xc5\xa2\x68\xc3\x24\xc0\xf2\x84\x0f\x39\x4f\x4b\x02\x25\xc0\x73\xcf\x98\x50\x03\x3a\x9e\xfe\xc3\xa3\x62\x67\xe7\x58\x58\x24\xb8\x8f\x61\x2d\xd0\xa9\xf1\x52\x26\x99\x72\x7f\x49\x1b\xee\xb7\xa8\x36\x92\xeb\x70\x6a\x5a\x76\xaa\x56\xad\xbb\xfb\x81\x58\x0f\x1e\xec\xef\x7d\xfd\x97\xbd\xa1\xd0\xf5\x7d\xca\x29\x0f\x7a\x3e\x8a\xea\x87\x80\x17\xbb\xaa\x2b\x48\x1e\x2c\x63\xfb\x41\x53\x4f\x85\x11\xec\xd1\x8f\xe8\x38\xb1\x9c\x78\xd7\x56\x98\xb8\xb0\x9e\xe2\xe0\x74\xd3\x4e\xe3\xe2\x7b\xb2\x45\x3e\x42\x8e\xba\x73\xa2\xe1\xcd\x89\x66\xd2\xf8\x9b\x1e\x56\x26\xce\xdd\x87\x5c\x4f\xc0\xcf\xf3\x9a\x11\x8c\x8c\xf3\xb1\x94\xcc\x4c\x75\x26\xca\x27\x9d\x05\x3e\x0a\x2c\xfe\xc8\x86\x9f\xac\xdb\xd6\xfd\x04\xbe\x2e\xb8\x4a\x34\xc6\x1a\x84\x75\x65\x94\xa3\x4a\xbd\x7e\xf9\xd5\xee\x37\xa1\x56\xcc\x1b\x8f\x6f\x31\xa1\x21\xb0\xf9\x45\xa5\xdc\x15\x83\x0d\x15\x16\x20\x1e\xb0\x76\x2c\x9a\xaf\x21\xa6\x18\xd8\x40\x8f\xc0\xc5\x19\xe1\x98\x0f\x10\xb4\xa8\x97\x96\x65\xae\xf6\x2c\xbe\xfa\x04\xf9\x96\xf6\xc1\x50\x1f\x9e\xa9\xc4\x2a\xd8\x43\xfd\x3a\xa9\x95\xa5\x5a\xf2\x3b\x9f\xb4\xfa\xa4\xb3\xd7\xb7\xef\xf9\x3b\xa8\x17\xc0\xb4\x87\xc0\x0b\x1b\x53\x58\xee\xd8\xc8\x04\x53\xbd\x84\x88\xaf\xee\xe9\x02\xbe\x83\x50\x34\xc2\x8e\xbf\xfb\xa6\x4a\x68\xee\xc6\xeb\x42\x7e\x20\x58\x4a\x3a\xf7\xac\x4e\x91\x1a\xd8\x4d\xe7\xd8\xd6\xeb\x66\xe6\xc9\xd8\xe4\xc3\xc5\xce\xe4\x54\x0d\x6f\xd7\x84\x9f\x42\x56\x4d\xa2\x52\xc8\x82\xf7\xa4\xb8\xf3\x77\xc4\xd3\x70\x24\xe3\xb2\x07\x1b\x98\x53\xe0\x5d\x24\x79\x86\x54\xc0\x0b\xe6\xf5\xf9\x78\x46\xc5\x80\xb7\x82\x4c\xf1\x20\x28\xcd\x8b\xca\x11\x63\x00\xed\x4b\x52\x04\xc1\xf4\x7b\xc8\x1b\x1f\xb2\xe6\x53\x2d\xe2\xe8\x90\x19\x62\xb9\xa3\xdb\xf9\xa7\xfe\x62\xe8\x0c\xca\x67\x79\xc4\x2b\x13\xeb\xeb\x1f\xe1\xfd\xf8\x5e\xeb\x32\x65\x7c\xc1\x91\x46\x6b\x53\x93\x62\x6e\xe4\x7e\xa0\x9e\x08\x65\x71\x90\xb6\x9a\x79\x3d\x5b\x83\xb0\xc9\x60\xb1\x40\xa5\xae\x51\x6c\xbd\x76\x4c\xbc\x6e\x8c\xbe\x46\x4a\x34\xfc\x6c\x52\x6c\x16\xb3\x1c\x09\xff\x2f\x88\x59\xe8\x9d\xf5\xaf\x88\x59\x3f\xf6\x34\xfc\xe9\x62\x16\x47\xf0\x2d\x0a\x7b\x74\xc7\x6d\x9a\x02\x7f\x6c\x14\xba\xe8\x7b\xce\xcf\x3e\xaf\x9b\x6c\xaa\xb2\x45\xbb\x2c\x5f\xd5\x0d\x7a\x90\x64\xb3\x52\x5b\x0b\x69\xc2\xdd\x1f\x3f\x50\x4c\xa8\xf7\x01\x8e\x87\x74\xab\xd4\x86\x07\x03\x45\xb7\xaa\x6e\x2f\x97\xe5\xbf\x20\xbd\x89\x50\xac\xff\x73\xd2\x1b\xf6\xde\x09\x26\x9f\x26\xcf\x48\x2e\x8b\xbe\x15\x94\xe0\x55\x71\x89\xcb\x46\xfd\xd7\xb3\x05\x4e\x93\x14\x81\xee\xe4\x9f\xba\xe2\x90\xc8\x5a\xd1\x4d\x01\x79\x67\xb2\xec\x34\x27\xc7\x7f\x93\xf4\x71\xe8\x79\x60\xa6\x16\xf8\x59\x1a\xb5\xed\x27\x2d\xe5\xeb\xe3\x4e\xfd\xeb\x82\x44\xb7\x23\xb2\x1b\x5d\x67\x77\x9a\x4b\xe6\xd1\xf4\x09\x64\xfd\x67\x3e\xad\x27\xeb\x63\x47\xd0\x82\xfd\xbd\xd0\x36\xe2\x41\xf4\x09\x68\xcf\x09\x2a\x29\xd0\x39\xe2\x59\x53\xf0\x02\x4e\x71\xbf\x68\xcc\xdc\x83\x8b\xc2\x13\xee\x91\x87\x10\xdd\xdd\x4f\xd9\xcd\xde\x04\x7c\xaf\x5f\x7e\xb3\x83\x4f\x48\x0f\x59\x19\x6b\xc9\x46\xcf\x6a\xce\xa2\xa2\x1f\xa7\x4d\xbd\x5e\x71\x46\xeb\xa2\xd2\xb3\xd9\xba\xd1\xad\xd9\xbe\x17\xf3\xa0\x52\xc9\x19\x19\x8e\x04\x50\x7b\x50\x82\xc2\x2c\xdd\x36\x81\x10\x49\x81\x2a\x58\xa2\x12\x01\x92\xfd\x69\x90\xb9\xa9\x08\x02\x5e\x9b\xaa\xed\x03\x6e\xdf\xea\xbc\xf2\x3d\x81\xd9\x93\x11\xcd\x42\xfa\x8b\xdc\x9e\x6f\x3a\x66\xfa\xed\x7b\x5b\x19\xcf\x3f\x90\xcd\xac\x31\x3a\x7f\x5b\x95\x57\xf8\x6b\xa9\x2f\xbf\x87\x9b\x01\x7f\xce\x4c\x59\xbe\x5b\xe9\x19\x24\x58\xe4\x07\x3f\x12\x98\x26\x7e\x5e\x5f\xbc\x5b\xe9\x8a\xde\xd6\x65\xf8\xb1\xb6\xe6\x8d\x5e\xe1\xdf\x10\x22\xf7\x2d\x64\xd0\xe3\x92\x95\x13\x61\x5f\xe6\x45\xeb\xf6\x50\xb6\x7d\xef\xb8\x93\x36\x33\x25\x24\x70\xe5\xc4\xd7\xf8\x31\x81\x2a\xf6\xde\xc4\x70\x0d\xb8\x5b\xf8\xe8\x43\xfb\xa1\xf9\x50\x7d\x98\x1f\x4f\x4e\x6f\x51\x6a\xe6\xf9\x73\xf7\xc5\xc6\x2c\x7c\xe0\xad\xe0\x4a\x18\xcb\xd1\x65\xb3\x75\x33\x72\xcf\x7e\xff\x7d\xa4\x3e\x8e\xd4\xbc\xa8\x74\x09\x12\x8d\x8f\xd3\x9d\x61\x00\xc7\xe6\x14\x7b\x2c\xfa\x74\xa4\xe3\x32\xa0\xb0\x47\x41\x37\x9b\x5c\xeb\x53\x18\x8b\xcd\x17\xb5\xfa\x98\xaa\x79\x7c\xc6\x2c\x9e\x04\xaa\x2e\xf2\x1a\xfa\x48\x59\x6e\xfc\xf5\x1a\x12\xf7\xdf\x74\x55\x4f\x3c\x76\x71\x7d\xbc\x5f\x80\x41\xe0\x23\xf3\x86\x8c\x79\x05\xf2\x05\x32\xbf\xb3\x7a\xb9\x6a\x8c\xb5\xc5\x49\x51\x16\xed\x95\x1a\x58\x63\xc8\x40\x0d\xfd\x42\x11\x9a\x56\x01\xe0\x50\x71\xd8\xd7\xd7\xa0\xe3\xe9\xd1\x1b\xc4\xf8\xe2\xb7\x27\xa5\xa3\x24\x58\xc8\xb9\x14\x1e\xed\x61\xb6\x6e\x3a\x28\x9c\x02\xb2\x10\x5e\x84\x49\x61\x5a\x37\x50\x99\xca\xd4\x4e\xfa\x7a\x07\x1e\x0f\xc7\x8d\x59\x95\x7a\x66\x06\xb4\x4f\x47\xf8\xd8\xd3\xc4\x4c\x21\xa0\xc5\x56\xf0\x1a\x47\x0f\xdf\x75\x23\xe4\xbd\x8f\x01\x2b\x53\x28\x3b\x60\x43\x82\x4f\x31\x4c\xd3\xd1\xc7\x58\xd7\x11\x6a\x12\xb9\xf1\xa1\xab\xf8\x21\xf5\x50\xfd\x55\xa6\xc7\xa7\x69\xd8\x39\x90\x85\xb8\x65\x2f\x5e\x7a\xdd\x02\x44\xc2\x56\xe5\x95\xd2\xd6\x16\xa7\x15\x42\xf9\xcd\xe7\x86\xad\x53\x1a\x64\x8a\x75\x55\x19\x93\x9b\x5c\x35\xa6\xca\x8d\x3b\x0f\x63\xfa\x3c\x9c\x24\xe1\x34\xd1\x14\x4b\x9a\x80\x48\x04\x4e\x26\x18\x1c\x17\xc3\xe7\xa9\x70\x1c\x0a\xca\x62\x9b\xbc\x67\xfb\x5c\xa1\x3b\xec\xf2\xff\x1c\xd9\xe8\xf0\xeb\x98\x83\x38\x38\x31\xfd\x5f\x4f\x50\xc4\x0c\xfd\xcb\x34\x65\x03\x45\xf9\x5f\xa6\x02\x40\xc0\x0a\xab\x9c\xa8\x6f\xac\xa5\x8c\x12\x40\xc3\xee\x22\x60\x4c\x55\x87\xff\x07\xe9\xc9\xff\x20\x39\x09\x3a\x9b\x47\xba\x2c\x1f\xa9\xa2\xb2\xad\xae\x66\x9c\x48\x23\x54\x75\x27\xc9\xf9\xdb\x41\x0f\xcd\x81\xec\xf5\x61\x7c\x9d\xef\x68\xa8\xff\x4b\xc4\x08\x77\xda\x61\x0f\x51\x52\x53\xb4\xcc\xff\x5f\x41\x99\xd0\xd3\xae\x9f\x32\x8d\x10\xbd\xef\xdf\x83\xea\x10\x9c\x47\x82\x3f\x0a\x13\x96\x9e\x58\x16\xff\x65\xec\x38\xc9\x91\x1d\x07\x7d\x51\x2e\x32\x67\xa8\xfb\x94\xd2\x86\x26\xbc\x86\xf2\x19\x44\xbb\x34\xa3\xc7\xb4\xf5\x5f\x23\x58\xc5\x46\x82\x25\x26\x2e\x22\x58\x48\xaf\x8a\x94\x5e\x85\xb9\x1c\xca\x69\xed\x63\x8b\x3e\x31\x0d\xea\xe6\x79\x04\xbf\x5d\xc4\x4c\x2c\xaa\xbc\x38\x2f\xf2\xb5\x2e\xf1\x58\x82\x30\x48\xe7\xcd\x5f\x38\x3f\x88\x44\xea\x32\x7b\xf4\x96\x35\xe5\xdc\xdf\xab\x89\xcf\xfd\x96\xff\xd4\x9b\x65\xee\xa4\xa7\x11\xad\xf0\x7b\x38\x54\x74\x04\x04\xf6\x38\x51\xd4\x83\x83\x8b\x32\x80\x19\xe0\x3f\x3b\x2d\xce\x4d\x35\x52\x76\xa5\x67\x46\x59\xb3\xd2\x0d\x40\x44\x95\x05\xc7\xe0\x11\x66\x88\x29\xe7\x4e\x42\xa5\x75\x8a\xae\x0f\x11\x2d\xe3\x4a\x45\xbb\x49\x14\xf4\x07\x2b\xc6\xd1\xc0\x8f\xc2\xde\xec\xfb\x62\x3b\x32\xa4\xb8\x8b\x01\x57\xe5\x62\x51\x97\x46\x2c\x08\x6e\x02\x99\x7e\x8d\xd7\x36\x32\x7d\xd3\x75\xbe\x21\xe3\xae\x48\x4e\x29\x87\x29\x26\x12\xe1\x08\xc3\xcb\x62\xae\xac\xe1\xe9\x0a\xf1\x15\x56\x44\x08\xfe\xf6\x9b\x2f\xfe\xdb\x6f\x59\xf7\x12\xee\x81\x41\x41\x94\x5a\x9f\x02\x7e\x01\x69\x10\xc3\x58\x43\x8a\x96\x06\x01\x7b\x4d\xae\x32\x50\xd2\x67\x01\xf0\xaa\x5d\x78\x7f\x53\xa8\x4c\x4c\x18\xd4\x31\x28\x18\x0a\xf7\x42\x5b\x05\x08\x0f\xae\x18\x42\xc0\x59\x7d\x6e\x72\x55\xb4\xc3\xb1\xaf\xef\xad\x87\xa5\x39\x01\x3b\x0b\x78\x29\x5c\x2c\x74\x6b\xce\x4d\x43\xd9\x51\x30\xc7\x4f\x79\x45\xdf\x0f\xc0\xe9\xe7\x0a\x40\xc2\x05\x14\xd7\x5c\x97\xa5\xaf\x81\x01\x72\x64\xd6\x47\xcc\xa0\x0e\x8e\xf2\xae\x5e\x98\xf3\x9c\x7a\x92\xcc\xde\x41\x3a\x9d\x11\x6a\x30\xc5\x46\x62\x02\xab\xfe\xf8\xcd\x78\x75\xf0\xb4\xf1\xd5\x92\xc4\xf3\x6c\xdf\xdb\xe2\x63\x10\xc5\x2c\x13\xa4\x5a\x87\x09\xa5\x0e\xe2\x25\xea\x4b\xe1\x3d\xda\x61\x18\x3b\xec\x62\xc2\x3a\xc5\x8c\x93\xdf\xa7\x47\xc5\x71\x1f\x63\x83\x6d\x72\x81\x84\x83\x09\x0c\x8c\xe0\x5f\x86\x81\x5b\x90\x5b\x3f\xe6\x12\x98\xac\x36\x6b\xf3\x74\xd3\xe5\xe8\xed\x9f\x37\x7d\x8a\x02\x2a\x74\xa0\x26\x1f\x9a\xdb\x34\x04\xe7\xba\xbc\x95\xcb\x17\xce\x3e\x2a\xdc\x4b\x38\x97\x92\xa9\xdc\x8b\x12\xf2\xde\xef\x30\xf9\xd1\x84\xc6\x0a\xba\x44\x71\x7a\xae\x4b\xd2\x9b\xa2\x66\xcd\x4d\xb8\x34\x16\x25\xef\x59\x3d\x97\x6a\x51\x62\x9e\xf0\x5f\xd0\x59\x66\x30\x17\xd9\x2d\x2e\x1c\x89\xed\x24\x49\xdd\x9e\x5a\x42\xe3\x95\x45\xce\x03\x1d\x16\xc4\xb5\x78\x18\x28\x20\x59\x94\x96\xb5\x6d\x41\xc7\x5e\x57\x7c\x6c\x67\xda\x7a\x3e\xb4\x31\x6d\xd8\x65\x58\xf9\x48\x65\x59\x60\x92\x43\x4d\xf0\x19\xe5\xe8\xf4\x89\x6f\xaa\x75\x59\x22\x12\x83\x23\x76\x88\x18\x11\xaa\x0e\xde\x14\x78\xb4\xfd\x48\xe3\x84\x48\x11\x23\xe3\x37\x89\x8c\x8d\xef\x30\x34\x4f\xef\xe2\x1f\x04\x3b\x43\xa6\xe5\x38\xd1\x2e\xe6\x26\xa6\x03\x79\x3f\xf2\x90\x90\xbd\xf2\x3d\xa5\x74\xec\xbe\x73\xbe\x30\x1a\xad\xbb\x62\x5c\x31\x4a\x98\x09\xb7\x92\x83\x61\x7f\xd6\x4e\x51\x49\x27\x04\xed\x7d\x63\x74\x2b\x26\xba\xa0\x1c\xb4\x59\xf6\x94\xf3\xc2\xd2\xc4\x03\x38\x22\x2e\x72\xe8\x33\x54\x9d\x7a\x32\x61\x7b\x59\xd6\xe7\xb2\x14\xb8\xdd\x18\x06\x24\xfa\x78\x67\xd3\xd7\x3d\x48\xb2\x92\x01\xc1\x86\x25\x6a\xd4\xb9\x2e\x47\x9b\x28\x48\x62\x9d\x4f\xb7\x53\x70\x65\xe2\xf3\x93\x04\xf0\x6d\x24\x0d\xa8\x37\xdd\x4c\x1a\xfc\xf6\xb8\x8d\x34\x20\x03\x60\x4d\x4b\xae\x46\x36\x1c\xf2\x11\x5c\x9e\xfe\xe6\x44\xd7\x23\x86\xbb\x08\x6b\x83\x29\x58\xc0\xf8\x34\x88\x4d\x34\x70\xbf\x25\x49\xb0\x47\x38\x57\x9e\xb0\xc0\xf2\xf4\xd0\x15\xe8\x7c\xc7\xe1\xa1\x37\xd9\x7f\xd7\xaa\xc8\x73\x40\xb6\x11\xb4\x21\x7c\x92\xa1\x24\x78\x70\x6c\x72\xdd\xf2\x3d\xef\xf8\x9d\xa5\xe6\x69\xd8\x27\x82\x04\x09\x83\xc7\xfe\xde\xee\xfe\xfe\x8e\x90\x62\x57\x08\x5e\x67\x2e\x5b\xd5\x2e\x9a\xfa\xc2\x2a\x73\x39\x33\xe4\x73\x3d\x78\xb0\xff\xe5\x57\x5f\x7f\x35\x52\x0f\xf6\xbf\xfc\xfa\xc9\xd7\x43\x96\xea\xa5\xa4\xca\x3f\xcc\x65\x1b\x7c\x18\xe5\xa4\x09\x9f\xfc\x3f\x33\x13\x4e\xaa\xc4\xde\xb1\x1c\xc1\x9e\xe0\x44\xda\x23\x44\xc8\x80\x0f\x40\xbe\x18\xc2\xb0\xe1\xbf\xaf\xbc\xa9\x55\x88\x44\x50\x72\x17\x00\xb4\xaf\xaf\x7d\x5c\xa5\x97\x6c\x28\xb3\xf5\x01\xb8\x75\x1e\xe2\x34\x07\xc4\x48\x48\xa3\xe9\x5f\xe2\xc7\x3b\x00\x0b\xce\x88\x93\x02\xf0\x96\x78\x21\xdf\x84\x5f\x2e\xa8\x84\xd7\x6b\x4b\xd6\x25\xa2\x84\xdd\x6a\x7d\x5f\xd7\x2b\x58\xa6\xf5\xe9\xc2\x23\x2b\x7a\x73\x52\x00\x46\x4b\x34\x52\x4b\x7d\x99\x68\xa4\x68\x2e\xd1\x0d\xdf\x7d\xc4\x7a\xa9\xb0\x33\xc0\x5d\x49\xe5\xb5\x81\xb8\x75\xca\xc5\xe9\xdb\x42\x97\xa4\x79\xdd\x2c\xd1\xd7\x49\x0d\x1e\x3c\x7e\xf2\x64\x7f\x28\x45\xaa\x01\xef\x2e\xff\x95\x9b\x60\x98\x76\x06\x22\xf0\x1e\x59\xd0\xe4\x0b\x30\x77\x07\x5c\x1d\x58\x6d\x9f\x22\xc6\x3b\xe8\x3b\xb9\xa0\x52\x5a\x3c\x20\xeb\x9c\xaf\x6b\xa0\xfa\x5c\xf7\x0f\xc1\x75\x1f\x20\x6c\xf9\x11\xaf\x53\xe4\x4a\x3c\x80\x8c\x32\x50\x80\xe9\x04\xd1\x7f\xd1\xdd\x81\xaf\x4c\xd8\xd3\x7c\xbd\xc2\x20\x1e\x9c\xcc\x3a\xe5\x47\x10\x48\x02\x5d\x47\xa7\xb3\xe0\x49\x8b\x13\xf2\x77\x83\x31\x10\x84\xbc\x33\x23\x9a\xed\xd6\x36\x84\x46\x70\xf9\xf3\x48\xb9\xcd\xcd\xf1\xcd\xf9\x34\xaa\xf8\x17\xce\xcb\x57\x19\x48\x97\xae\xb4\xbb\x6f\xa0\x62\xb7\xfd\x28\xb6\x82\x3f\x40\xc4\xa4\x2a\x52\x30\xf5\x39\x7e\x49\x0d\x19\xc6\x92\x94\x6d\xb1\xfb\x8e\x02\x35\x3c\x5a\x1f\x36\x16\x75\x9b\x03\xea\x12\x87\xb4\x9b\x2e\x63\xe7\xdb\x64\x4c\x49\xce\xd5\xfb\x29\xee\x82\x84\x69\x56\xd4\xd5\x3b\xc7\x52\xff\x19\xf2\xe2\xe9\x80\xbf\x7d\xcf\x4c\x0c\xf7\x2e\xcf\x78\x7c\xfa\x3b\x5a\x8d\x62\x77\xf7\x13\xce\xa2\x38\x49\xe9\x41\x0a\xcc\x5d\x45\x9d\xa0\x12\x44\x38\xa9\xb7\x28\xd9\x44\x1a\x0c\x3f\xfc\x18\xf2\xb4\x33\xd5\x4e\x82\xad\x9b\x99\x93\x83\xeb\x0b\x4b\xdc\xd1\x89\x01\xa8\xf4\x59\x5d\x59\xf4\x18\x2e\xaf\xd0\x85\xae\xaa\xab\x5d\xd0\xe9\x84\x44\xc9\xe8\xbb\x28\xa4\x80\xfb\xa1\xe9\xd0\x9f\x2e\xb5\x56\x07\x8a\xcd\xf7\x09\x90\x68\xb4\xec\xdb\x7d\x96\xfd\x9f\x74\x5e\xd4\x16\x9c\x49\x38\x5c\x0a\x5d\x68\x5b\xd3\x4c\x2c\xf9\x8b\x25\x51\xe6\xe8\x1b\x3a\x12\x41\x5b\x6a\xa3\xe5\x38\x66\x71\xc0\x58\xfc\x07\xde\x6e\x77\xee\xbd\x4f\x4a\x14\x10\x12\x87\xa2\xfe\xd6\xf5\xa8\x77\xb5\xe9\x8c\xbb\x52\x74\xbe\x43\x7b\x28\xcc\xa6\xd3\xe4\x63\x54\xef\xa7\xe1\x60\x71\xb0\x6a\x3a\xc4\x31\x26\xe3\xde\x70\x59\x4b\xe6\xe2\x17\x73\x72\x56\xb4\xfc\x38\xcb\x30\x3d\xb6\x1b\x8f\xc9\x41\x83\x6f\x74\xae\xea\x39\x06\xa8\x15\x73\xa5\xfd\x46\x71\x84\x28\x06\x17\x93\x6e\x23\x11\x69\x26\x26\x48\x50\xe5\x43\xac\x70\x9a\x7a\xbe\xde\xf4\x49\xe7\x60\x58\x10\xe1\x20\xe8\xec\xe1\xfd\x41\x77\x11\x3d\xa5\x9a\x95\x6b\x0b\x94\x35\x75\x77\x50\x83\xec\xa4\x5c\xbb\x8b\x6f\xb6\xb6\xf8\xdf\xa2\xc2\x7f\xeb\x75\xab\xca\x5a\xe7\xee\x3e\x2c\x7e\x37\x0a\xd3\xf1\xab\x75\x05\x0f\x67\x65\x31\x3b\x53\xf9\x49\x89\x7f\x64\x6a\x07\x9c\x23\xea\xb5\x35\x79\x7d\x51\x29\xf8\x6b\xbd\xc2\x7f\x41\x9b\x05\x7f\x41\xba\x26\xfc\x6b\xdd\xe2\x1f\xa6\x6a\xf9\x59\x69\xdc\x69\xa4\xba\x28\xa1\x1c\x85\xe5\xd9\xf5\xc9\xb2\x68\xd5\x99\xb9\x82\xea\xcf\xcc\x15\x18\x91\xdc\x1f\xeb\x95\x32\x4d\x53\x37\x0a\x5c\x26\x2e\xdb\xa5\xa9\xd6\xd9\x50\x20\x79\x6e\x74\x2a\xc5\x38\x35\x0a\xf2\x32\xe7\xa6\x6a\xd5\x49\x01\xae\xe3\x77\xc6\xd7\xe7\xba\xd5\x02\x5c\xd2\xbb\x19\x76\xdd\x07\xf7\x24\xca\x57\x70\x52\xc4\x40\x04\x51\x8d\x00\x4d\x68\x9b\xe2\xf4\xd4\x34\xd2\xd5\xbc\x1b\x77\x1f\x6b\x5e\x16\x6e\x66\xe5\x99\x9d\x57\x6f\xcf\x4d\xe3\xea\x7e\xbb\x6e\xfb\x5c\x13\xc3\xe4\x73\x61\x35\x1c\x87\x65\x18\xd0\x97\xd7\xd7\xfe\xad\xd0\xa8\xb9\x69\x4a\x11\x72\xec\x68\xd3\xac\xf8\xa1\x53\xb1\x74\xec\x1e\x7a\x67\x5d\x6d\xa8\x78\x43\x95\xf3\x79\x52\xa7\xac\x6d\xfb\x1e\x38\x5a\x9e\x26\x90\x7c\xac\xd2\x1b\xfd\xc9\x4e\x87\xef\x7a\x3b\xfe\x49\x4d\x85\x46\x26\x13\x85\xcb\x8b\x7a\xfc\xa1\x02\xf6\x36\xf9\x40\x1d\xb9\x4f\x8e\x11\x8b\x77\xd3\x0e\x43\xf5\xe1\xa1\x98\x91\x50\x4b\xf6\xe8\x51\x16\xac\x46\x72\xba\xbc\x62\xf3\xfa\x1a\x4a\x89\xf1\x08\x12\x83\xd1\x91\xd5\xcc\xf4\xa1\x2f\x80\x66\x10\x82\xc3\xd5\x81\x1a\x4c\x3e\x1c\x4e\x02\x65\x92\x74\x34\x8a\x05\x76\xbc\x5a\xdd\x9c\xe9\xa6\x5e\x57\xb9\x9a\xeb\xa2\x84\xe0\x58\x56\x54\xec\xce\xb4\x45\xed\x06\x86\x6e\xfa\xdd\xbe\xd2\x8d\x35\xff\x78\xf7\xf6\x87\xce\x29\xa4\x19\xa5\xe9\x71\x45\xb0\x30\xbd\xf5\xa1\x4d\x22\x76\xfe\x79\x53\x5b\xbb\x4b\x8c\x80\xba\x5c\x96\xca\x7d\x01\xc7\x5e\x36\xf7\xeb\x9b\xef\x37\xb5\xe6\xc6\x7e\xb9\x2c\x47\xaa\x5d\xae\xc2\x4d\x04\x05\x82\xeb\x01\xfc\xec\x43\xb5\x4b\xbc\xd1\x6e\x3a\x41\xd5\xaf\x5f\x7e\xb3\x7d\x6f\xab\x6d\xae\xc8\x43\x11\xb2\x57\x54\xe6\x42\xbd\x78\xfb\xe6\x47\xd7\xb5\x86\xc2\xe6\xd0\x75\xb5\x5d\xae\xb0\xc7\xaf\x9a\x7a\xf9\x0e\xda\x62\x0a\x95\x39\x8a\x38\xb9\x5c\x96\x24\x67\xdf\xa8\x19\xe4\x19\x19\x28\x7f\x95\x63\x1d\x71\xd6\xef\xed\x00\x4b\xe1\x5e\x5f\x5f\xbb\xd1\xba\x9b\x8b\x02\x75\xed\xb7\x57\xef\xf5\x29\x8a\x01\x19\x34\xdd\x00\x0d\xee\x66\x48\xe5\xdb\xc6\xbd\x1d\xa8\xec\x75\x05\x89\x84\xd5\xaf\x6f\xbe\x9f\x82\xb6\x1b\x27\x95\x61\x2d\x68\x66\x2e\x97\xa5\x58\xb1\x73\xdd\x10\x3a\x02\x05\x0d\xab\xb2\x9e\x71\xb4\x88\xfe\xa8\x2f\xbf\xaf\x67\x3f\xea\xa6\x05\xde\x96\x7e\x33\x46\xb7\xab\x73\xa1\x01\x5b\x6a\xf2\x60\xfc\xe8\xb3\x89\x2b\xd3\xb4\xe0\xf5\x36\x38\x3a\x7c\x78\x3c\xfc\xed\xe0\xe8\x3f\x1f\x1e\x3f\xc2\x17\x0b\xa3\x73\xc4\x21\x99\xfc\xe7\x60\xfc\xe8\x70\x38\x3d\x52\x1f\xda\xe3\x47\x83\xa3\xff\xfc\xd0\x7c\xa8\x8e\x1f\x0d\x3f\x9b\x2c\x4f\x09\xac\xe1\xc1\x5f\xbe\x7a\xf2\xc5\x48\x3d\xf8\x7a\xff\xf1\x13\xf8\xe7\xc9\xe3\x29\x74\xad\x54\xab\xa6\x6e\xeb\x59\x5d\xaa\xdc\xb4\x98\xf2\xd9\xd5\x0e\xef\x7e\xe4\x57\xe4\xfd\xae\x4f\xea\x75\x7b\xad\x57\x2b\xf7\xff\x5d\xdb\xd6\x8d\x3e\x35\xd7\xe3\x9d\x5d\xa0\xee\xee\xda\xbe\x9e\x17\xa5\xb9\x6e\x8c\xbd\xbe\x28\xf2\x53\xd3\x0e\xa7\x34\x8c\xaa\x7e\x8e\x5e\x82\x5c\xd7\xdf\x5f\xbe\xbf\xfe\xee\xe5\xb3\x17\x43\x2a\xb0\x92\x6d\x7d\x98\x7c\x98\xe0\xe3\x75\x43\xad\x1f\x7d\xb8\x18\xef\xec\x1e\xef\x4c\x87\x83\xc3\xa9\x7b\x3f\x38\x9c\x1e\xfd\xe7\x87\xc9\xe1\x83\xe3\x47\xff\xef\xf5\x70\x80\x7f\x4f\x8f\x1f\xb9\xf7\xd3\xc1\x87\x7c\x67\x78\x3d\xbc\x1e\x4e\x70\x62\x27\x8f\x54\xc0\x6c\xde\xbe\xb7\xa5\x1e\xa9\xfd\xa1\x7a\xbf\x30\x57\x20\xdf\xae\xad\x99\xaf\x4b\xcc\xab\xda\x36\x75\xbe\x9e\x19\x86\xeb\x71\x8b\xfe\x1e\x28\x1c\x7a\x7f\x7c\xd4\x97\x93\x8f\xb6\xae\x56\xe3\x8f\xde\x5f\xd5\x5c\xea\xe5\xaa\x84\x80\x7f\xf5\x48\x3d\x86\x8a\x2d\x26\x69\xc0\x0c\xc0\x53\x7c\xa3\x94\xda\x55\xdf\xbe\x7c\xf5\xf6\xa7\x97\x4a\xdb\x33\xc0\x69\x72\x35\xa8\xb6\xd1\x95\x75\xe7\x49\x94\x7b\xf6\xea\xfd\xcb\x9f\x30\x37\xbd\xb2\xa6\x29\x74\x59\xfc\x8e\xf8\x99\x03\x3b\x86\xad\x08\xa9\xcd\x82\x45\x0b\xa0\xd6\x67\xc6\xda\x17\xf4\xd2\xc9\x18\xd4\xa7\x2f\x86\x8e\xfd\x80\x87\x0b\xe3\xc7\x84\xef\xbe\x1c\x62\x02\x26\x77\xd8\x74\x59\x2a\x7b\xb5\x3c\xa9\x4b\xc0\x20\x27\x97\x5b\xc7\x29\x61\xd9\x27\x43\x65\x2e\xcd\x6c\x0d\xfd\x00\x1c\x3c\x44\x40\xc1\x1c\xdf\x3c\x0a\xdf\x00\x88\x03\xef\xbf\x7b\xf9\x83\xe2\xfc\x90\x0a\x78\xa2\xb6\x86\xea\x8b\xb9\x42\x37\x0d\xa8\x7c\x22\xd1\xbd\x2d\x67\xd4\xc6\xc5\x7b\xcf\x55\x5b\x66\x7b\xc2\x2a\x6e\x1c\xd8\xe3\x3f\x31\xb0\x2f\x86\x74\xcf\xfc\xd9\x81\x9d\xd6\x9b\x47\xd3\x86\x5e\x8b\xd1\x70\x10\x0e\xc5\x0f\xec\xae\x9a\xba\xac\x4f\xd5\x6c\xa1\x1b\x65\xcd\x3f\xd7\xc6\x5d\x62\x83\x07\xfb\x7b\x7b\xdf\x7c\x3d\x7c\xaa\x96\x80\x0a\xb1\x5a\x19\x6d\x8d\x02\xb8\x14\xc8\xc8\x76\xae\x73\x13\x1c\x94\x90\xbe\x94\x25\xee\xd4\x03\x95\x3d\x9a\x64\x9c\x43\x3e\x7b\x94\x79\x29\xed\xc1\xd7\xfb\x5f\x7c\x3d\x52\xaf\x5f\xaa\xa5\xbe\x42\xad\x23\x6e\x60\xd2\x3b\x52\x34\x38\x44\xa0\xc0\x25\x33\x99\x28\xad\xe6\x85\x29\x73\x8c\xfe\xb9\x28\xaa\xbc\xbe\x18\x33\x55\x03\xf7\x1b\xc6\x47\xc8\xeb\xa5\x2e\x2a\x30\x26\x03\x16\x11\xc8\xa0\x7c\x33\x48\x62\xa7\x0e\x3c\x59\x04\x97\x72\x47\x40\x71\x99\x02\xad\x9f\x4c\xd4\xcf\x16\x0d\xcb\xe0\x75\x1e\x22\x2c\x6a\x00\x7a\x78\xc6\xc6\x6b\xca\x2f\x5b\xb8\x59\x7b\xfd\x12\xd7\x6e\x59\xe7\xc5\xfc\x4a\x15\x2d\xba\x20\x84\x2e\x76\xa9\xb1\xcf\xd6\xb3\x09\xe5\x41\xd3\x75\x24\xcb\xa3\x23\x3c\x59\x12\xd2\x9a\x3a\x05\xd9\x79\x1b\xbc\xdd\x4f\xa3\x5b\xc1\xd1\x9b\x1a\x32\xaf\xd8\xed\x7b\xf2\x7e\x50\x07\xca\xd1\x3e\xca\x71\x1b\x55\x19\x2b\xf5\xa5\xf7\x06\x61\xed\xa8\x6c\x56\x57\xb6\x6d\xd6\x8e\x6b\xca\x80\xc4\x70\xa8\xfa\x47\x7d\xe9\xe9\x20\xec\x23\xf1\xe2\x7d\x20\x42\x3e\xe2\x4b\xe7\xf9\xfb\x3a\x50\xce\xb7\x4d\x38\x88\x03\x85\x4d\x38\xa6\x48\x88\x28\x7c\x42\x5e\x46\x9e\x75\xa8\x7f\xd0\x25\xb4\x49\xf1\x96\x96\x0e\x4e\xb8\x4b\x63\xfe\x25\xae\x05\x25\xa3\xa0\xa6\x93\x16\x9f\x9e\x36\x7b\x11\x7a\xa1\x86\x83\x9e\xe2\x28\xb1\xf7\x54\xe3\x4e\x52\x26\xad\x7c\x80\x91\x4b\xe5\x3a\x36\xf6\x70\x57\xf4\x35\x12\x2f\xdc\x5d\x7e\x38\x9b\xfc\xa2\x68\x16\x64\x20\x4f\xdd\xa0\xe3\x8d\x27\x4e\x84\x6b\xd8\xed\x02\x7c\xe2\xfd\x7b\x7c\xf9\xd0\xdb\x4e\x2c\xf5\x64\xe2\x2e\x4e\x48\x9f\x50\xcc\x55\xe3\xc8\x93\x25\x4c\x08\x01\x85\xeb\x3e\x3d\xda\x43\x54\xb1\x6c\x47\x58\xdc\xb6\x7a\xda\x18\x5b\x44\x18\xdb\x27\x5f\x88\x47\xde\xcf\x6e\xe0\x77\xd4\x51\x18\x8c\x13\x66\xfb\x9f\xc3\x74\x0d\x43\xea\x06\x9c\x1a\xa9\xb4\x0f\x2e\x25\x88\x2d\x44\xaa\xad\xd8\x49\xe8\x5f\x6b\x15\x95\xa6\xbe\xc9\xad\x9e\xe0\x5b\x71\xee\xe1\x58\x16\x95\x5d\xd1\x0d\x13\x42\x2a\xeb\x46\x89\x4b\xcf\x1d\x8f\x70\x6b\x88\x83\x48\xdf\xde\x79\x14\x7d\xc6\xaf\x91\x4a\xf2\x78\x8d\xd4\xc7\x7f\xfe\xfa\xdd\x4f\xfe\x04\x21\xb8\x13\xd4\x8a\xf1\x30\x6c\x2d\x32\x8e\x31\xf1\x95\x83\x47\x6e\x38\xe9\x98\x7e\xc0\x5f\x6b\x0c\x6e\x97\x74\x33\xec\x0a\xe9\x52\x21\x20\x87\xb6\xb6\x7c\xd3\xc9\xa4\x7b\xc5\x68\xa4\xfb\xb9\x65\x29\xa4\xca\xe4\xb7\x51\x98\xcc\xb7\xcd\x2b\xed\x08\xe0\x55\x64\x4e\xe7\xaf\xc5\xf4\x41\x2e\x93\xf4\xa3\xc1\xdd\xf3\x28\x62\x80\x12\x3a\x14\x55\x9e\xb8\x73\xdf\xef\x4c\xb0\x7b\xd8\x33\x1b\xb2\x92\xe3\x70\xa2\x7c\x3a\x35\x3e\xb1\x61\xff\xf7\x7d\xc9\x7b\xb3\xb3\x30\x7d\x85\x7a\x52\xdb\x09\x03\x79\xa7\xe3\xa9\xea\xf4\xfe\x40\x09\x2d\xf9\x2d\x0d\xc9\xf4\xc6\xec\x4f\x2a\xf6\xc6\xcd\xb6\x40\x4e\xf3\x1d\xef\x0c\x1c\x72\xb4\x22\x0d\x91\xf3\x07\xb9\x73\xdc\xa4\xfa\x2f\xdd\x93\xa1\x38\x8c\xcf\x3c\xaa\x03\x6a\xa5\x90\x09\xff\xa8\x2f\x83\x19\x0f\xdc\xdb\x74\xab\x5a\x7d\x66\xac\xca\xe6\xa5\x6e\x33\x6f\x16\x1b\x54\x75\x4b\x39\xd7\x73\x63\x56\x54\x0b\x20\x5a\x61\x5c\xa5\xb1\xea\xc1\x37\x5f\x7f\xfd\x17\x79\x91\x7e\xd4\x97\x2f\x39\x75\x93\x6e\x4e\x4d\x3b\x52\xb6\x99\x09\x19\xfd\xcc\x5c\x8d\xa0\x3e\x38\x86\xae\xc5\xb7\xde\x2a\x22\x6e\x69\x42\x44\xb0\x63\x59\xe2\xfa\x5a\xfd\x71\x23\x71\x26\x81\x27\xae\x44\x0b\xe4\x69\xd9\xcc\x8e\xe0\xdd\xa6\x5c\xef\x03\x25\xaa\xe5\xa2\x87\xd4\x63\x35\x05\x04\x6b\xb3\x72\xed\x0d\xe0\x0f\x47\x36\xc0\x7a\xc6\x65\x0f\x44\x1b\x12\x3a\x92\xe1\xaf\xcd\x2a\x95\xb6\xa3\x2c\x86\x3c\x35\x58\xb0\xb3\x19\xf0\xb5\x5f\xca\x47\xa4\x10\xb5\x0a\x91\x34\xac\x01\x9e\x42\xe3\x74\xf3\x6d\x35\xdd\xbe\xa7\x1e\xa9\x5d\x35\x2f\xaa\x1c\xc5\x84\xa6\x38\x5d\x08\x5e\x7e\x40\x59\x19\x1c\xdb\x8a\xe9\xfb\x28\xa2\x6d\xb7\x65\x56\xdf\x5c\x12\x9d\xe4\x8f\x86\x54\x29\x3b\x50\xf8\x14\xb6\x1e\xd1\x83\xbb\xe4\x0a\x4e\x92\x9d\x80\xdd\xfe\x89\x3b\x3d\x50\x4c\x55\x46\x62\x24\x92\x50\xcf\x5a\xc6\x8c\x06\x67\xf2\x17\xcc\x81\x20\xcc\xf4\x0b\xc9\x90\x50\xdf\xdd\xb6\xb1\x63\xfe\x81\x89\x7b\x04\x7b\x22\xce\x91\xc7\x51\x23\xbf\x7f\xbd\x6e\xeb\x58\xd0\x39\x05\xb8\x12\x31\x25\xc4\x60\x90\xbc\xb9\x7d\xcf\xf3\x14\xc9\xe1\x04\xe2\xf7\xc8\xf3\x03\x81\x66\x21\xc5\x12\x99\xdb\x66\xed\x06\xa7\x10\x40\x13\xb4\xe3\x65\xb1\x44\x8f\xa7\xeb\x6b\x9c\xa9\xf1\xa9\x69\x79\x02\xbf\x03\x55\xc8\x20\x23\x15\xc3\xae\x2b\x98\xa5\xc8\xa5\x12\x28\x0e\x1d\x5b\x73\xa3\xc1\x4d\x14\x64\x3c\xad\xce\x2a\x27\x9a\xca\x71\xf2\xb6\x9d\x79\x5a\x87\xa7\x8b\xe7\xc0\x4f\x75\x64\x69\xe2\xa7\x84\x5f\x0e\xb4\x28\x7d\x46\x71\xb6\xb3\x36\x4d\xb1\x9e\x90\x74\x09\xfe\xbe\x75\xd2\x18\x7d\xd6\xb5\xc1\x45\xa8\x85\xb5\x23\xd3\x94\x24\x12\x0c\x86\xda\xef\x28\x6f\xbb\xee\x6c\x66\x7f\x3c\xe3\xd5\x2b\xaa\x74\x37\x52\xf8\xc4\x8b\x3e\xc6\x91\x33\x66\x4b\xee\x0a\x9c\xc0\xae\xd8\xd9\xab\x38\x29\x03\x53\x6a\xbb\xd3\xd9\x69\x4c\xe8\x2a\x45\xb7\xae\xaf\x71\x63\xbb\x2a\x01\xcf\x96\x61\xe2\xbd\x92\x0e\x0b\xef\x1d\xcb\x7b\x33\xed\x78\x48\xc3\xd1\x99\x57\x6a\x36\x3a\x5a\xb2\x22\xf9\x58\x56\xe4\x17\x05\x58\xcf\x46\x7d\x74\x92\xfb\xda\x12\x16\xbc\xaa\x2b\xd3\x37\x83\xf1\xef\xeb\xeb\xf8\x48\x47\x4a\xd7\xd7\xb0\xac\x73\xd0\x47\x6b\xb9\x7a\xe8\x56\xa0\xf3\x3c\xe2\xfb\xd9\xf5\xb9\x2c\x6c\x1b\x69\x27\x20\xcb\x50\xae\xbc\xf5\x60\x33\xe9\xc2\xa9\x88\xbb\x28\x2f\x94\xf8\x8d\xbb\x53\x3a\xd7\xf3\x1f\xb1\x68\x24\xd8\xf5\xb8\xd6\x1e\x64\x0e\xda\x0e\x47\x49\xd1\xe3\xa7\x22\x9f\xf6\xe4\x91\x7a\xbe\xd0\x78\x18\xcf\x4d\x63\xe1\x3e\x44\xa9\x1f\x48\x3d\xde\x01\xc8\x58\x2f\x8c\x67\xe6\x22\xf2\xac\x9e\x95\xd6\x1d\x1c\x82\x0d\xe2\x57\xbf\xfe\xfa\x2b\xaa\x3e\x10\xf4\x61\x61\x88\xf3\xe3\x90\xa8\x3e\xca\xfe\x1c\xf7\x25\x50\x74\xae\xc7\xd3\xf6\xc2\xbe\x5b\x23\xbc\x67\xb8\xf6\x5d\xb7\x1f\x8f\x38\x0f\xc5\x08\x7e\x83\xae\x1e\x58\xd9\x73\x26\xe9\xb4\xd9\x03\x9f\x4e\xd6\x09\x26\x5e\x9c\x04\x29\xd0\x78\x46\x33\xba\x30\xe8\x69\xd2\xd6\x42\x2d\x32\x47\x1b\x24\x4d\xd8\x2d\x97\x03\x09\x6b\xc3\x00\xb6\x09\xea\x11\x25\xba\xb4\xd4\x2b\xec\x85\x07\xe9\xcb\x21\x41\x7c\x0f\x55\xd9\x0f\x3b\x02\x8f\xbe\xab\x06\x18\x15\x71\xa0\x03\xe9\x17\x67\xdc\xfd\xdd\x13\x2f\x1e\x13\x02\xa8\xed\x38\xa1\xfb\x34\xb3\x92\x56\x89\xeb\x87\x06\x45\xde\xa8\x6d\x8d\x92\x34\xaa\xe1\x5a\xc7\x22\x8a\x53\x26\x22\xdf\xa0\xc6\x58\x17\x61\xc7\xbc\xde\xaf\x60\xcf\x1c\xf9\x72\xe1\x14\xc0\x3e\x38\xba\xb5\x28\xa2\xe3\xe0\xdb\x14\x17\x71\xb5\x2a\xaf\xfc\x09\xc7\x24\xad\xee\x5c\xaf\x9a\xfa\xbc\xc8\x25\xe8\xb7\xdb\x39\xc0\x02\xfb\x0d\xf7\xf0\x21\xad\x2a\x7d\x16\xc2\xaa\xe8\x72\x38\x88\xde\x0f\xc4\xe6\x0d\xbb\x21\x8e\xdc\x82\x46\x0e\xb8\xeb\xf0\xe6\xce\xb9\xf6\x81\x8a\xf1\x04\x62\x3c\x79\x63\x3e\xb7\x18\xdb\x77\xe1\x76\xb6\xe3\x42\x6a\x37\x3e\x2e\x1e\xf4\x1b\x16\xbc\x5e\x1c\xa3\x22\xae\x5d\x6e\x5b\xf2\x1c\x48\xb2\x43\xb7\x5c\x9f\x85\x17\x2c\xaf\xbb\x9f\x05\x98\x4d\x73\xde\xdb\x14\xea\xae\x20\xd6\x90\xd2\xa1\x52\xbd\x1d\x49\x09\xaa\xb8\x4f\xfd\x78\xf8\x30\xfc\xee\x0c\x9c\x40\xce\xcc\x19\xf8\xd4\x35\x66\xd6\x86\x93\x45\x7d\x77\x7b\xfa\x40\xc9\x6d\x0e\xd5\xf1\x7d\x17\x76\xce\xf5\x75\x54\x2a\x7b\x14\xbf\x7f\x1a\x87\xff\x54\x75\x45\x57\xc9\x08\x24\x3b\xa5\xd5\x4a\x17\x8d\x74\x1a\x82\xa6\x83\x2a\x27\x9c\xd8\xc7\xca\xd3\xdb\x70\x60\xb7\x83\xf3\xd9\xeb\x39\x15\xab\xd7\xed\x6a\xdd\xda\x68\xa2\xb6\xd8\x48\x08\x45\xc8\xf7\x21\x89\xfa\x44\xa1\x7a\xb9\x42\x8a\x71\xd0\x3f\x73\xbe\x2d\x98\x0f\xd2\xe8\x73\xaf\x80\xde\xe9\xd9\xcc\xac\x5a\x70\x81\x01\x03\x2d\x7d\x75\xd7\x94\x42\xc3\x7b\x70\x16\x19\xc9\x73\x2b\x21\x47\x34\xb9\xa1\xa4\xef\xba\xe7\x01\xcf\x23\x97\x3d\xda\x6d\xb9\x71\xbb\xcc\xfc\x73\x5d\x9c\xeb\x12\x14\xfd\xa1\xd6\x50\x36\x54\x91\x66\x7b\xdc\x3c\x02\x9c\x70\xe1\x47\x9a\x68\xc0\x46\xee\xda\x32\x94\x34\x09\x90\xe5\x49\xea\x91\x14\x8e\xfe\x27\xf7\x72\x4f\x1b\xb0\x95\xfb\x7a\xe5\x8f\x19\xcf\xcb\x53\xf1\xb6\x8f\xbb\xe5\x15\x1e\x8a\x82\x37\xe1\x4f\xc1\x98\x45\x6f\x44\x50\x70\xea\x38\x87\x34\xd2\x77\x1a\x22\xc4\x20\x49\x42\x25\x67\x5d\x82\x37\xc2\x5c\xc6\x23\xda\xf6\x9e\xb8\x3f\x57\xa5\xa3\x9e\x60\x12\x46\x24\x5a\x5d\xba\x6b\x0e\xb6\xd7\xc9\xfa\xe4\xa4\x34\x23\x32\x53\xc7\x1c\xd5\x72\xfb\x5e\xb2\x94\x8e\x02\x1f\xa9\x0c\x3d\xbd\x33\xc9\x9a\x46\x54\xd8\x95\x0d\xd4\x77\x73\x64\xa3\xb7\xb8\x7f\x6a\x05\x7d\xf6\xf4\x2d\xa1\xbd\xf9\x03\x23\x5e\xa7\xb1\x91\x7c\x84\x63\x9f\xe2\x18\x0e\x95\x51\x53\x95\xfd\x50\x0b\xe6\x01\x49\xa1\x3b\x0d\xfe\x10\xb5\x75\x44\x7a\x6e\xfa\xa2\xb9\xb7\x7a\xd1\x0a\x83\xa8\x1f\xba\x63\xf1\x0a\xcb\xd0\x9b\x65\x1a\x86\xd6\x41\xc5\xf1\x3e\x46\x7c\xab\xaf\x2b\x72\x95\x56\x8b\xba\xcc\x19\x48\x12\xe3\x42\xc0\x8e\x84\x79\x91\xfe\xb9\x36\x4d\x01\x12\x09\x3e\x98\x82\x42\x1f\x2b\xf9\x5e\xdb\x76\xf7\x8d\x63\x9c\x0a\x93\x2b\x34\xba\xab\x99\x9e\x2d\x50\x9e\x82\xf4\x63\xc4\x64\x6e\xdf\xdb\x2a\xb5\x6d\xb9\xf0\x94\x58\x35\xd3\xea\xd3\xa9\x37\xff\x49\x1d\x0e\xf9\xe4\xaf\x9b\x72\xaa\x12\x67\x00\xc6\xe3\xcc\xfe\xfe\xf2\x3d\x06\xf3\x15\xd6\xbd\x2e\xa7\x2a\xb6\xcd\x93\x24\x29\x6d\x47\x74\xa6\xe0\xab\xd3\xb2\x3e\x71\x1f\xf9\x6c\x7e\xc2\x46\x2c\x9e\x6a\x7b\x55\xcd\xc4\x6f\x92\x57\xdf\x63\x1f\xf4\x6a\x55\x16\xd8\xb5\xc9\xe5\xee\xc5\xc5\xc5\xee\xbc\x6e\x96\xbb\xeb\xc6\x1d\xa6\x3a\x37\xf9\x53\xb0\x5e\x5a\xd3\x1e\xfc\xfc\xfe\xd5\xee\xd7\xd8\xe1\xc9\xa3\x6d\xca\x7a\x51\xaf\xdb\x29\xd9\x48\x70\x09\xc1\x03\x4a\x72\x9d\xe2\xd1\xda\x9a\xa6\xd2\x4b\xf9\x68\xa5\xad\xbd\xa8\x9b\x5c\x3c\x82\x15\x10\xbf\xf1\x58\x4d\x51\x77\x89\x4f\x1a\x9d\x17\x68\x75\x92\x8f\xc9\x6d\x82\x17\x67\xcb\x71\xf0\x30\x03\x70\x57\xf0\x92\x6c\x65\x8f\xb2\xa9\x62\x83\x2a\x5a\x77\x5a\x73\xd9\x4e\xc9\x4b\x65\x55\xea\xa2\xa2\x20\xcb\x45\xbb\x2c\xf9\xb9\xfb\x9b\x1e\x5f\xc2\xd3\x68\xea\xc0\x0b\x87\x9d\x5c\xb0\xd4\x47\x5b\x57\x49\x31\xf7\x88\xca\x7d\xd4\xe7\xda\xce\x9a\x62\xd5\x02\xe2\x03\x3b\x5c\xb3\x36\x81\x3b\x0b\x4d\xb9\x4a\x27\xb2\x47\xd0\x99\x89\x6c\x06\xaa\x9e\xc8\x9a\x62\x3e\x34\xaa\x2f\xf3\x62\xd0\x9b\xef\xb3\x68\x06\xf8\xc5\x7b\x73\xd9\xc6\xc3\xe0\x37\xff\x78\xf7\xf6\x87\xa8\xc7\x93\x89\x02\xaf\x84\xf8\xb6\x9b\x4c\xd4\xff\x67\xae\xac\x0f\x0d\x57\x88\xb4\xa9\x06\x4e\x3a\x61\xab\x7d\xf6\x28\x1b\x92\xd9\xd0\xb6\x45\x85\x66\x53\xf4\x39\x23\xd9\xc7\x16\xd5\x69\x69\x30\xcc\x3c\x16\x97\xa6\x9e\x9a\x0b\x66\x8f\x03\x86\x41\x3c\x36\x97\x2d\xad\x37\xfc\x9d\x4d\x15\x3a\x25\x8d\x44\x18\x1b\x04\xe8\xd4\xca\x4d\xa7\x1a\xc0\x2d\x71\xa0\xaa\x1a\xcd\x20\xee\x20\x40\x97\xf0\x4a\x81\x5d\x00\x25\x33\x7f\x9a\xb8\x9e\x97\xe7\xba\x5c\x43\x66\x5f\x57\x06\x22\xae\xdd\xb4\x09\x0c\x12\x51\x85\x7b\x93\xf9\x3c\xd3\xde\xa5\x4c\x54\x07\xce\x55\xbe\xae\xcb\x65\x29\xbe\xbe\x84\xf6\x13\x07\xb1\x64\x3d\x5e\xd5\x4d\x1c\xe8\x61\x17\xf5\xba\xcc\x29\x4f\x6e\xa4\xd8\x9e\xd2\x27\x57\xf5\x1a\xf8\x2c\x9d\xe7\xee\xef\x46\x81\xc2\x0c\xfd\x64\xb8\x2a\xc4\x81\x9a\xd3\x17\x6e\xdd\xc0\xa5\x00\x3e\x45\xd1\xd1\x31\x9e\x9d\x06\xa9\x7c\xd4\x6c\xf0\xb8\x41\xcd\x39\x4c\xb1\xd0\x4f\xf3\x76\x05\xfa\x19\xd2\x95\x92\x6f\x2d\x3e\xda\x8e\x01\xf5\xbc\x00\xeb\x66\x7f\xbe\x2e\x4b\x35\x2f\x4d\x7e\x0a\x39\x2d\x90\x26\x2b\xcc\xab\x8e\x86\x79\xd4\x37\xe3\x77\xb0\xd9\x4e\x6a\xb7\xe3\x04\x09\x87\x11\xfa\x6f\x51\x5b\x30\xf6\xda\x1a\xd2\x9b\x17\x56\xd5\xcb\xa2\x6d\x4d\x3e\x52\x17\x4d\xd1\x82\x74\xee\xf8\x53\xa9\xcf\x0f\x77\xc3\x3a\xce\x89\xcb\xd6\x02\x6e\x24\xf6\xcc\xf3\x8f\x0f\xc3\xd6\xf8\x76\x5d\xe0\x6d\xa7\xd3\x61\x41\x09\x69\x8b\xe8\xb3\x4b\xf4\x58\x1b\x20\x03\x5a\xe8\xc0\x54\xec\x6a\xf8\x18\x1a\x13\xe5\x3b\xed\xf4\xd4\xc9\xda\xfe\xc8\x0d\x36\xf2\x50\x98\xde\xee\x7f\x20\xec\xa6\x43\xf6\xa7\xf3\xef\xef\xf8\x56\xda\x30\xfd\xd6\x78\xa3\x8b\x4a\x2d\x4d\xbb\xa8\x73\xaa\x4e\x2e\xc4\xba\x29\xbd\x75\x35\x12\x5d\x5f\xcf\xdd\x3b\x70\xc7\xaa\x68\x9e\x47\xca\x16\xcb\x75\xe9\xb6\xfb\xaa\x31\xbb\xfb\xe3\x27\x0a\x52\x17\xb5\xeb\xc6\x6c\x27\xde\x0b\xe0\xe2\x26\x33\xfa\x33\x73\x16\xa2\x62\xd6\x0d\xc5\x42\xa2\x3b\x5c\x27\x63\x70\x38\xd2\xb3\x90\xb5\x05\x2d\x54\xbe\x4b\xdb\xf7\x64\x8d\x75\xd7\x72\x84\xc0\x31\x3c\x2f\x23\x5e\xe0\x9f\x7f\xfa\x1e\xf6\x7e\xbd\x76\xa4\xb3\x2d\x76\x91\xf9\x01\xc7\x34\x3c\x6f\xee\xf7\xcf\x3f\x7d\xef\xbf\x60\xb5\x3c\x71\x4b\x36\x52\x34\xa0\xae\xde\x7a\x2a\xdb\x7d\xe5\xeb\xe1\x74\x45\x18\xc6\x8d\x37\x10\x3e\x7a\xef\xd3\xb2\x6d\x79\x1f\x59\xf2\x3e\xf2\x5e\x8c\xea\x5c\x53\xd3\x2b\x76\xb8\x24\x78\x0f\xd0\xf4\x3b\xe9\x06\x99\x23\x74\xa7\x47\xee\x9e\xac\x7a\x85\x5d\xb9\xeb\x87\xfc\x1c\xe6\x45\x63\xfe\x0e\x45\x43\x2d\x10\x0e\x78\xae\x9b\x42\x9f\x50\xd7\x0a\xd1\x1f\xa0\x73\x8e\xd5\x04\xc5\xa5\x9f\x6c\x71\x06\xbb\x56\xbd\xf5\x0a\x13\x8d\xfb\x1d\x16\xea\xe3\x04\xb4\x1c\x36\x40\xd3\x8e\x4f\x9f\xe3\xb3\x60\xee\xb9\x04\x4f\xf8\xd0\x55\x2e\xe0\xd8\xd5\x78\xc4\x85\x55\x69\x2d\xc5\x5c\x15\x2d\x7a\x16\xbe\x78\xfb\x06\xd0\x6c\x95\xf7\x1f\x52\xb3\xba\x2c\xbd\x8f\x28\x33\x97\x2f\x5d\x65\x7d\xbd\x00\x00\xac\xa4\x81\x10\xba\x7e\x7d\xdd\x79\x87\xf9\xbb\xd4\x90\xa3\x33\x39\x9c\x2e\xed\xa4\x0f\xf2\x67\xc6\xdf\xf5\xc0\x8f\xf7\x85\x99\x9b\xa6\x31\x39\x2e\x7e\x4e\xbf\xc2\x7c\xf3\xfb\xc1\x90\xef\x0b\x4c\xf4\xfb\xa2\x53\xd2\x4f\xfc\x20\x03\xcf\xf2\xa5\x59\xd6\xcd\x55\x16\x56\xe6\x5d\xab\xdb\xb5\xdd\xcd\xc1\x41\xc6\x89\x3a\x3e\x57\x30\x2e\x32\xbc\x7e\xee\xe6\xd0\xcd\x8b\xf8\x09\xc7\xce\x57\x43\x1b\x5f\x0d\x5a\x76\x48\xb5\x00\x2c\x0c\x79\x50\x54\xed\x05\x56\x92\x33\xbe\xf3\x9e\xbf\x5c\x47\xfc\x82\xf1\x7e\x44\x0b\xef\xbd\xf2\x1a\xa4\x2a\xdf\x3b\x13\x9c\x97\x44\x4a\x37\x7d\x52\x37\xad\x5a\x1a\x6b\xf5\x29\x97\x6d\x9e\x9d\xa0\xaf\x44\x36\xd3\xd5\xcc\x94\x26\xcf\xfc\x77\xaf\xf4\x99\x51\x97\x0b\x54\x1e\x61\x33\x07\xc1\x37\x40\xe7\x57\xef\x50\x94\xdb\x1b\x09\x49\x1d\x2e\x29\xcb\x34\x42\x2d\xb4\x5d\x00\x7c\x68\x64\xa9\xc0\x80\xe5\xd8\xce\x27\x69\xf2\x99\xb9\x12\xb2\xac\x23\x60\xe0\x56\x15\x45\xf0\xd1\x38\x23\x70\x65\xaf\xe3\x4a\x68\x4f\x22\x18\xc7\xef\x0e\x90\x54\xd2\x5b\xef\x46\x05\x2d\xaa\x03\xc5\x1e\xd9\xe4\xb3\xd7\x4b\xf0\xd4\x70\x18\x2b\x4d\x92\x52\x47\xd8\xff\xa3\xfd\xe3\x1e\x65\x37\xbe\x52\x8f\xa5\x5e\xa5\xa3\x13\xd9\xf2\xdd\x49\x6b\x3e\x33\x57\x3d\x80\x00\xd1\xc7\xc4\x53\x50\x15\x3e\xca\x8b\x22\xaf\xe5\xd4\xde\xc8\xa5\xfc\x49\x5f\x48\xf4\x06\xb7\x64\xcf\xca\x32\x5e\x35\x89\x68\xd3\x01\x49\x90\x4b\x74\xb8\x61\xe6\xa6\x01\x12\x37\x69\xfe\xb9\xbb\x80\xd0\x74\x83\x4b\x80\x6f\xac\xdb\x38\xe2\x5c\xdc\x81\xbe\x4e\xfb\xa7\xbc\x23\xf9\x8f\x4f\x7c\x01\x5d\x16\x6b\x49\xdf\xf5\x1c\xc5\x23\xaa\xf4\xf8\xae\xd7\x11\xac\x76\xe7\x58\xa7\x58\xd5\x1b\x16\x8f\xb1\xe3\xd2\x59\x7a\x7b\x6e\x9a\xa6\xc8\x85\xb3\x44\x6c\xd3\x97\x53\x57\x53\xd9\x37\x64\x75\xdf\x94\x61\x7c\xf3\x6c\x08\x8b\x7d\x64\x6b\xfd\xd4\xde\xde\x41\x59\x05\x69\x95\x7d\x5b\xea\x55\xb2\x9c\x33\x0f\xd6\x4c\x5d\x8d\x8b\x48\x0a\xf1\xd7\x98\x3e\x78\x7d\x77\x0e\xc6\xe9\xe4\x3b\x64\x02\xf4\xef\x57\xbb\x6c\x75\xad\xcc\x45\x48\x40\x0b\x41\xf2\x17\xe0\x62\xad\x5b\xc7\x02\x5a\xd3\x9c\x1b\x0b\xd9\x02\xeb\xca\x08\x5d\x6f\x18\xc8\x11\xb6\xe5\xd6\xf7\x48\x75\x1f\x8f\x5c\x17\x7c\x99\x5e\x12\x90\xa8\x08\x91\x3d\x37\xb3\x35\x31\x23\x7a\xb5\x6a\xea\x55\x03\x4a\xdf\x64\x3a\x99\x6e\x8f\x75\x79\xa1\xaf\xec\x00\xdb\xc2\x47\xd8\x95\x48\x4b\x7b\xf3\xe7\x16\xf3\x39\xdc\x18\xd2\x1e\x8b\xaf\xe0\x9e\x89\xa2\xd0\xa0\xa9\xf7\x78\xc7\xcb\x65\x04\x3e\xea\x3d\x31\x18\xa1\x90\xe3\x73\xe8\x66\x8a\x16\xb9\xed\xfa\xa8\x6d\x05\x6f\xfc\x31\xb4\x3b\x10\x95\xa6\x51\xef\x5b\x79\x5d\x99\x81\xda\x1b\xf5\x95\xe9\x19\x2c\xfc\x73\x13\x92\x07\x3c\x43\x38\xfd\x5c\x72\x22\xfc\x63\xbc\x6a\xea\x65\x61\xcd\x80\xfd\x08\xc7\xcc\x80\x80\xf2\x36\xe6\x45\xc6\x3a\x47\x26\x9f\x96\x82\xac\x79\x07\xb4\x34\xae\x9b\xe2\x35\xc6\x96\xf2\xcb\xb9\x2e\xca\xd0\x25\x72\xee\x81\x00\xa3\xd9\x42\x37\x7a\x06\xea\xf1\x07\x7f\x79\xf2\xc5\xfe\x14\xa5\x58\xa4\xb3\xae\x7b\xb5\xd7\x68\xb8\xc1\xe4\x79\x08\x12\x22\x75\x3a\x9b\x1c\xd5\x40\x08\x61\x4b\x70\xab\x42\xef\x12\x55\xb4\xfc\x3d\x05\xad\xce\x75\x69\xaf\x50\x50\xaa\x08\x3c\x23\x96\xb8\x31\xe4\xe1\x8b\x69\x88\x71\x9f\x5d\xa1\xd4\xed\x4e\x8d\x17\x9f\xb8\xda\x5f\x8c\xd2\xa5\xad\xc1\xc1\xc2\x55\xe7\x6a\x06\xa1\xc4\x90\x59\x54\x9f\xeb\xa2\x64\xf6\xdc\x8e\x51\x74\x1a\x28\x10\xe4\xd0\x89\x84\xfe\x88\xfc\xf7\x87\x14\x86\x27\x30\x58\xdd\x9c\x8d\xe0\x21\xac\xb3\x78\xc3\xd3\x32\xea\xd1\xbf\xee\xa8\x6c\x32\xc9\xbc\x3f\x32\xe4\xb5\x2b\xb4\x25\xf9\x92\x21\x22\xda\x1a\x09\xaa\xb6\x6a\x65\x1a\xd5\x16\xb3\x33\xd3\xaa\x07\xfb\x8f\xf7\xf6\xbe\xc4\x7e\x13\x94\x27\xbb\x3f\xd2\xe7\xd7\xd7\xfe\x09\x27\x9d\x95\xef\xf0\x69\x68\xfa\xe5\x65\xeb\x56\x5c\xb8\x07\x30\x08\xa3\xb0\xf5\xa7\xe8\xcc\xc2\xf0\x8b\x7e\xda\x80\xa8\xf9\x09\x3e\xec\x6e\xae\x8e\xc5\xb8\xd5\x4c\x4a\x68\xec\x92\x51\x80\x8f\x02\xe0\xc8\xa3\x8e\x28\xb8\x2c\xf1\xbc\x4e\x17\xb5\x6d\xa7\x70\x90\x97\x85\x85\xd6\xb6\x83\xbd\x1d\x6a\x7d\x81\x95\xa6\x40\x51\xab\x6e\x10\x05\xac\x77\x1a\x3d\x81\x27\x38\xa9\x4b\xdd\xbf\x3f\xc0\xa0\x0c\x0f\x3b\x42\xbf\x71\x69\xef\x1f\x1c\xf4\x2c\xf8\xf5\x35\x97\x79\xdc\x5b\xe6\xb1\xb4\x27\xfa\xfa\xbe\xc0\x2f\xa3\xfa\x41\x1b\x00\x69\x8f\x33\x75\xa8\xb2\xaf\xf7\x32\x35\x55\xd9\x97\x5f\x7e\x81\x50\x25\xf7\x0f\x0e\x98\xa6\xa5\x8a\x7f\x5f\x5b\xb7\x7b\x77\x54\x8a\x7b\x3b\x4d\xc5\xc8\x3a\x53\x8c\x37\x9b\x47\xf9\xc6\xb5\xe0\xf9\x68\x45\xa0\x18\xb8\x1a\xc8\x50\x34\xc2\x93\xad\xe7\x5c\xa2\x37\x38\x83\xde\x1d\x08\xb5\xa5\xf6\x9b\x70\xe4\x76\x74\x50\xe8\x77\x53\x46\x82\xd9\x6f\x25\x43\xfc\xb6\xee\x70\x99\x0f\x85\x47\xca\x0a\xb7\xf9\xe0\xdd\xbd\xed\xd5\x3b\xbc\x65\x2f\xb4\x45\xe1\x08\x61\x15\x8a\x1c\x37\x2b\x55\x34\x52\x90\x86\x19\x30\x2f\xc3\xa4\xf4\x48\x1f\x9c\x16\xd3\xb5\x94\x0c\xe4\x17\x03\x1a\xd6\x79\xd1\x98\x54\x3d\x61\x55\xed\x16\x00\x34\x17\xda\x9e\x81\x0d\x72\xfb\x5e\xa4\x9e\x00\x31\x13\x3f\x0b\xfd\xff\x05\xb8\x79\x0c\x34\x74\x4c\x8a\x35\xad\xaa\xfd\x98\x42\xae\x1a\x59\xcf\xc3\x87\x5e\x3b\x01\x16\xb1\x9d\x1d\x42\x2b\xf7\x9e\x2c\x42\xf2\xf6\x20\x00\x19\xa8\x32\x5a\xdd\xb4\x59\xba\x40\x3f\xaf\x56\xe8\x1b\xe4\x53\xb9\x45\xd4\x0d\xff\x18\xb7\x35\x94\xf3\xfc\x36\x7d\xfc\xc2\x91\xf4\x65\x51\x19\x11\x83\x02\x61\x66\xc4\xc0\x62\x55\x0b\x6d\x43\x8c\xe9\xfd\x10\x71\x4a\x16\x32\x6a\x4b\x54\xfb\x4e\x13\x72\xe9\xcf\x3f\x7d\x2f\xdc\xa5\x3e\x07\x3d\xd0\x95\xf7\x0c\x75\x25\x5e\xcf\xbd\x0d\x70\xf7\x5d\x51\xcd\x58\x5f\xad\xab\x7c\x52\x37\xee\xf5\x0f\x75\x65\x76\xdf\xc0\x54\x93\x91\xb0\xd4\xee\x22\x42\x55\x09\xeb\xc8\x60\xa8\xa8\xcd\xa3\x1a\xde\xd4\x4d\x50\xd9\x81\xa6\x8b\xc3\x42\x79\x81\xb0\x17\x55\x2d\x47\x4b\x5c\xb7\x1c\xf3\x50\xda\x3a\x5e\x53\x48\x77\x61\xc3\x35\x38\xa2\x20\x18\x7c\xd3\xd6\xee\x1e\x84\xf2\xf2\xf0\x7a\x7e\x49\xf4\x98\x48\xa7\xda\x71\x7f\x62\x18\x3d\xfb\xaf\x72\xa1\xa1\x23\x29\x0f\x81\xa2\x1c\x66\x70\x87\x72\x7d\x01\x70\xfd\xc1\x37\x5f\x7d\xfd\x78\xca\x88\xb1\xf0\xd6\xd6\xc8\x20\x17\xed\xe7\x16\x68\xcb\xda\xc2\xc9\x02\x73\xbd\xdb\x5a\x6b\xf0\xd4\x6b\x1b\x82\x2c\xa2\x6c\x54\x58\x77\x07\x6f\xd0\x31\x2a\x42\x43\x59\x54\xc8\x6d\x44\xea\x04\xbe\x3a\xa0\x44\x37\x63\x9d\xe7\x13\x9a\xd6\xf6\x8c\x31\x02\xe9\x62\x74\x5b\x37\xc7\x9e\x24\x7e\xfe\xdb\xe7\x81\x0b\x01\x9d\x79\x48\x41\x4d\xdf\x72\x85\x82\x8f\x68\xed\x48\x65\x9f\xed\xff\x76\x90\xa9\x1d\x44\x31\x00\xc4\xb0\xa9\x6c\x4f\xc4\x32\xe5\x39\x1a\x51\x08\xd9\x96\xe3\x9a\xc2\x9a\xed\xfc\x89\x85\xca\xa2\x56\xbb\xa8\xab\x94\xae\xb2\xf7\x14\xdc\xb6\xff\x47\xa0\x4b\xac\x54\x31\xf7\xd6\xf3\x65\x9d\x9b\xb1\xb8\x2e\xc4\xab\x3e\xac\x1e\x69\x4c\x3f\x0a\x43\x10\x9e\x13\xc4\x15\x27\x82\xfe\x40\x65\x9d\x9e\x66\xa3\xbb\x6b\xed\xb8\x00\x33\x91\x6b\xf5\xe9\x9f\x6f\x3f\x4c\x48\x68\xbb\x5b\xd3\xad\xf3\x0d\x5e\xb9\xb3\x56\x4e\x28\x9f\xea\x13\xe3\xc8\x84\x95\xe4\x40\x5e\xbf\x82\x2e\xc0\x6f\x61\xcf\x47\xe4\x7a\xd8\xf5\x82\x89\x94\x05\x22\x6f\xc5\xbe\xd1\x45\x7e\xf6\xa3\xa4\xfa\x94\xf2\xf3\x60\x9e\xa1\x81\x9d\xa9\x23\x3b\xa3\x83\x60\xdc\x8c\x14\x4a\xfa\x6e\x50\x75\x95\xc6\x72\x6f\xea\x09\xf4\x32\xc3\x8a\x49\x1b\xd9\x89\x0f\x82\xe1\x93\x71\xff\x48\x7a\xb6\xa2\x7f\xf8\x21\x1f\xfb\xcd\x45\x76\xd4\x40\x75\xaa\x65\xef\xbe\x43\x4c\x59\xb0\xe3\x7d\x05\xdc\x89\x7a\xaa\xfe\x79\xb0\x37\xde\xdb\x87\x63\x26\x12\x37\x88\x56\x20\x4a\xc9\x3d\x15\xf7\x11\xba\xf0\x83\xb7\x0a\x69\x1c\x03\xca\x1c\x2a\x23\x0a\xf4\x95\x5d\x24\xca\xca\x4d\x0b\x55\x8c\x42\x61\x40\x36\xeb\x4b\xb5\x5d\x5f\xb0\x09\x97\x4a\x4e\x96\xc5\xd2\xa0\x81\x1d\x42\x5f\x74\x53\x5e\x21\xd7\x23\xb6\xda\x89\x99\xd7\x8d\x79\xe7\xae\x13\x50\xf3\xcb\x27\x84\x26\x9b\x68\xed\xbd\x17\xb4\x25\x60\x3f\xbf\x07\x63\x16\x49\x44\xb6\xa2\xca\x99\xd8\x4e\x27\xeb\x06\x42\xeb\x9d\xad\x3a\x0c\x15\x49\xf7\xe9\x48\xe1\x29\x20\x25\xb8\x9b\x46\x95\x75\x75\x6a\x1c\x47\x84\xda\xec\xd2\x67\x74\x95\x9a\x6e\xf8\x26\x13\x9c\x60\x65\x5b\x5d\x96\x41\x79\xe2\xf6\x6a\x24\xe4\x8b\x65\xfa\x43\x91\xb4\x3e\x55\xfb\xde\x8b\x6a\x7f\xe4\x45\xfc\xa9\xda\x57\x37\xa9\x67\x70\xa1\x8e\x07\x6a\xc3\x5a\x01\x22\xa1\x00\x8a\x08\x0a\x0d\x40\xb6\xbc\x95\xd9\x0d\xe6\xce\xbb\x99\x5d\x76\x6d\x00\x2b\xa0\x13\xca\xf4\xba\xad\x77\xe3\x0d\x70\xbf\xab\x61\x41\x95\xc9\xee\xfe\x08\xfc\xc3\x7c\xe3\x59\x5f\xd2\x56\x5c\xa8\x60\x1a\x50\x07\x6a\x5f\xb8\xe5\xc2\xb6\x92\xdc\x6f\x20\xc9\x92\x49\xf5\x64\xb8\x6b\x87\x0a\xb8\x54\xc8\x93\x9a\x2a\xcf\x46\xea\x28\x6c\xc1\x84\xdc\x4f\x26\xea\x3d\x9a\x16\x25\x97\x00\x5e\x51\x48\x41\xd8\x16\xf9\x37\x89\x56\x2e\xad\x91\x8e\xb3\x33\x2d\x55\xd2\xcd\x06\xe1\xf5\x6b\xb0\x39\x33\xfa\x32\xf3\xa1\xc3\x23\xd1\x46\x82\x05\x2c\x3c\xfd\xac\x98\xac\x58\xa5\x65\xc1\xca\x1e\x2b\x8c\x47\x78\x66\x3c\x6e\x73\x8f\xfb\x1f\x84\x77\xd7\x2b\x7d\xea\xea\x0d\x28\x10\x9a\x5c\x1e\xe5\xd9\xc3\x0f\x36\xea\x4b\xc3\xf2\x1b\xc9\xf4\xbd\x2b\x96\x2b\x48\x28\x8b\x58\x13\x35\x33\x31\x34\xec\x58\x63\x89\x65\xfa\x73\x19\x33\x8d\x64\x0d\xab\x3b\x69\xa0\x35\x30\xe7\xa6\x21\x87\x9e\xc2\xfa\x9e\xfa\xa0\x0c\xec\x17\xea\x0c\x47\xaa\xd2\x4e\x9a\x79\xe7\x35\x88\x22\xde\x6e\xa4\x52\xb2\x0a\x11\xd2\xec\x41\x3f\xe2\xe3\x4c\x67\x59\x86\x77\x2c\x89\x9d\x18\x6d\x0b\xdd\x34\x69\x2b\xd3\x16\xa5\xf7\x39\x60\xc3\x80\x7d\x4f\xec\xba\x3e\x6b\x55\x1f\xae\x37\x29\xc9\x81\xff\xcc\x72\x00\xd1\xad\xea\x0b\xbc\x04\x69\x9b\x3c\x96\x8d\x95\x46\x37\xde\xa4\x8e\x66\x5e\x48\x3e\x6f\x43\xdb\xd1\x7e\x0e\x92\x80\xfb\x92\x37\x76\x52\xa6\xd3\xa5\x17\xa6\x31\x90\x8c\x67\x66\x84\x16\x76\x0e\x10\x05\xee\x1e\x39\xd5\xcd\x89\x3e\x35\xa9\x25\x79\x32\x51\x83\xaa\x56\x4b\x0d\x79\x97\x16\xf5\x05\x10\x68\x11\x73\x43\x3a\x42\x40\xf7\x20\xe0\x96\x21\x9d\x8e\x40\x04\xa5\x5f\x44\x98\xe4\x99\x08\xe9\xb9\xdb\x25\x41\x1d\xf8\x7d\xc0\x89\x1a\x02\x59\x6a\x55\xa0\x59\x9b\x08\x19\xa9\xcb\x01\x4d\x4f\x7d\x29\x61\x84\x53\x49\x96\x36\xd4\x7c\x4d\x62\x98\x0f\xd6\x08\x95\x1c\xa8\xc7\x7b\x7b\x40\x81\xf0\xc1\x5f\xd5\x17\x7b\x7b\x7c\x67\xae\x2d\x26\x94\xdd\xfb\x52\xb4\xf0\x77\x23\xc2\x19\x1c\xd3\x12\x96\xb7\x1b\x5f\x27\xfd\x86\x3f\x3d\x2e\xb5\xb3\xe8\xac\x25\x0a\x2b\x78\xe1\xa4\xba\x01\xc8\x76\x17\xfa\xaa\x2f\xa2\x0a\x7d\xa9\x2f\x34\xb8\xff\xb5\xc3\x68\x41\xa8\x37\x9f\x1a\x4b\x95\xc0\x9a\xfb\x59\xe5\x7c\xd8\xa8\x61\x9d\x2d\x74\x51\x45\x20\xe6\x49\x38\x56\xa0\x59\xff\xdd\xe2\xce\x6d\x02\xcf\xd6\x16\x53\x0f\xaf\xb8\xef\x89\x6c\x8d\xbc\x90\xb3\xd8\x14\xb9\xec\x56\xb9\x75\x97\xac\x73\xe0\xbf\x4a\x2d\x1f\x9f\xd2\x1b\x27\xc6\x7c\x7a\x27\x3a\x42\xcf\xc6\xc6\xa5\x23\x3f\xdc\x3c\x52\xe5\x21\xe8\x23\x6d\xfc\xc7\x7b\x5f\x06\x5d\x37\xea\x37\xbf\x7b\xf9\xec\x85\x84\x1f\x89\x48\x71\x56\xd5\x54\x5f\xf6\x34\x6d\xa9\xf5\x7d\x8a\x6e\xa6\xb4\xc9\x2f\xf6\xbe\xbc\xa5\xf6\x96\xeb\xc8\x92\x60\x1b\xd6\x6c\xa3\x2a\xb3\x34\xed\xe7\xd6\x67\x40\x20\xdc\xd6\xf4\x2e\x8c\xea\xe6\xdd\x0f\xb6\x38\x6f\xcf\x0c\xd6\x20\xff\x3e\xe8\x45\xb6\xb6\xd8\x1a\xe4\x5f\xc2\x03\xbf\x6a\x82\xda\xdc\x97\x6f\xe8\xda\x8d\x7a\x83\x8a\x49\x43\x46\x04\xac\x18\xdc\xfe\x43\x2f\x7d\xc1\x16\x41\x89\x9b\xa5\x2e\x01\x8b\x35\x8c\x03\x8d\x4c\x30\x97\xe0\x3a\x5f\x57\xc8\x55\x92\x0d\x92\xfb\x6b\xe5\x5d\x99\xae\xfb\xf5\x35\x1a\x9b\x3b\x56\xc2\x78\x2d\x30\x78\xa1\xe3\x06\x02\x14\x34\x4a\x4a\xc7\x6b\x1b\x52\xe5\xa5\xb1\x09\x92\xfa\x83\x80\xcd\x92\xeb\x9c\xbc\x5e\xa4\x5b\x57\x64\x31\xe5\xa1\x3c\xed\xbc\xa2\x6e\x0e\x3a\xdc\x41\x20\xed\x34\xbc\x9d\xe4\x0a\xc2\x35\x9b\xbc\x74\xe3\xdb\x48\xc9\xb6\x84\xdf\xd3\xb8\x31\xb6\x2e\xcf\xcd\x2f\x45\xbb\xe8\x91\xc9\x8e\x02\x5b\x63\x05\x57\x84\x97\xee\x71\x7f\xce\x0f\x51\xb5\x1b\xf8\xc6\x9a\x99\xd9\x16\xf5\xe2\x1a\x1f\xf7\xdc\x21\x77\x18\xfc\xe5\xec\x3d\xaf\x73\xcf\xd2\x81\x37\x15\x5b\x71\xa4\xbb\x55\x87\x17\xf8\xd7\xc4\x87\x30\xb3\x87\x24\x4a\x50\x34\x8a\x13\xed\xc1\xc1\x15\xc3\x64\x68\xf3\x84\x41\x8f\xa2\x4f\xf9\xa8\x4e\x6f\x99\x81\xe7\x24\x18\xc2\xef\x8e\x21\xd8\xf5\xfc\xd3\x67\x9a\x1a\xf8\xaf\xca\x4d\xdc\xa5\x0d\xb2\x93\xb0\xee\xba\x03\x41\x12\xdb\xb3\x7f\x3c\xfb\x55\xcd\x30\xf6\x46\x1c\xe0\xfb\x03\xb5\xbb\x1b\x19\x15\xa2\xfc\x6e\xb7\x19\x14\xea\x55\xd6\x8f\xb1\xb4\x7d\xaf\x6b\x4c\x21\xcf\x83\x53\xd3\xfe\xe3\xdd\xdb\x1f\x3a\x0e\xbc\x48\x82\xbd\xa3\x46\xec\x4c\x4d\x9d\x80\x64\x48\x3d\xa5\x47\x2a\x03\xbf\xfc\xc8\x63\xf9\xd4\xb4\xef\x20\x44\xa3\xd3\xd4\xa7\x36\x22\x92\xaf\x88\x96\x28\xee\x23\x45\xba\x8d\x60\x91\x8e\x30\xad\xd3\x48\x65\xab\xda\xb6\x31\x7a\xba\x2a\x46\x6c\x6b\x96\x40\xea\x47\xfc\x30\x06\x89\xee\x1d\xad\x74\xf5\x99\x4c\x14\x44\xed\x05\x54\x5f\xaf\x8e\xe4\x27\x98\xe7\x0d\x1d\xdd\xb7\x6f\x81\x30\x23\x43\x03\xaf\xbd\xc8\x55\x29\x9d\x42\x71\xc1\xfd\x1c\x62\x48\x71\x00\x6a\xdb\xe4\x06\x1d\x4f\xb2\xdb\x3f\x03\x11\x25\xe0\x86\xe9\x1b\x9d\xd2\x54\xc4\xe0\x6d\x53\x04\x5a\xf1\xcf\x30\xaf\x1b\x69\x17\x59\xa3\xc3\xdd\xda\x0e\xa9\x69\x9e\x4a\x34\x7c\x72\x00\xd1\xea\x64\x5d\xcd\x16\xaa\x9e\xfb\xa9\xc6\xbb\xcf\x1b\x7a\x28\xc1\x15\x9c\x19\x34\xf4\x75\x97\x38\x58\xd5\x46\x2a\x9c\x88\x51\xe7\x88\x4a\x7a\x14\x13\xab\x91\x50\x83\x74\x36\x89\x58\x65\x01\x24\xde\x32\x20\x97\xc4\xe9\xbe\x0d\x77\x5a\xc0\x32\xcb\x0c\xee\x54\xe5\x6f\xe6\x5c\x97\x3f\x83\x69\x25\xda\x74\x31\x24\x72\x67\xd5\xa2\x45\x4b\x23\xe2\xc2\x8a\xf1\x61\x91\xb1\x6c\x21\xe4\x8b\x63\xe0\xc2\x13\x8e\xc2\xf4\x31\x22\x37\x12\x76\xb9\x17\xb5\xfc\xa2\xd1\xab\x67\x65\x94\x33\x0e\x02\x82\x04\xbe\x99\x2b\x72\x07\x7a\x1f\x7d\x92\x18\x82\xff\x5c\x52\x53\xea\x09\x56\x16\xe5\x33\xbd\x2d\x85\x3b\x66\x40\xf6\x90\x1c\x7c\xe9\xbc\x0f\x59\x20\x21\x62\xc0\x55\x8e\x26\x5a\x8c\xcd\x40\xf4\x6b\x28\x0d\xaf\x42\x8e\x13\xd7\xfa\x28\x54\x3b\xae\x2f\x2a\xd3\x78\xd8\xe3\xe1\xd8\xfc\x73\xe0\x58\xad\xf1\xac\x04\x0d\x0c\x46\xd7\x76\x52\x99\xe1\xb7\x21\x2f\x4b\x18\xb5\x6b\x6e\x8c\x31\xcb\xdf\x82\x6a\x39\x1a\x43\x7c\x7b\x42\xd9\xa5\x5e\xf5\xe8\xdd\xdc\xc2\x88\x7c\x7d\x9d\x7c\x20\x90\xba\x00\x20\x57\x08\xf2\xf3\xf9\xa2\x28\xf3\x24\x4d\x06\x27\x26\xe9\x94\x7b\x9a\x08\x2e\x22\x79\x02\xaf\xc4\x18\xad\xae\xbc\x7c\x3d\xb4\x2a\xc9\xf6\xeb\x06\xf3\xba\xaa\x62\x87\x55\xb9\xd7\xfe\xa7\x37\x17\x34\xfe\xe9\xdb\xeb\xee\x54\xb8\x04\xfe\xb7\x31\x4d\xad\x84\xac\x32\xe5\xdc\xa3\x56\x0d\xe2\xfd\xc2\x8f\xd3\xd4\x8a\xfe\xfb\xf8\x68\x84\xdd\x16\xb3\xaf\x98\x13\x96\x16\xc5\x17\xec\xcd\xc6\xe9\xea\xbb\xed\xc4\xdf\x95\xf3\x2f\xea\xc6\x27\xad\xc7\xa6\xb3\x2e\x5a\x3a\xec\x5b\x99\xa9\x1c\x49\x34\x86\x75\x95\x8c\xa2\x87\x86\xe3\xf9\x1b\x0c\x6f\x4b\x65\xdc\x4d\xaa\x44\x09\x4e\x4f\xea\xfc\x2a\x93\xbc\x5c\x27\x6b\x3c\x98\xb9\x91\x79\xc5\x64\xaa\xee\xe8\xb8\xd3\x6e\x93\xa9\x1f\xbb\x35\xe9\x40\xfb\xfb\xf0\xee\x55\x33\x26\xeb\xc6\x78\x51\xe4\x39\xa4\xc0\xef\xcd\x8e\x22\x01\xea\xdf\xae\x4c\xa3\xd5\x5f\x0f\xd4\xfe\xe3\xf1\xfe\x63\x7c\x89\xcf\x1a\x83\x01\x60\xf5\x7c\x6e\x4d\xfb\x4b\x91\xb7\x0b\x34\x79\xe1\x83\xef\x4c\x71\xba\x68\xad\x02\x04\x80\x76\xa1\x2b\xf5\xbb\x69\x6a\x55\x57\xca\xd6\xcb\x40\x35\xc3\xed\x85\xb9\x8b\x42\x65\xae\x51\x50\xde\x89\x17\x58\x29\xbc\xa1\x1b\xa7\x6f\x74\xe7\x85\x05\xb0\xac\x0d\xc3\x63\xbc\xc5\xcd\x13\xc3\xc5\xc5\xad\xb6\xcd\x79\x10\x1e\xef\xa9\x03\x35\xf9\x7f\x1e\xef\x4d\x20\xfe\xaa\x39\x69\x34\x38\x1d\x1e\xa8\xc9\x87\xa3\x0f\xc7\x84\xc7\xfe\xfc\xa7\xef\x5f\x61\x16\xd5\xc3\x0f\x15\x95\xc4\xcc\x26\xad\x69\xd8\x5d\x10\x90\xdc\xf1\xe9\xf5\xc9\xba\x6d\xeb\xea\xba\x58\xea\x53\x40\x80\x37\x2d\x80\xc1\x0f\x3f\x9b\x14\xf2\x63\x8d\xe3\x82\x2f\x01\x96\xe3\x1a\xa1\x1f\xaf\x9d\xf8\xa1\x1b\xa3\xaf\xcf\xcc\xd5\xa9\xa9\x86\x93\x02\x3a\xee\x15\xf9\x27\xeb\xa2\xcc\x7f\xd4\x8d\x5e\xb2\xf3\xd6\xe5\xc8\x89\xde\x23\x25\x1c\xc3\x46\xe0\x1c\x11\xd0\x95\xc8\x9d\x9e\xa1\x88\xd2\x24\x40\xf5\xc9\xc7\xb0\x71\x41\xc6\x47\x9c\x75\x43\x49\xb9\x8a\xd6\x2c\x41\x83\x17\xb1\x64\xd0\x68\xc4\x42\x9d\xc7\xfe\x0b\xd2\x53\xed\xfa\x5a\xf1\x0c\x93\x2f\x06\xf6\x5d\xc5\x20\xbb\x98\x2b\x13\xc0\x87\x42\xd3\x18\x24\x6c\x67\xba\xd4\x0d\x29\x12\x75\x9e\x87\xd1\x9f\x6f\x22\x71\x93\x89\x7a\xed\xbe\x27\xf4\x1a\xac\x41\x0d\xb0\xe6\x9a\x35\x16\xc3\x91\xc2\xf8\x7d\x70\x51\xa9\xd6\x4b\xd3\x14\x33\xcc\x0f\x47\xad\xf5\xcc\xb9\xda\x51\xd9\x51\x06\x46\x71\xce\xb7\x19\x47\x2f\x1e\xaa\x82\xcd\xde\x3b\x2a\x3b\xce\x46\xea\xbc\x6f\x89\x52\x92\x1b\x90\xe3\xbc\x81\xd1\xcf\x61\xf0\x46\x73\x4d\xf2\xb2\xf5\xc5\x4c\x46\x6b\xc8\x91\xbc\xbc\x88\x68\x9c\x85\x20\x8a\xa2\xa2\x4a\x70\xc2\x6e\x1b\x67\x45\x69\x8d\xdd\x48\xea\x93\x8f\x1c\x85\xb1\x71\x4c\x37\x72\x2c\xdd\x4e\xd1\x5a\xf8\x4e\x45\x0b\x0a\x7d\x8a\xd0\xcd\xa2\x3d\xc9\xb9\xe2\x9c\x38\x51\x37\xcb\xc0\xb8\x81\x6f\x1f\xfa\xf5\xc1\x37\x67\xe6\x6a\x42\x79\xc8\x30\xd0\x58\x61\x64\x1d\x3b\x6c\x4a\x17\xcb\x88\xc8\xe8\x68\x58\xe2\x20\x51\x0f\x5d\x8f\xdd\xc1\xa7\x24\x8c\x6e\xd4\x07\x71\x38\x56\x1a\x55\x83\x0a\x50\x9f\x97\x4c\xfb\xd2\x23\x55\x54\xe7\xf5\x99\xdb\x7c\x12\x3b\x25\xf6\x96\x8a\x13\xeb\xf5\xe5\xd3\x55\x87\xf8\xd7\x60\x08\xf0\xa4\xb7\xa4\x5b\x65\x2d\xd1\x91\xf2\x1c\x84\x93\x6f\xf0\x08\xfc\xfc\xd3\x6b\x27\x49\xd5\x15\x80\xbe\x63\x58\xd9\x8e\xca\xc0\x35\xaa\xaf\x84\xac\xf2\xc6\xe3\x88\xbd\x43\x13\xbd\x9f\xbf\xb6\x46\xbe\x37\x40\xb0\xc3\x45\x34\xfe\x62\xfc\x18\x13\xba\x15\x35\x1c\xec\x0e\xd5\xe8\xc5\xc2\x8c\x0a\xf4\x46\x69\x0b\xb7\x4d\x19\x5a\x2e\x3e\x4c\xf1\x04\xfd\x9e\x82\xfc\xea\x98\xe9\xbd\xa8\x46\x4a\x5b\xbb\x5e\x1a\xf6\xce\xa3\xd8\xe6\xfe\xdd\x37\xde\x44\x5d\x35\xba\x83\x0f\x94\xe6\xc8\xce\x87\x0f\xfd\xa5\x55\xd8\x1f\x4b\x5d\x54\x6f\xe1\x8c\x62\xd9\x7e\x4a\xdc\x22\xd2\xca\x52\x5e\xb8\x31\x3d\xd6\x9d\x9c\x71\x74\xac\x30\x19\x2e\x84\x7a\x89\xd4\xb2\x82\x47\xea\x1e\xd4\xd7\xf3\xf8\x5c\x13\x81\x74\x9d\xc8\xea\x32\xcf\xc0\x9c\x35\x80\x74\xf7\xfa\x8a\x56\xd2\x11\xd4\x92\x62\xa7\x26\x13\x95\x17\x90\xd8\x7e\x14\x8c\xdd\x5c\x0b\x9c\x37\xab\x1a\x33\x5b\x37\xb6\x38\x37\xe5\x95\xa0\x4b\x44\x76\x20\x72\xe8\x16\xba\x34\x52\xfa\x88\xcb\xde\x4a\x84\xc2\x32\xff\x14\x70\x1e\x1b\x63\xd7\x65\x8b\xae\x63\x22\xa5\x48\xe0\x29\xec\xf8\x63\x5d\x54\x03\xf0\x11\x94\x31\x10\x8f\xf7\x46\x88\xec\xee\x39\x8a\x5e\x29\x99\x6b\x35\x1b\xf9\xcd\xd8\xbb\x1b\x96\xc5\x7f\x84\xfb\x66\x28\x92\x55\xc5\xaf\x6e\x67\x62\x7b\xe5\x3f\x8c\x3e\x82\x99\x59\x35\xf5\xea\xbb\xba\x46\xd7\x81\x8c\x77\x13\xa0\x15\x51\x42\x04\x47\x46\xf3\xbc\xbb\xdb\xbc\x10\x49\x42\x0a\x8f\xa1\xa9\x57\x9e\x0b\x0e\xf5\x11\x9d\x11\x4c\x21\x7c\x76\xd8\x93\xbe\xd2\xbf\xe4\xc4\x57\xb4\x35\xdd\x7f\x89\xa3\xeb\x97\xa6\x58\x67\xc6\xd9\xa0\x85\x89\xe0\x67\x6b\xd4\xb8\xb0\x03\x95\x4d\x65\x2a\x55\x76\xb5\x45\xf3\xab\x69\x8f\xf8\xe5\x31\xa0\xed\xd9\x8e\xc8\x08\xd7\x5c\x38\xb0\x9e\x9d\xef\x56\xcd\x31\x12\x92\xc5\x23\x5e\x27\x4a\x47\x0d\x45\xd5\xfd\x84\x8d\xe4\x92\xa8\x85\x0a\xf1\x16\x24\x29\x60\x1a\xc6\xeb\x6b\x75\xbf\x81\x1f\xae\x72\xc8\x22\x10\x7d\x36\x94\x13\x17\x6d\x04\xc7\x9e\x45\x79\x13\xd3\x6c\xcf\x71\x96\x73\x9e\x48\x91\xe1\xf9\x20\xce\xf0\x8c\xc1\xb0\x52\xd2\x49\x73\x86\x1f\xc6\x2a\xed\x0d\xc9\xc2\x63\xfc\x2f\xc2\xbc\x42\xe0\x23\xcc\xef\x1f\x42\x54\xe1\x06\x13\x87\xd1\xf1\xe6\x23\x95\x7d\x68\x3e\x54\x6e\xfe\x7d\x50\xf2\x4d\xc8\x7e\xff\x5f\xaa\xea\x66\x08\xda\xe9\x4d\x82\x58\x74\xb7\x5c\x2e\x1a\xc9\x02\xe0\xa0\xbc\xcb\x12\xa7\x0f\x33\x17\xea\xd7\x37\xdf\x7f\xd7\xb6\x2b\x72\x51\x1c\xc8\x14\x5f\xe4\x92\x74\xc3\xa4\x05\x52\x96\x2d\x9a\xd7\x39\x47\xa7\x5f\x2e\x9a\x00\x82\xc0\x81\xed\x97\x8b\x86\xf4\x9b\xef\xd8\xde\xc6\x54\xdc\x09\x1e\x21\x66\x8d\xdc\x0c\xae\xd0\xf1\x80\x8c\x73\x40\x90\xf7\xfc\x45\xf7\x78\x6f\xcf\x7d\xbb\x37\x75\x7f\x31\xc0\x6a\x92\xe4\x0c\x9c\xd8\xf7\xbf\x7c\xb2\x37\x05\x09\xb0\x2d\x96\xc6\xaa\xd7\x2f\x3d\x06\xf8\xfe\xe3\xc7\x5f\xa0\x4f\x52\xc1\xe0\x36\xea\xc4\x55\x0d\x91\x5c\xee\xed\x94\x7e\x84\xfe\x43\x03\x12\x73\x20\x9d\xdc\x81\xd7\x29\xc7\xbd\x41\x29\xb6\x0a\x51\x02\x90\x27\xe8\xc4\xa8\xa5\xae\xd6\xba\x64\x97\x4d\xf0\x2f\xe2\x4c\x98\x83\x07\x4f\x1e\x7f\xbd\x37\xdc\xbe\x07\xd7\x35\xa5\xf2\x79\x06\xb6\x98\x5f\xf1\x22\x8e\xf4\xc0\x5c\x44\x0d\x41\xc9\x9b\x61\x2d\x59\xf7\xb6\xc5\x0b\x8c\x40\xec\xdd\x0d\x16\xad\x17\xef\x73\xf9\x90\x10\xe2\x07\xe2\xb6\xf2\x08\xfd\x3e\x49\x6a\x0d\x31\xf7\xf7\xef\x47\x13\x05\xde\xa6\xd9\x45\xd1\x2e\x9e\x37\x26\x47\x90\x56\x9b\x51\xa3\xa1\x98\xab\x8d\x2b\x02\x30\xf8\x03\x95\xcc\x77\x5c\xef\xd3\x64\x7f\x7b\xff\x45\x41\x49\x22\xec\x17\x8c\x2e\x0e\xb6\x0a\x06\x17\xaa\xad\x55\x14\xe8\x06\x50\xa6\x8c\x17\x08\xfe\x3e\xdc\x3a\xe7\x11\x8f\xcf\x04\xf3\x51\xd1\x04\x5c\x5f\xab\x74\xfc\xf7\xbd\xd3\xb6\x08\x5a\x8b\x2f\x44\x0a\xa9\x32\x71\x86\xca\x05\xfb\x05\xfa\x88\xd3\x48\x4d\x5a\xb0\x15\x13\xcf\x34\xb7\x02\x9b\xd0\x67\x58\x76\x53\xb7\xb3\x03\xa7\xd3\xeb\x52\x2f\x17\xcd\xb8\x5e\x99\x30\x45\x63\x34\x08\xf0\x2f\x89\x9c\x83\x4e\x95\xe2\x1d\xc1\xbd\x85\x27\x8c\xf6\x16\xa7\x72\x21\x60\x47\xf4\x54\x26\x1f\xa2\x04\xfb\x96\xb3\x65\x87\x7e\x23\xac\x59\x07\xc3\x14\xfc\x73\x6f\x2b\xe6\x46\x84\x4e\xb8\x07\xdd\x72\x51\x8e\xe8\x1e\xcf\x15\x0e\xb4\x57\xcb\x62\x49\xbe\x47\x09\xa4\x45\xd4\x4d\x1f\x27\xff\xf0\xa1\x82\x89\x4c\x62\xef\x45\xb7\xfa\x5e\xf7\x54\x34\x4c\xb5\xd2\x93\x89\xfa\x75\xf7\x27\xce\xdd\xb3\xfb\x4b\xd1\x2e\xa2\x70\x7f\x42\x03\xeb\x8b\xd2\x84\xfc\x9b\x10\x6b\x80\xe1\x56\xc8\x6c\x52\xe6\x3b\xe0\x43\x4b\x50\x68\xe9\xc6\xf8\xba\xf4\x59\x01\x81\xad\x5a\x7d\x2c\x4e\xad\xbe\x50\xab\xf5\xef\xbf\x97\x06\x7c\x89\x2d\xfa\x83\x56\xe6\xdc\x34\x14\x1d\x43\xa0\x3b\x76\xdd\xb0\xb7\xd4\x64\xa2\x06\x45\x8b\x50\x63\x48\xbb\x4f\x0c\x8a\xb7\x8e\x39\x5e\x99\x66\x97\x83\xc0\x4e\xb4\x2d\x40\xfc\x35\xe7\xa6\x52\x6b\x2b\x70\xa8\xd6\xab\x61\x34\x3a\xab\x97\xa6\x3b\xb8\x0b\x48\xc5\x4e\x09\x7c\x29\x34\xa1\x98\x7b\x3f\x73\xde\x5e\xd2\x8d\xab\xf7\xf8\xb9\x63\xc9\x9e\xf6\x59\x3a\xd9\x99\x04\xfb\xbc\xad\xd4\x81\xca\x62\x92\x90\xf5\x2c\xa5\x13\x32\xa5\x1b\xa3\xdc\xd4\xa9\x0b\x2b\xee\x99\xde\xc8\x80\x9e\xb8\x80\xb8\x9d\xe7\xc2\xc6\x19\x19\x62\x37\x62\x41\xa4\x69\xbc\x52\x9c\x85\xd4\x20\xbe\xb5\x15\x62\xba\xe2\xdb\xa1\xc8\x25\xc2\x81\x68\x1b\x8e\x00\xde\x66\xfc\x83\xfd\x86\x08\x1e\xc4\x7f\xe5\x31\xb6\x50\x53\x84\xce\xfc\x31\x86\x83\xab\x40\x86\x0b\x6c\x6d\x25\xae\x5f\xe1\x73\xce\x19\x2a\x3f\x67\x32\x3a\x08\x8f\x98\xfb\x98\xde\xc1\x7e\xec\x3d\x85\x44\x0d\x0f\xbe\xfe\x6a\xef\xc9\xc8\x71\x15\x8f\xf7\xfe\x22\x6a\x81\x55\x43\x9f\xe5\xde\xa7\xc1\xe3\x6a\xcb\x47\xed\xca\xce\xdf\xd1\xc9\x94\x75\x3a\x52\xa1\x6a\x8c\x20\xfe\x94\x0e\x8c\xe2\x61\xa7\xdc\x52\x78\xf3\x8c\xf3\x09\xaa\x93\xa2\xd2\xcd\xd5\x2e\x18\xf0\x25\x8c\x24\xa6\x22\xb4\x51\x2e\xc2\xb8\x8e\xc1\x83\xfd\xfd\x2f\x1f\x7f\x35\x14\x4f\x49\xff\xe8\x3a\x15\xd5\x15\xa5\x5c\x3a\x94\x73\xc1\x10\x96\xe9\x27\xa2\xc4\x8d\x9a\x0a\x87\x8c\x64\xec\xbd\xc0\x36\x83\x61\xff\x4a\xf0\x5f\x1e\x2c\x83\xcf\x98\xbc\xd6\xbe\x07\xa0\x03\x00\x9e\x3f\xf7\xe2\xe6\x56\xb4\xcb\x79\xf7\xfb\x3d\x1a\x6f\x7b\xff\x9a\xb6\x68\x74\x6b\x0a\x28\x32\x04\x75\x9a\x6d\x3a\xd4\xdd\xf3\x17\xd5\x8d\xa7\x27\xd4\x2d\xe1\x87\x21\xdd\xad\x72\xcc\x46\x94\x72\x01\x8c\x53\x90\x67\xb2\xd1\x10\xb6\x28\xd6\x76\x18\x51\xa7\x2a\x0f\xb7\x58\x1c\xb9\x26\x93\x3e\x01\x3c\x0e\xc4\xf8\xf3\x44\xf6\x02\x1a\x23\x93\xfe\xd5\xd7\x5f\x4c\xd5\xdb\x4a\x84\x1e\x14\x73\x14\xf4\x16\xda\x22\xe4\x24\xb8\x29\xb6\xe8\xb5\xaa\x71\xeb\xc1\x94\x5e\x19\xde\x0f\x1b\x89\x56\x1c\xa8\x90\xb8\x0c\x32\xf2\x49\x8a\x6e\xe2\xbf\xdf\x54\x6d\x67\xa1\xa5\xb3\x53\x2a\x8b\x91\x50\xc0\x21\x49\xe8\x00\x21\x82\xe6\x3a\xe0\x72\x7f\x00\xbc\xb1\x04\xb9\xb5\xe4\xb6\x94\x25\x58\xb3\x10\x28\x1c\xe0\x68\x37\x3c\x37\xb3\x65\xef\xf3\xcb\xdd\xf0\x26\x63\x59\x27\x41\xac\xe5\x96\x27\x83\xc3\xa9\xab\xff\xda\x7d\x32\xc4\xa7\x13\xf1\x8d\x84\x71\x65\x6c\x53\xaa\x39\x82\x24\x92\xae\xa0\xec\x5e\x45\xbe\x6d\xba\xe4\xf7\x91\x5a\xa6\x65\xf7\xd2\x9b\x68\x5e\x83\x43\x1b\xf8\x2b\x7f\x6e\x7d\xaa\x30\x08\x0e\xd7\x55\xae\xc4\xad\x1f\xcd\xb2\x0f\xbd\x1a\x04\x77\x14\x09\x6d\x43\x1d\xec\x04\x20\x77\xd4\xbc\xfe\x65\x48\xc4\x76\x23\x3e\xec\xf2\xfc\x3e\x8a\x1e\x5c\x63\x9e\xa6\x03\xfa\xb6\xa8\x72\xde\x1f\xad\x3e\x55\x0b\xb7\xeb\x44\x20\x59\xaf\xd4\x73\xeb\x18\xc0\x6f\x04\x12\x0c\x73\xec\x05\x88\x3a\xb9\xd1\x25\x45\xab\xcf\xa4\x1c\x24\x90\x06\x36\x0f\x02\x7c\x04\x68\x3b\x45\x2e\x60\xb7\x4a\x34\xbf\xf5\xc9\x32\x34\x56\xaf\xe0\xc9\xfe\x8a\x4f\xfe\x96\x0d\x51\x67\xc7\x07\x2e\x45\xbd\x76\x67\x10\x71\xac\xa7\xca\x8e\xf1\xa3\xe7\xf8\x80\xdf\xdb\x66\x36\xc5\x70\x78\x3a\xa2\x20\x1b\xd3\xcb\x0c\x28\xb6\x89\x3c\x42\x7b\xf9\x26\x73\x1e\x21\x13\x61\x4b\x63\x8c\x8c\x17\xac\x88\xf8\x56\x60\x9f\x11\x01\x49\xea\x08\xf7\xbc\x7b\x33\xee\x30\x2e\x87\xea\xcb\xbd\x2f\x15\xaa\x37\x42\x89\x8d\x90\x4e\xfc\xc2\xa7\xc5\x75\xec\x22\x79\x4d\x80\xe7\xcb\x80\x56\x2b\xf6\xc7\x19\xfd\x2f\x51\x3e\xb7\x5b\xea\x32\x97\x4a\x21\x34\x49\x35\x90\x9b\x1b\x52\xa6\x1f\x0c\x3f\x1c\x0e\x0e\x0f\x1e\x5e\x7f\x36\xbc\xfe\x70\xf8\xe1\x70\xc2\x07\x82\x61\x0e\xb1\xa8\xf5\x90\xb5\xbd\x24\x13\x0a\x4d\x55\xc6\x5d\x84\x85\x85\x87\xdc\x78\x77\xa0\x52\x35\xe0\x24\x48\xd1\xd1\xf1\xaa\x5e\x0d\xc8\x2c\x12\xcc\xf7\xba\xca\x6b\x08\xc5\x47\xc3\x6a\x40\x00\xc0\xf9\x40\xbf\x27\x5f\x63\x94\x26\x93\x8e\x87\x3c\x32\xd1\xe9\x7f\x01\x78\xa8\x23\xe1\x91\xcf\x6a\x0c\x47\xcc\x8a\x4e\x44\x2b\x98\xaa\x60\x62\xc2\xb1\xdd\x40\xe5\x00\xbd\x1a\xca\xc6\x54\x22\xa4\xcc\x0c\x50\xbf\xdd\xdc\xa3\xdc\xe4\x0f\x28\xfc\x9f\x9b\xe6\xa2\x29\xda\xd6\x54\x21\xd8\xc7\x31\x02\xba\xa8\x08\xea\xd5\xb5\xf4\x63\x53\xaf\x00\x43\x03\xbb\x18\x42\xd9\x41\x2d\x84\x8b\xef\xf1\x3e\xd0\xbd\x10\xb5\xb1\xd9\xba\x29\x33\xd2\x8e\xc6\x60\x34\x9d\x04\x9d\x83\x24\xa0\x1d\xc2\xc0\xd4\x70\x0c\x86\xf1\xb7\xf3\xc1\xdd\x70\xf8\x19\x28\xba\x93\xde\x90\xd7\xeb\xc3\x87\x2a\x73\x7f\x02\x3c\x7a\xc8\x40\x44\xb7\x4e\x31\x9f\x77\x53\xb4\x91\x0e\xc1\xe2\x8c\xaf\x32\x27\xef\x0a\xac\x24\x8f\x79\x05\xc9\xdf\xbc\x16\xc9\x4f\x17\x84\xc8\xf4\x25\xe6\xa3\xda\xbc\x3f\x20\x45\x8f\xf9\x7d\x86\x6a\x99\xc6\x2c\xcd\xf2\xc4\x10\x36\x98\x81\x98\x41\xf7\x37\x1a\xd3\xb4\xb5\xf5\xac\xd0\xae\xab\x40\xf8\x31\x9a\x45\xae\x6d\x58\xae\xe7\xe1\x48\xf4\xd8\x73\xd3\x42\xbc\x72\xc9\xf3\x01\xeb\xb8\x93\xe7\x51\x94\xb6\x11\x9c\x2e\x5a\xc0\xdd\x5e\xa8\x1b\x34\xed\x70\x54\x5c\x3c\x4d\x1e\x87\xe8\x28\x3c\x83\x14\x53\xf2\xb7\xd0\x9c\x43\xeb\x00\xdb\x01\xb9\x2e\xe4\x88\xa3\x88\x67\xba\xf2\xd2\x0d\x1b\x60\x8f\xfa\xa1\x55\xfc\xf6\xed\xe0\xaa\x60\x4d\x6c\x9c\x96\x0d\xa7\x98\x3b\x14\x01\x28\xd2\xa1\xb4\x35\xc0\xa9\x14\xe6\xdc\x20\xf8\xbc\x9e\xbb\xc7\x74\x63\xfa\xd4\xfe\xc4\x86\x84\xd4\x2f\xc4\x0d\x20\x2c\xfd\x71\x57\xe1\x9f\xc2\xa9\xfa\x93\x9b\x7a\x85\x61\x10\xd2\x20\x9e\xaf\x1d\x95\x81\xfd\xb9\xaa\x71\xd9\xc0\xac\x24\xc3\xb3\x93\x8c\x70\xbe\xf6\x90\x64\x46\x80\xef\xcd\x01\x05\x1b\x46\x27\x31\x24\xba\x67\x80\xbc\xf9\x37\xc7\xf7\xbb\xc7\x82\x30\xa9\x03\x52\x88\x1f\xc5\xdd\xc7\x1e\xf4\xbf\xea\x9b\xaa\xee\x24\x1d\x04\xaf\xfa\x74\x34\xcf\x4b\xa3\xab\xdd\xf5\x2a\xa4\x8c\x1e\xcc\x8b\xc6\x58\x5a\xb9\xb0\x46\x20\x52\x45\x20\x8e\x7d\xc6\xd0\x9f\x8c\x6d\xeb\xc6\x74\x4f\x32\x14\xd8\x38\x06\x31\x0b\x32\x1a\xc9\x51\x20\x38\x63\xda\xaa\x79\x63\x64\x18\x73\xa7\x12\xe9\xed\xb4\xd4\x67\xa8\xf0\x43\x9b\x64\x63\x76\x51\x75\x07\x19\xfa\xe8\x7a\xca\x6b\x03\x82\x9a\x9d\x35\xe6\x42\x41\x80\xb7\x95\xee\xc8\x29\x01\x70\xbd\x4c\xae\x9d\x5e\x0a\x81\xa1\x0c\x0c\xfd\x14\x11\x3b\xb8\xfc\xe6\x6b\x48\x74\xbd\xe6\x18\xf5\xf8\xf6\x86\xac\xdf\x3d\x87\x3d\x0a\xe4\x71\x7b\x08\x23\xac\x01\x30\x2c\x2c\x1d\xa4\x43\xe8\x24\xe6\x0c\xb3\xd6\xdd\x19\xc1\xa3\x43\xd2\x4a\xb9\x29\x85\x1f\x99\x78\xdc\x53\x57\xaf\xe7\x74\xdf\x5e\x8c\xb7\x7c\x12\x65\x11\xc1\x72\x95\x06\x80\x03\xdc\xc5\x03\xf4\x41\x30\x24\x2c\x3f\x6c\x90\x5b\x31\xb2\x82\x20\x27\xeb\x39\x78\xaf\xc2\x0b\x06\x0f\x1f\xe0\x3e\xd0\xe5\x70\x0a\x51\xbd\x4e\x0c\x83\x18\x7b\x74\x08\x69\xf4\x29\x86\x9c\x50\x40\x38\xe6\x96\xc8\x11\x5b\xb2\xf0\x48\xe9\x23\x95\x23\xb3\x67\x31\x9d\x1c\x32\xb3\xe4\x23\x65\x56\x18\xb8\x63\xd3\xc6\x30\x17\x31\x54\x5d\x54\xb3\x72\x9d\x1b\x1a\x9f\x70\x91\x41\xb8\xe1\x76\x59\xf6\x38\x55\x59\xf3\xdd\xfb\x37\xdf\x47\x1c\x3f\x85\xd6\x70\xaf\x64\xe3\x42\x2e\xbc\xcf\x7a\x0e\x91\x50\xbc\x17\x2d\x8f\xed\xaa\x24\x15\x78\xf9\x90\xbe\xe3\x49\x84\x6b\xfe\xa4\xae\x1d\x0d\xf1\xdf\xca\xb6\x0f\xb8\x28\x2c\xae\xff\x2c\x96\x3c\xc3\x63\x81\x2f\xcf\x73\xf9\xd4\x33\x74\x30\xf0\x5c\x1d\xa8\x06\x13\xb2\xbc\xd7\xa7\x84\xbc\x88\xac\xcf\x28\x48\xfe\x60\xd7\x93\xfd\x78\xf8\x50\x1d\x1d\x07\x37\x2a\x4c\xe8\xd2\xea\x53\x1e\x17\xd5\x1d\x8f\xfe\x88\xfb\x33\xc6\xd5\x27\xc7\x7c\x2e\x7d\xb4\xef\x88\xce\x71\xf0\x78\xf2\x1d\xa4\x95\x02\xef\x9a\x57\xb4\x93\x06\x0a\x53\xaf\xab\x63\xb1\x4c\xdc\xdb\xa1\xf0\x21\xb5\xa1\xcb\xf4\x67\xe2\x8f\xce\xc6\x53\xff\x71\x24\xd8\x45\x49\xae\xd8\x43\xc0\x34\xa7\x66\x00\xb9\xec\xb1\x8f\xa9\x87\x34\xfb\xf0\x42\xc2\x1c\xb3\x12\xf9\x3e\x81\x62\x96\xb9\x02\xc9\x93\x53\x57\xb8\xd5\xf8\x8d\xb4\x87\xc1\x4d\xc7\x3d\x40\xa9\xe0\xd1\x23\xc8\x7a\xfa\xbd\x2b\xa1\x09\x92\x15\xec\x35\x2b\xc0\x7b\x87\xac\xa6\xf1\x77\xdd\x58\x31\xf4\x65\xea\x04\xb9\xa5\x89\x2d\xee\x27\xdc\x35\x76\x2b\x5e\x47\x78\xe6\x64\xcb\xf2\x8a\xdd\x69\x42\x90\x99\x98\x34\x0a\x23\x30\xb3\xb6\x6e\x38\x1d\xb6\xc7\x05\x80\xcd\x85\x31\x06\x50\x05\xdc\xdd\xf3\x39\x26\xcf\x08\xbc\xbb\xca\xe4\x5a\xba\x02\x7f\x13\xb0\x86\x5c\x7b\x8a\x84\xea\xaa\xc0\x44\xa8\xf0\x09\xcb\x65\x94\x8d\x23\xbc\xdc\x1b\xe1\xfb\xd4\xcb\x0e\xf0\xed\xc2\x3d\xd0\x71\x98\x0b\x94\x9d\x5c\xc4\x86\x11\x57\xfe\x8b\x49\xfc\xf1\x3e\xb7\xd1\xe5\x25\x59\x6e\x75\x40\x75\x40\x0f\xa9\xba\x4e\x38\x6c\x9c\x19\x10\x0e\x02\x8b\x12\x01\xd5\x33\x4a\x69\x89\x15\x05\x28\x4f\xae\xb9\xc7\x09\x97\xb5\x51\x3f\xbe\x7d\xe7\xd5\x51\x32\x81\x31\x5c\x7f\x32\xe8\x08\xf3\xd2\x8e\x90\x2d\x88\x51\xa2\xf1\xc8\x99\x72\xce\x87\x4c\x00\xf0\xdc\x1a\xe3\xc7\x97\x71\x31\x57\x99\xeb\x50\xe6\xb3\x75\x38\x49\x4a\x84\x5c\x42\xbc\x3a\x68\xce\x38\x32\x52\x82\x8c\x78\x81\x31\x0d\x0b\xa4\xc0\x33\x91\xf0\x0b\xaf\x34\x9c\x17\xbc\x2a\x01\x9f\x59\x38\x10\x44\x56\x8a\x28\x0c\x0b\x38\xa9\x28\x51\xf7\xda\x52\x8a\x71\xd2\x6e\x45\x8a\x7b\x09\x94\x21\x18\x47\x52\x91\x95\xf3\xb1\xeb\xd6\xc0\x1f\x96\x00\x5c\x48\x4e\x9f\xe1\x8d\x63\x50\xc4\xdd\x5a\xd6\x33\xb6\x17\x60\x92\x7c\xbf\x4c\xe0\x97\x98\xaf\x97\xcb\x2b\x95\x17\xe7\xbe\xb6\x97\x97\xf1\xfd\xe8\xc8\xc8\x79\x5d\xe4\xea\xf5\x4b\xf5\xf9\x8f\xa6\x59\x16\x90\xd9\x4a\xbd\x30\x55\x61\xf2\xcf\x29\x93\xa2\x94\x08\x06\xd9\x5f\xf3\xe2\xfc\x6f\x59\x08\x94\x4a\x2f\xd2\xce\xc4\x0d\xc7\xf3\xc2\x15\xf4\xa3\x10\x50\x89\x11\x52\x22\x63\x43\x43\xa6\x27\xf4\x7d\xc4\x52\x71\x85\x34\x75\x37\x01\x8a\x5b\x68\xa9\x1e\x3e\x14\xa4\x2f\x0a\xb4\x0e\x32\x9c\x9b\x72\xf4\x45\x0d\xc1\xb3\x7e\x8d\x00\x11\x99\x81\x62\x42\xb3\x23\x0f\x4a\x14\x07\xdb\xdf\x74\xaf\x09\xf2\x0c\x94\x91\x1c\x7d\xa1\x1f\xba\x2a\x96\x1a\x9d\x5b\x6e\x0b\x1b\x61\x05\x79\x63\x56\x03\xa6\x72\xc5\x12\xfc\x42\x6e\x89\xf5\xc4\x30\x38\x27\xbe\x56\x63\x0e\x6f\xbb\x19\xd2\xa9\xec\x09\x33\xc9\xeb\xd9\x4b\x8c\x9c\x23\x3f\x23\xaf\x49\xe4\x3f\xe8\xba\x8e\xae\xa4\xbf\x9b\xd6\x11\x4a\xf2\x3b\x02\x88\x09\xed\x7d\x28\xd3\x7c\xdb\xa7\xa6\xfd\x05\x0a\xde\x32\xca\xc2\x26\x45\x0e\xf1\x0f\xf6\x8c\xe3\x6c\x34\x6e\x64\xdf\xf8\x58\x1d\x62\x1a\xff\xbd\x30\x17\x49\x8e\x49\x8c\xe2\x21\x57\x33\x6b\xda\xb7\xf0\x7b\x9a\x4c\xb8\x40\x58\x2b\xa4\x82\x7b\xb6\x6e\x7e\xac\x6d\x81\xee\xef\xb3\x75\xf3\xbd\x99\xb7\xf0\xc7\xf3\x77\xef\xde\xd7\x2b\xf8\x93\xff\xc5\x9a\xf9\x2d\x95\xd4\xe5\x0c\xb2\x4a\xf9\x5a\x60\xff\xad\xe8\x57\xb8\xb6\x66\xd6\x72\x4f\x32\x7e\x9b\x71\xbc\xdd\x6c\xdd\xd0\xd2\x30\xab\x82\x73\x43\x95\x35\xf5\xca\xe7\x3a\xd9\x0e\x18\x8e\xbe\x11\x08\x82\x1c\xa9\xa2\xda\x45\x3c\xdf\x7a\x35\x29\x0d\x04\x86\xa3\x93\x06\xb8\x62\xd4\x98\xd4\xa3\x98\x41\xdd\x5e\xdb\x12\x7a\x8a\x7c\x81\x2b\x11\x8c\xea\x30\xf7\xb6\xbd\x2a\xcd\x58\x0c\x29\x6b\x4c\x09\x30\x19\x99\xd4\x6f\xf8\x19\xc2\x14\xd4\x2f\x43\x88\x15\x29\x91\xfd\xac\xf6\xcf\x4a\x5b\xaf\x58\xc9\x10\x66\xb8\xbf\xa8\x1b\x9d\x2f\x9b\xae\x00\xc0\x78\xc4\xc3\xd2\x27\xb6\x2e\xd7\xad\xc9\x00\x12\x3c\x7a\x35\x2f\x2e\x23\x9f\xd9\x41\x58\x7c\x4c\x98\xca\x1d\x91\xea\xc6\x75\x5b\x67\x43\xf5\x37\xb5\xbb\x1f\x56\xe4\x07\x4a\xe9\x7e\x62\x14\xdc\x69\x6d\x1d\x36\x47\x68\xb3\x98\x2b\x53\x38\x6a\xe8\x56\x49\xd5\x8d\x82\x85\x2a\xac\xf2\xf9\xac\x43\x51\xcb\x45\xb9\xfb\xa0\x2f\x73\xfd\xf5\xab\xd7\x1d\x3c\xaf\x9c\xd8\xd8\x62\x3d\xb8\x72\x56\xeb\xe3\xee\xc6\x02\x5c\x7c\xdc\xd6\x2b\xff\x96\xd6\x40\xbe\x76\x3d\x66\xfa\x2c\x7d\x1b\x7c\x5d\x70\x4d\xbc\x2a\x6b\xdd\xca\xc9\x04\x15\xfb\x5e\x5a\x71\xb7\x2c\x4e\x76\x28\x7c\x73\x7b\xfc\x76\x70\x01\xe4\x91\x77\x52\xaa\x11\xfa\x25\xee\x9d\x42\x1c\x65\xd5\x0d\xca\xf6\xee\x72\xf5\x4a\xdd\x4f\x11\xec\xdd\x39\x84\x37\x07\x49\xc9\xdd\x50\x27\xfc\x1e\xe2\xd6\x79\x4f\x13\x79\xd3\xa9\x1e\x56\xbd\xbf\xfe\x12\x27\x26\x29\x2b\x5b\x28\x71\x86\x76\x98\x5e\x75\x06\x91\x81\xee\x26\x13\x3e\x75\xe9\xe4\x8c\xa1\x44\x34\x31\x48\x65\x86\x1b\x56\x16\x76\x0f\x1c\xc1\x50\x2e\x98\x6a\x37\x87\x1f\xd4\x1d\x6a\x9c\xf4\x08\x3a\xec\x59\xa6\x34\x90\x98\xae\x0e\xbf\xa4\x91\x75\x96\xbc\xba\x41\xbb\x30\x0d\x7f\xdf\x12\x5a\xbd\x15\xdd\x19\x63\x7f\x5b\xb0\x90\x23\xef\x08\xb6\x7b\x45\x7b\x44\xdc\xa3\x23\x77\x27\x8e\x3c\x95\x24\x29\x07\x54\x3a\xf8\xf4\xa4\xbe\x74\x44\xdb\x1d\xf4\xa9\x93\x43\xdc\xb2\x4d\xd5\x9e\x22\x93\x5c\x5e\xcf\x28\x88\x3d\x04\xa4\xca\x80\x7d\x89\x5b\x70\xdf\x15\x8e\xe7\x44\xf6\x2a\xdc\xec\x79\x3d\xeb\xbd\xcd\x11\xd8\xdc\xeb\xf8\x3c\xba\xb7\x56\x79\x61\x67\x75\x55\xa1\x6d\x83\x13\xcc\x85\x86\x99\xf8\xa2\x32\xca\x0e\xc2\xe8\xe9\xf6\x4e\x56\xea\xa4\xbe\x4c\x74\xde\x28\x61\xe4\xe0\xd5\x07\x72\xc6\xe9\xb7\xcf\x7f\x1a\xa9\x8f\x6b\x0b\xe0\xe2\x6a\x6f\xb4\xa7\x1a\x8d\x24\x71\xc1\x2e\x1f\xf4\xed\xb7\xa5\x9e\x9d\x7d\x6b\x9a\xe6\x4a\x3d\x19\xa9\xe2\xed\x3b\xf5\x85\x1a\xb0\x4e\x51\x15\x3f\x2e\xea\x0a\xb3\x8f\x48\x21\x17\xa6\xf2\xd4\xb4\xdf\xd6\x6b\x80\x2f\x7e\x5e\x16\xa6\x6a\x7f\x32\xb3\x16\x64\x5f\xdb\x36\x1d\x03\x3f\xad\xd5\xe6\x2f\x85\x5b\xf4\xd6\x05\x24\xa4\x10\xac\x0e\x2c\x4e\xd7\x32\x0e\xeb\x7e\x52\x5f\x02\x45\xd8\x71\xbb\x65\xec\xa4\xf9\xff\x20\xda\xb3\xcb\x53\x39\x9e\x41\x33\x8e\xcb\x80\xef\x70\x9f\xb8\x0f\xe1\xa0\x87\x2f\x7f\xdd\xf0\xa5\xa3\x01\xdb\xde\x2e\x8b\x92\x16\x13\xfa\xae\x29\x94\x82\x39\x63\xf0\x89\xde\x6d\x05\x26\x5d\x68\xf2\x47\x88\x46\x1f\xd1\xaf\xdb\x36\x3d\xc6\xad\x7b\x3e\xa0\x67\xf7\x87\xfd\xf8\xca\x5d\x65\x41\x9e\x71\xdc\x0a\x31\x73\xc0\x66\x12\xcb\x39\x48\xab\x74\x35\x86\x0a\x6f\x46\xea\xc4\xcc\x34\x08\x67\x98\xc1\xa4\xb5\xe8\xfc\x40\x75\xe1\xe7\xe9\x15\xb2\x81\x1d\x4b\x78\x02\xaf\xa4\x4f\xe4\xfd\xfe\xdd\x25\xa1\xfd\x31\xea\xc0\x09\x2f\x6b\x77\xb0\xe4\xa5\xee\x6f\xf0\x2d\xcf\xba\xde\xb1\xf1\x3a\x04\x99\xec\x82\x8f\x1a\xa3\xcb\x47\xd1\x1a\x89\x7a\xf1\x01\xc7\x24\xc9\x67\x83\x61\x02\x4f\xc9\xb0\xe6\x58\xc8\xc6\x9d\x13\x9f\x33\xdb\xb0\x01\x7e\x40\xb6\x81\x7b\x82\xc4\x71\xa9\x12\x4f\x96\x53\x7e\x93\xb4\x92\x24\x12\x88\x46\x75\x02\x59\x6a\x6c\x67\xcf\xe1\x61\x8b\x99\xc6\xbe\x6e\xe1\xf7\xef\xeb\x15\xe0\x02\x64\xa3\x80\x86\x92\x56\x88\x87\xf0\x53\x6b\x74\x67\xb1\xa7\x4a\x01\xbe\xbe\x3e\x41\xcc\x3e\x6c\x84\xa7\x1c\x81\xbd\xf1\x28\xa8\xa5\x6e\x4e\x8b\xca\xf6\x53\x94\x3a\x8c\x73\x57\x75\x86\xbe\xdb\xb7\xc1\xb1\xbe\xf7\x00\x51\x84\x9d\x92\x94\xa6\x16\xe3\x4c\x6a\xa4\x67\x1b\xab\x74\xa3\xf5\x75\xa6\x24\x48\x4e\xd2\xbf\x10\x27\x98\x52\x9f\xbe\x8d\x4c\x6a\xef\x97\x28\xfd\xc2\x67\x8c\x22\x13\x15\x03\x5f\x84\xdb\xf7\xab\xd8\xaa\xc1\xc2\xd3\x59\xec\x3e\x6a\x11\x64\xa6\x60\xf6\x89\xfb\xdd\xb3\xc7\xf1\x47\x6a\xf9\x41\x66\x67\xe3\x00\x85\x2a\x22\xb8\x93\x90\x43\xa9\x9d\x35\x75\x59\x02\xf3\xac\xd1\xbb\xac\x2e\x4b\xc7\x77\xa3\x0a\x2d\x05\xb1\xfa\x43\x7c\x30\x55\x99\xb8\x5e\xb2\x51\xf8\x98\xde\xd0\x95\x95\xa9\x1b\xa9\x90\x20\xa8\x2e\x60\x08\x45\x04\x0e\xf2\xc7\xf1\x77\x6e\x9e\x5c\x31\x5c\x24\x81\x69\xd5\x8b\x7c\x26\x42\xf1\x68\x4a\x34\xb8\x2b\x33\x97\x96\x4a\xf6\xdc\x11\x19\xc2\x07\xe8\x4f\xe9\x45\xed\x11\x38\x02\x11\x3b\xdf\x14\xda\xed\xdb\x76\xb5\x1c\xba\xff\x1e\xe1\x48\x8f\x49\x53\x11\x3a\x1f\xaf\x22\x47\x72\x09\xdc\xa4\xa2\x1a\xf3\x94\xb2\x63\xda\x7d\x37\x4d\x10\x28\xaf\xa6\xac\x8f\x11\x8b\xc0\xbe\x6a\x1b\x4a\xd1\xc4\x6e\x7b\xc7\x30\xec\x41\xe4\x69\x1e\xf7\x11\x53\x54\x4a\x88\x87\x68\xde\x46\x1d\x16\x7c\x24\x3c\x7b\x13\x24\x35\x4a\xaf\xe8\xd5\x0c\x33\x6b\xbf\xab\xeb\x33\x4b\xd1\x1e\x41\x0e\xe0\xa3\x02\x9f\xfd\x62\x4e\xce\x8a\x56\x9d\xac\x4f\xa7\x6a\xd1\xb6\x2b\x3b\x9d\x4c\x4e\xd6\xa7\x76\x7c\x01\x2f\xc6\x75\x73\x3a\xb1\x8b\xfa\xe2\xb7\x93\xf5\xe9\x78\x76\x5a\x1c\x16\xf9\xc1\xe3\x6f\xf6\xbe\xfe\x12\xbe\x3e\x35\xed\x73\xba\x4c\xdf\xb5\x57\xa5\xf1\x21\x7e\x2b\xd3\xcc\xc0\xec\xe8\xee\x5b\xaf\x37\x45\x48\x50\xea\xe0\xe4\xa4\x6e\xdb\x7a\x39\x01\xfd\x29\xd4\x26\xf9\x4d\xaf\xe2\x9e\x59\xab\x96\x75\xbe\x2e\x0d\xa5\xbe\xe0\xbc\x17\x74\x13\xe2\x3b\x88\x99\x01\xe6\x75\xe6\x93\x43\x14\xad\xc2\x0c\x53\x29\x4e\x1c\xa1\xc2\xa1\xba\x22\x45\x79\x13\xe7\x26\x90\x1b\x98\x48\xbf\xd3\x0e\x94\xce\xf3\xbf\x9b\xd6\x3d\x7d\x3d\x0f\x71\x68\xab\xe2\xd2\x94\x91\xc6\x29\x3d\x13\x9e\xf3\x88\xbc\x41\x3a\x4f\xb7\xfc\x93\x03\x12\xbf\xa5\x38\x28\x51\x25\x8b\x39\x15\x48\x67\x5e\x9f\x9a\x91\x9a\xb3\x6e\xb6\xad\x69\xba\xa2\x33\xd4\x54\xeb\x65\x55\x57\xab\x4b\x4e\x7e\x13\xfa\x11\x87\xe6\xf2\x19\x15\x8a\x0a\x3f\x19\x3b\x2a\x5b\x5d\x66\x3e\x9e\x96\xeb\x90\x7b\x7a\xfb\x1e\x9c\x06\x6f\xda\x0e\xe4\xb1\xa8\x2a\xd3\x20\xd4\xcf\x08\x7f\xc0\x2d\x3d\x52\x0b\x7a\x76\x81\x3f\xeb\x75\xcb\xe5\x10\x78\xc8\xfd\x46\xec\xa0\x4d\x84\x14\x4b\x4f\x55\x86\x55\x65\x23\x05\xe5\xa7\x2a\x83\x3a\x13\xaa\x49\xe0\x07\x1d\x84\x3f\xae\x6d\xa5\x73\xc7\x01\x4e\x55\x06\xbd\x64\xbc\x93\x11\x63\x6d\x91\xd5\x43\x65\xd9\x54\x65\xd0\x3b\x0f\x89\x12\xb5\x43\x0a\x53\x48\x33\x88\xcf\x29\xe0\x9b\x23\x72\xf1\x06\x77\x0c\x29\x70\xcb\x6e\x1f\x8b\xc1\x8f\xc4\xc8\xb7\x83\x65\xc7\xd1\x6c\x5f\x57\x4c\xb5\xb1\xbe\x14\x6c\x04\x74\xac\x0b\x5d\x54\x84\x32\xd4\x91\xf4\xe1\x6a\x96\x9d\x15\xc6\x76\xea\xe2\xfd\xd8\x66\x4e\xb4\x11\xb0\x8f\x9d\xc8\x9b\x7c\xcb\x3d\x01\xb2\x0e\x9c\xc9\xf5\xb5\x07\x21\xa1\x27\x87\xcc\xc0\x80\x1f\x17\x72\x6e\x21\x31\xe4\xa7\xdd\x3a\xb8\x0c\x49\xc2\x62\xd2\x0f\x78\xc7\x96\x58\x6b\x95\x28\xbe\xa3\x08\x89\x67\x90\x4c\xee\xc9\xe4\xeb\xc9\xe3\xbd\xfd\xc7\xe8\x32\x01\x66\x2f\x88\x52\x52\x45\xc5\x3c\x3a\x1a\x4d\xd0\x2d\xf4\x4d\x7d\xe2\xb8\x9d\x77\x7a\xae\x9b\x62\xa4\x4e\xd6\x6d\xc8\x75\x47\xc7\x16\x3c\x76\xb4\xba\x58\xd4\xa5\x51\x65\xdd\x3a\xf2\x35\xd3\x95\xca\xeb\xb1\x7a\x67\x8c\x5a\xa1\x21\x06\x03\x44\x74\x8b\x0d\xff\xfc\xd3\xf7\x50\x7f\x5e\xd8\xd9\x1a\xcc\x45\xd3\x50\x25\x13\xef\xd3\xa2\x5d\xac\x4f\xc6\xb3\x7a\x39\x41\x30\x11\xfe\xc7\x55\x39\xf9\xcb\x57\x5f\xd2\x27\x12\x8b\x6b\x93\xc9\xe1\x48\x65\x28\xcb\xfa\xcd\x7c\xdc\x13\xff\xe6\x44\x15\xfe\x10\x0f\xac\x82\xd4\x3c\x48\xd7\x83\x1f\x76\x8f\x1d\x21\xcc\x75\xd0\xbb\x6c\xd0\x94\x90\x19\x0d\x55\xaf\x78\x6f\x1f\xc1\x39\x98\xe0\xd1\x38\x06\x78\x11\x20\x72\xdd\xe7\x38\x8a\xf8\xf9\x28\xd4\x7a\xb1\x28\x66\x0b\x88\xb4\x2c\xac\x3a\x05\xd2\xc4\xa9\x77\x79\x9e\xde\xe8\x76\x31\x5e\xea\x4b\x1f\x1d\x06\x5d\x3d\xa9\xf3\xab\x23\x70\xe1\xa9\xcb\x32\x4c\xd2\xc8\xcd\x47\xdf\xf3\xbe\x8f\x6b\xe2\xc6\xd2\x8f\x3b\xcf\xf9\x63\x7c\x9d\x2e\x0c\xbd\xed\x04\x28\x06\x80\x86\x75\x1a\x47\x71\x18\x66\xc0\xad\x61\xb2\x74\x7c\xcf\x92\xf8\x33\xe2\xed\x08\xe1\x69\xeb\x16\x14\x55\xf3\xba\x99\x81\xbf\xab\xd7\x17\xc7\x1a\x3d\x21\x9b\xe0\xc1\x44\xf2\x90\x64\x6c\x7b\x77\x67\xe3\x71\xad\x60\xf9\xe8\x39\xf0\xbe\x7a\x76\xb2\xa7\x97\x81\xd2\x1d\x32\x15\x9a\x46\x60\xc2\xfc\x5e\x72\x57\x24\x34\xa5\x17\xd7\xfb\x85\x51\xd5\x7a\x79\x62\xdc\x66\x0b\x5a\x12\xd2\xc4\x05\x8f\x27\xc8\xc1\x1a\xf4\x28\xe8\x70\x1c\x78\x30\x5b\xfc\x6e\xba\x2e\x8f\x52\xfa\x4a\x0c\x86\xe1\x53\x5d\xe5\xef\x24\x46\x24\x3c\xcb\xf3\x6f\xd9\x73\xcf\x77\xf5\x27\x73\x5a\xd8\xd6\x34\x88\x8e\xe6\x76\x49\xae\x9e\xbd\x79\xe1\x39\x26\x0b\xa9\x1a\x08\x6e\xc9\x11\x9f\x13\xc8\x74\x3e\xd3\xad\xa9\x82\xa3\x32\x80\xf3\x40\x7d\xf3\xa2\x84\xec\xf1\xba\x85\x60\xb5\xb5\x75\x1c\x99\x9b\xc2\x91\xdf\x0f\xe7\x85\xc6\xac\xb4\x2b\x74\xb9\xa4\xba\x8a\xba\xf2\x81\x35\x0b\x8d\xcc\x9e\x9b\xff\xc6\xb6\xba\xca\x9d\x94\x5d\x57\x57\xcb\x7a\x6d\x45\xff\xec\x58\x3d\x13\x9d\x2e\xac\xb2\x7a\x0e\xd4\xb0\xca\xd5\xb2\xb6\xad\x6a\xea\x93\xb5\xc5\xca\x20\x83\x78\xad\x1a\x1a\xf1\x58\x41\xee\x5a\x30\xbb\x11\xa2\x52\x61\x31\x67\x22\x6b\xa5\x42\x43\xd0\x88\xc5\xc0\xec\xc9\x44\xe5\xa6\x29\xce\x1d\xab\xda\x40\xfc\x3c\xbf\x1f\x41\xbb\x34\x59\x00\x17\xd7\x2c\x01\x3d\x22\x37\x65\x71\x6e\x1a\x4a\xc7\xa8\x4a\x6e\xd8\x4f\x19\x66\xc8\x57\x2f\x6a\x24\xe2\xe4\x8e\xea\x88\x0c\x7b\x72\x12\x1e\xb8\x4f\xf2\x08\x68\x53\xa2\x83\x17\x1a\x02\x1e\x27\x13\xb2\x5e\x95\x0a\x72\x76\xce\xcb\x62\x06\x41\xe1\x8b\x02\x90\x97\x0a\xab\xce\x4d\x03\x5e\x04\xf5\x9c\xba\x3a\x02\xe7\x4a\x77\x61\x5d\xd4\xcd\xd9\x98\x76\xc6\x0f\x75\x4b\x2a\x33\x77\x9d\x2c\xf5\x65\xb1\x5c\x2f\x95\xe3\x61\xf5\x49\x51\x16\xed\xd5\x48\x95\xc5\x49\xa3\x9b\x82\x17\x5c\x37\x06\x16\x98\x26\x00\x41\x3b\x68\xbe\x66\xa5\x06\x07\x55\xb3\xb4\xa6\x3c\x37\x16\x83\x04\x79\x45\x69\x35\x71\xfe\xd0\xe5\x81\x22\x49\x94\xe6\x91\xc3\x88\x51\x8a\x79\xf3\x02\x5c\xb4\x90\x14\x43\x3e\xf8\xaa\x1d\x8b\x79\xd7\x51\xa0\xd9\x18\x22\xd6\x97\x75\xe3\x58\xc9\xb9\x5b\x12\x34\x19\x5b\x83\xf3\xdf\x77\x29\x36\x27\xeb\xe6\xcc\x4c\x1c\x35\x2b\x1a\xf3\xd1\x4e\x2e\x8a\xb3\x62\xf2\xf3\x2a\x87\x05\xd9\x65\x6f\xdf\x5d\x3f\x03\x0f\x5c\x81\x5d\x37\x22\x37\x7d\x52\xa7\x8d\xdb\x9f\xb4\x93\x74\x94\xc1\x7b\x0b\x5f\x8c\xf5\x92\x79\x7a\x7c\x30\x50\x19\x6e\xc7\x6c\x04\x4e\x6c\xb7\x42\x3f\x3d\x8d\xc0\x3e\xbc\xc3\x00\x3a\x08\xbd\xd1\x2b\x70\x3f\xf5\x33\x43\x59\x59\xeb\xb9\xf7\x4a\x75\xec\xc6\x6f\xf4\xda\x3b\x17\xd0\xae\x60\x3f\x23\x5f\x8d\xdb\x86\x9f\x6d\xac\xe5\xb3\x50\xc1\x67\x92\x1a\x89\x6d\x18\xf9\x70\x1a\xb3\x92\x6e\x6e\xfc\x29\x4c\x14\xf5\x88\x46\x1c\x5e\xa9\xdf\x3e\x0b\xfe\x1c\xf0\x19\x54\xf3\xf0\x61\xdc\xf5\xcd\x75\xf8\xa1\xfe\x26\xe6\xaf\xeb\x44\xe8\x29\x2a\x38\xe5\xac\x6a\xeb\x49\xa0\xdb\xa0\x9f\xa9\x02\xb0\x52\xe6\x05\xf8\x79\x80\x89\xbe\x08\x5b\x73\xf0\xe0\x2f\xfb\x7b\x8f\x1f\xcc\xea\xa5\x23\xea\xd3\xfd\xbd\xd1\x27\xf2\x5d\x4f\x9e\xfc\x65\x08\xb5\xb8\x46\x9e\x03\x96\xf9\x3f\xde\xc1\xe9\x3b\x69\xea\x0b\x6b\x1a\x65\x96\xeb\x52\xb7\x75\x63\xd5\xe0\xc1\xfe\x17\x4f\xbe\xfa\x6a\x18\xef\xb5\xaa\xc6\xb4\x04\x30\x01\x3d\xd6\x92\x74\x16\xc4\xcc\x86\x81\x87\x9d\x94\xce\x89\xbb\xe5\xdc\x66\xfb\xff\x03\x00\x00\xff\xff\x1d\x30\x27\xdd\x1d\xea\x03\x00") - -func assetsJsJquery211JsBytes() ([]byte, error) { - return bindataRead( - _assetsJsJquery211Js, - "assets/js/jquery-2.1.1.js", - ) -} - -func assetsJsJquery211Js() (*asset, error) { - bytes, err := assetsJsJquery211JsBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "assets/js/jquery-2.1.1.js", size: 256541, mode: os.FileMode(511), modTime: time.Unix(1499700236, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "assets/css/bootstrap.min.css": assetsCssBootstrapMinCss, - "assets/favicon.ico": assetsFaviconIco, - "assets/js/jquery-2.1.1.js": assetsJsJquery211Js, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "assets": {nil, map[string]*bintree{ - "css": {nil, map[string]*bintree{ - "bootstrap.min.css": {assetsCssBootstrapMinCss, map[string]*bintree{}}, - }}, - "favicon.ico": {assetsFaviconIco, map[string]*bintree{}}, - "js": {nil, map[string]*bintree{ - "jquery-2.1.1.js": {assetsJsJquery211Js, map[string]*bintree{}}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/file-server/embedding-files-into-app/main.go b/file-server/embedding-files-into-app/main.go index ac43c3a8..4f71cc15 100644 --- a/file-server/embedding-files-into-app/main.go +++ b/file-server/embedding-files-into-app/main.go @@ -1,30 +1,41 @@ package main import ( - "github.com/kataras/iris" + "embed" + + "github.com/kataras/iris/v12" ) -// Follow these steps first: -// $ go get -u github.com/shuLhan/go-bindata/... -// $ go-bindata ./assets/... -// $ go build -// $ ./embedding-files-into-app -// "physical" files are not used, you can delete the "assets" folder and run the example. -// -// See `file-server/embedding-gziped-files-into-app` example as well. +//go:embed assets/* +var fs embed.FS + func newApp() *iris.Application { app := iris.New() + app.Logger().SetLevel("debug") - app.StaticEmbedded("/static", "./assets", Asset, AssetNames) + app.HandleDir("/static", fs) + /* + Or if you need to cache them inside the memory (requires the assets folder + to be located near the executable program): + app.HandleDir("/static", iris.Dir("./assets"), iris.DirOptions{ + IndexName: "index.html", + Cache: iris.DirCacheOptions{ + Enable: true, + Encodings: []string{"gzip"}, + CompressIgnore: iris.MatchImagesAssets, + CompressMinSize: 30 * iris.B, + }, + }) + */ return app } func main() { app := newApp() - // http://localhost:8080/static/css/bootstrap.min.css - // http://localhost:8080/static/js/jquery-2.1.1.js + // http://localhost:8080/static/css/main.css + // http://localhost:8080/static/js/main.js // http://localhost:8080/static/favicon.ico - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/file-server/embedding-files-into-app/main_test.go b/file-server/embedding-files-into-app/main_test.go index cde4f11f..03e32d33 100644 --- a/file-server/embedding-files-into-app/main_test.go +++ b/file-server/embedding-files-into-app/main_test.go @@ -1,13 +1,13 @@ package main import ( - "io/ioutil" + "os" "path/filepath" "runtime" "strings" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) type resource string @@ -18,7 +18,7 @@ type resource string func (r resource) contentType() string { switch filepath.Ext(r.String()) { case ".js": - return "application/javascript" + return "text/javascript" case ".css": return "text/css" case ".ico": @@ -40,38 +40,42 @@ func (r resource) strip(strip string) string { } func (r resource) loadFromBase(dir string) string { - filename := r.String() - - filename = r.strip("/static") + filename := r.strip("/static") fullpath := filepath.Join(dir, filename) - b, err := ioutil.ReadFile(fullpath) + b, err := os.ReadFile(fullpath) if err != nil { panic(fullpath + " failed with error: " + err.Error()) } result := string(b) - if runtime.GOOS != "windows" { - result = strings.Replace(result, "\n", "\r\n", -1) + result = strings.ReplaceAll(result, "\n", "\r\n") + result = strings.ReplaceAll(result, "\r\r", "") } + return result } var urls = []resource{ - "/static/css/bootstrap.min.css", - "/static/js/jquery-2.1.1.js", + "/static/css/main.css", + "/static/js/main.js", "/static/favicon.ico", } // if bindata's values matches with the assets/... contents -// and secondly if the StaticEmbedded had successfully registered +// and secondly if the HandleDir had successfully registered // the routes and gave the correct response. func TestEmbeddingFilesIntoApp(t *testing.T) { app := newApp() e := httptest.New(t, app) + route := app.GetRouteReadOnly("GET/static/{file:path}") + if route == nil { + t.Fatalf("expected a route to serve embedded files") + } + if runtime.GOOS != "windows" { // remove the embedded static favicon for !windows, // it should be built for unix-specific in order to be work @@ -84,7 +88,7 @@ func TestEmbeddingFilesIntoApp(t *testing.T) { e.GET(url).Expect(). Status(httptest.StatusOK). - ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). - Body().Equal(contents) + ContentType(u.contentType()). + Body().IsEqual(contents) } } diff --git a/file-server/embedding-gziped-files-into-app/assets/css/bootstrap.min.css b/file-server/embedding-gziped-files-into-app/assets/css/bootstrap.min.css deleted file mode 100644 index b578f18d..00000000 --- a/file-server/embedding-gziped-files-into-app/assets/css/bootstrap.min.css +++ /dev/null @@ -1,7225 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100% -} - -body { - margin: 0 -} - -article, aside, details, figcaption, figure, footer, header, hgroup, - main, menu, nav, section, summary { - display: block -} - -audio, canvas, progress, video { - display: inline-block; - vertical-align: baseline -} - -audio:not ([controls] ){ - display: none; - height: 0 -} - -[hidden], template { - display: none -} - -a { - background-color: transparent -} - -a:active, a:hover { - outline: 0 -} - -abbr[title] { - border-bottom: 1px dotted -} - -b, strong { - font-weight: 700 -} - -dfn { - font-style: italic -} - -h1 { - margin: .67em 0; - font-size: 2em -} - -mark { - color: #000; - background: #ff0 -} - -small { - font-size: 80% -} - -sub, sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline -} - -sup { - top: -.5em -} - -sub { - bottom: -.25em -} - -img { - border: 0 -} - -svg:not (:root ){ - overflow: hidden -} - -figure { - margin: 1em 40px -} - -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box -} - -pre { - overflow: auto -} - -code, kbd, pre, samp { - font-family: monospace, monospace; - font-size: 1em -} - -button, input, optgroup, select, textarea { - margin: 0; - font: inherit; - color: inherit -} - -button { - overflow: visible -} - -button, select { - text-transform: none -} - -button, html input[type=button], input[type=reset], input[type=submit] { - -webkit-appearance: button; - cursor: pointer -} - -button[disabled], html input[disabled] { - cursor: default -} - -button::-moz-focus-inner, input::-moz-focus-inner { - padding: 0; - border: 0 -} - -input { - line-height: normal -} - -input[type=checkbox], input[type=radio] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0 -} - -input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button - { - height: auto -} - -input[type=search] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield -} - -input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration - { - -webkit-appearance: none -} - -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid silver -} - -legend { - padding: 0; - border: 0 -} - -textarea { - overflow: auto -} - -optgroup { - font-weight: 700 -} - -table { - border-spacing: 0; - border-collapse: collapse -} - -td, th { - padding: 0 -} - /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, :after, :before { - color: #000 !important; - text-shadow: none !important; - background: 0 0 !important; - -webkit-box-shadow: none !important; - box-shadow: none !important - } - a, a:visited { - text-decoration: underline - } - a[href]:after { - content: " (" attr(href) ")" - } - abbr[title]:after { - content: " (" attr(title) ")" - } - a[href^="javascript:"]:after, a[href^="#"]:after { - content: "" - } - blockquote, pre { - border: 1px solid #999; - page-break-inside: avoid - } - thead { - display: table-header-group - } - img, tr { - page-break-inside: avoid - } - img { - max-width: 100% !important - } - h2, h3, p { - orphans: 3; - widows: 3 - } - h2, h3 { - page-break-after: avoid - } - select { - background: #fff !important - } - .navbar { - display: none - } - .btn>.caret, .dropup>.btn>.caret { - border-top-color: #000 !important - } - .label { - border: 1px solid #000 - } - .table { - border-collapse: collapse !important - } - .table td, .table th { - background-color: #fff !important - } - .table-bordered td, .table-bordered th { - border: 1px solid #ddd !important - } -} - -@font-face { - font-family: 'Glyphicons Halflings'; - src: url(../fonts/glyphicons-halflings-regular.eot); - src: url(../fonts/glyphicons-halflings-regular.eot?#iefix) - format('embedded-opentype'), - url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'), - url(../fonts/glyphicons-halflings-regular.woff) format('woff'), - url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'), - url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) - format('svg') -} - -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: 400; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale -} - -.glyphicon-asterisk:before { - content: "\2a" -} - -.glyphicon-plus:before { - content: "\2b" -} - -.glyphicon-eur:before, .glyphicon-euro:before { - content: "\20ac" -} - -.glyphicon-minus:before { - content: "\2212" -} - -.glyphicon-cloud:before { - content: "\2601" -} - -.glyphicon-envelope:before { - content: "\2709" -} - -.glyphicon-pencil:before { - content: "\270f" -} - -.glyphicon-glass:before { - content: "\e001" -} - -.glyphicon-music:before { - content: "\e002" -} - -.glyphicon-search:before { - content: "\e003" -} - -.glyphicon-heart:before { - content: "\e005" -} - -.glyphicon-star:before { - content: "\e006" -} - -.glyphicon-star-empty:before { - content: "\e007" -} - -.glyphicon-user:before { - content: "\e008" -} - -.glyphicon-film:before { - content: "\e009" -} - -.glyphicon-th-large:before { - content: "\e010" -} - -.glyphicon-th:before { - content: "\e011" -} - -.glyphicon-th-list:before { - content: "\e012" -} - -.glyphicon-ok:before { - content: "\e013" -} - -.glyphicon-remove:before { - content: "\e014" -} - -.glyphicon-zoom-in:before { - content: "\e015" -} - -.glyphicon-zoom-out:before { - content: "\e016" -} - -.glyphicon-off:before { - content: "\e017" -} - -.glyphicon-signal:before { - content: "\e018" -} - -.glyphicon-cog:before { - content: "\e019" -} - -.glyphicon-trash:before { - content: "\e020" -} - -.glyphicon-home:before { - content: "\e021" -} - -.glyphicon-file:before { - content: "\e022" -} - -.glyphicon-time:before { - content: "\e023" -} - -.glyphicon-road:before { - content: "\e024" -} - -.glyphicon-download-alt:before { - content: "\e025" -} - -.glyphicon-download:before { - content: "\e026" -} - -.glyphicon-upload:before { - content: "\e027" -} - -.glyphicon-inbox:before { - content: "\e028" -} - -.glyphicon-play-circle:before { - content: "\e029" -} - -.glyphicon-repeat:before { - content: "\e030" -} - -.glyphicon-refresh:before { - content: "\e031" -} - -.glyphicon-list-alt:before { - content: "\e032" -} - -.glyphicon-lock:before { - content: "\e033" -} - -.glyphicon-flag:before { - content: "\e034" -} - -.glyphicon-headphones:before { - content: "\e035" -} - -.glyphicon-volume-off:before { - content: "\e036" -} - -.glyphicon-volume-down:before { - content: "\e037" -} - -.glyphicon-volume-up:before { - content: "\e038" -} - -.glyphicon-qrcode:before { - content: "\e039" -} - -.glyphicon-barcode:before { - content: "\e040" -} - -.glyphicon-tag:before { - content: "\e041" -} - -.glyphicon-tags:before { - content: "\e042" -} - -.glyphicon-book:before { - content: "\e043" -} - -.glyphicon-bookmark:before { - content: "\e044" -} - -.glyphicon-print:before { - content: "\e045" -} - -.glyphicon-camera:before { - content: "\e046" -} - -.glyphicon-font:before { - content: "\e047" -} - -.glyphicon-bold:before { - content: "\e048" -} - -.glyphicon-italic:before { - content: "\e049" -} - -.glyphicon-text-height:before { - content: "\e050" -} - -.glyphicon-text-width:before { - content: "\e051" -} - -.glyphicon-align-left:before { - content: "\e052" -} - -.glyphicon-align-center:before { - content: "\e053" -} - -.glyphicon-align-right:before { - content: "\e054" -} - -.glyphicon-align-justify:before { - content: "\e055" -} - -.glyphicon-list:before { - content: "\e056" -} - -.glyphicon-indent-left:before { - content: "\e057" -} - -.glyphicon-indent-right:before { - content: "\e058" -} - -.glyphicon-facetime-video:before { - content: "\e059" -} - -.glyphicon-picture:before { - content: "\e060" -} - -.glyphicon-map-marker:before { - content: "\e062" -} - -.glyphicon-adjust:before { - content: "\e063" -} - -.glyphicon-tint:before { - content: "\e064" -} - -.glyphicon-edit:before { - content: "\e065" -} - -.glyphicon-share:before { - content: "\e066" -} - -.glyphicon-check:before { - content: "\e067" -} - -.glyphicon-move:before { - content: "\e068" -} - -.glyphicon-step-backward:before { - content: "\e069" -} - -.glyphicon-fast-backward:before { - content: "\e070" -} - -.glyphicon-backward:before { - content: "\e071" -} - -.glyphicon-play:before { - content: "\e072" -} - -.glyphicon-pause:before { - content: "\e073" -} - -.glyphicon-stop:before { - content: "\e074" -} - -.glyphicon-forward:before { - content: "\e075" -} - -.glyphicon-fast-forward:before { - content: "\e076" -} - -.glyphicon-step-forward:before { - content: "\e077" -} - -.glyphicon-eject:before { - content: "\e078" -} - -.glyphicon-chevron-left:before { - content: "\e079" -} - -.glyphicon-chevron-right:before { - content: "\e080" -} - -.glyphicon-plus-sign:before { - content: "\e081" -} - -.glyphicon-minus-sign:before { - content: "\e082" -} - -.glyphicon-remove-sign:before { - content: "\e083" -} - -.glyphicon-ok-sign:before { - content: "\e084" -} - -.glyphicon-question-sign:before { - content: "\e085" -} - -.glyphicon-info-sign:before { - content: "\e086" -} - -.glyphicon-screenshot:before { - content: "\e087" -} - -.glyphicon-remove-circle:before { - content: "\e088" -} - -.glyphicon-ok-circle:before { - content: "\e089" -} - -.glyphicon-ban-circle:before { - content: "\e090" -} - -.glyphicon-arrow-left:before { - content: "\e091" -} - -.glyphicon-arrow-right:before { - content: "\e092" -} - -.glyphicon-arrow-up:before { - content: "\e093" -} - -.glyphicon-arrow-down:before { - content: "\e094" -} - -.glyphicon-share-alt:before { - content: "\e095" -} - -.glyphicon-resize-full:before { - content: "\e096" -} - -.glyphicon-resize-small:before { - content: "\e097" -} - -.glyphicon-exclamation-sign:before { - content: "\e101" -} - -.glyphicon-gift:before { - content: "\e102" -} - -.glyphicon-leaf:before { - content: "\e103" -} - -.glyphicon-fire:before { - content: "\e104" -} - -.glyphicon-eye-open:before { - content: "\e105" -} - -.glyphicon-eye-close:before { - content: "\e106" -} - -.glyphicon-warning-sign:before { - content: "\e107" -} - -.glyphicon-plane:before { - content: "\e108" -} - -.glyphicon-calendar:before { - content: "\e109" -} - -.glyphicon-random:before { - content: "\e110" -} - -.glyphicon-comment:before { - content: "\e111" -} - -.glyphicon-magnet:before { - content: "\e112" -} - -.glyphicon-chevron-up:before { - content: "\e113" -} - -.glyphicon-chevron-down:before { - content: "\e114" -} - -.glyphicon-retweet:before { - content: "\e115" -} - -.glyphicon-shopping-cart:before { - content: "\e116" -} - -.glyphicon-folder-close:before { - content: "\e117" -} - -.glyphicon-folder-open:before { - content: "\e118" -} - -.glyphicon-resize-vertical:before { - content: "\e119" -} - -.glyphicon-resize-horizontal:before { - content: "\e120" -} - -.glyphicon-hdd:before { - content: "\e121" -} - -.glyphicon-bullhorn:before { - content: "\e122" -} - -.glyphicon-bell:before { - content: "\e123" -} - -.glyphicon-certificate:before { - content: "\e124" -} - -.glyphicon-thumbs-up:before { - content: "\e125" -} - -.glyphicon-thumbs-down:before { - content: "\e126" -} - -.glyphicon-hand-right:before { - content: "\e127" -} - -.glyphicon-hand-left:before { - content: "\e128" -} - -.glyphicon-hand-up:before { - content: "\e129" -} - -.glyphicon-hand-down:before { - content: "\e130" -} - -.glyphicon-circle-arrow-right:before { - content: "\e131" -} - -.glyphicon-circle-arrow-left:before { - content: "\e132" -} - -.glyphicon-circle-arrow-up:before { - content: "\e133" -} - -.glyphicon-circle-arrow-down:before { - content: "\e134" -} - -.glyphicon-globe:before { - content: "\e135" -} - -.glyphicon-wrench:before { - content: "\e136" -} - -.glyphicon-tasks:before { - content: "\e137" -} - -.glyphicon-filter:before { - content: "\e138" -} - -.glyphicon-briefcase:before { - content: "\e139" -} - -.glyphicon-fullscreen:before { - content: "\e140" -} - -.glyphicon-dashboard:before { - content: "\e141" -} - -.glyphicon-paperclip:before { - content: "\e142" -} - -.glyphicon-heart-empty:before { - content: "\e143" -} - -.glyphicon-link:before { - content: "\e144" -} - -.glyphicon-phone:before { - content: "\e145" -} - -.glyphicon-pushpin:before { - content: "\e146" -} - -.glyphicon-usd:before { - content: "\e148" -} - -.glyphicon-gbp:before { - content: "\e149" -} - -.glyphicon-sort:before { - content: "\e150" -} - -.glyphicon-sort-by-alphabet:before { - content: "\e151" -} - -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152" -} - -.glyphicon-sort-by-order:before { - content: "\e153" -} - -.glyphicon-sort-by-order-alt:before { - content: "\e154" -} - -.glyphicon-sort-by-attributes:before { - content: "\e155" -} - -.glyphicon-sort-by-attributes-alt:before { - content: "\e156" -} - -.glyphicon-unchecked:before { - content: "\e157" -} - -.glyphicon-expand:before { - content: "\e158" -} - -.glyphicon-collapse-down:before { - content: "\e159" -} - -.glyphicon-collapse-up:before { - content: "\e160" -} - -.glyphicon-log-in:before { - content: "\e161" -} - -.glyphicon-flash:before { - content: "\e162" -} - -.glyphicon-log-out:before { - content: "\e163" -} - -.glyphicon-new-window:before { - content: "\e164" -} - -.glyphicon-record:before { - content: "\e165" -} - -.glyphicon-save:before { - content: "\e166" -} - -.glyphicon-open:before { - content: "\e167" -} - -.glyphicon-saved:before { - content: "\e168" -} - -.glyphicon-import:before { - content: "\e169" -} - -.glyphicon-export:before { - content: "\e170" -} - -.glyphicon-send:before { - content: "\e171" -} - -.glyphicon-floppy-disk:before { - content: "\e172" -} - -.glyphicon-floppy-saved:before { - content: "\e173" -} - -.glyphicon-floppy-remove:before { - content: "\e174" -} - -.glyphicon-floppy-save:before { - content: "\e175" -} - -.glyphicon-floppy-open:before { - content: "\e176" -} - -.glyphicon-credit-card:before { - content: "\e177" -} - -.glyphicon-transfer:before { - content: "\e178" -} - -.glyphicon-cutlery:before { - content: "\e179" -} - -.glyphicon-header:before { - content: "\e180" -} - -.glyphicon-compressed:before { - content: "\e181" -} - -.glyphicon-earphone:before { - content: "\e182" -} - -.glyphicon-phone-alt:before { - content: "\e183" -} - -.glyphicon-tower:before { - content: "\e184" -} - -.glyphicon-stats:before { - content: "\e185" -} - -.glyphicon-sd-video:before { - content: "\e186" -} - -.glyphicon-hd-video:before { - content: "\e187" -} - -.glyphicon-subtitles:before { - content: "\e188" -} - -.glyphicon-sound-stereo:before { - content: "\e189" -} - -.glyphicon-sound-dolby:before { - content: "\e190" -} - -.glyphicon-sound-5-1:before { - content: "\e191" -} - -.glyphicon-sound-6-1:before { - content: "\e192" -} - -.glyphicon-sound-7-1:before { - content: "\e193" -} - -.glyphicon-copyright-mark:before { - content: "\e194" -} - -.glyphicon-registration-mark:before { - content: "\e195" -} - -.glyphicon-cloud-download:before { - content: "\e197" -} - -.glyphicon-cloud-upload:before { - content: "\e198" -} - -.glyphicon-tree-conifer:before { - content: "\e199" -} - -.glyphicon-tree-deciduous:before { - content: "\e200" -} - -.glyphicon-cd:before { - content: "\e201" -} - -.glyphicon-save-file:before { - content: "\e202" -} - -.glyphicon-open-file:before { - content: "\e203" -} - -.glyphicon-level-up:before { - content: "\e204" -} - -.glyphicon-copy:before { - content: "\e205" -} - -.glyphicon-paste:before { - content: "\e206" -} - -.glyphicon-alert:before { - content: "\e209" -} - -.glyphicon-equalizer:before { - content: "\e210" -} - -.glyphicon-king:before { - content: "\e211" -} - -.glyphicon-queen:before { - content: "\e212" -} - -.glyphicon-pawn:before { - content: "\e213" -} - -.glyphicon-bishop:before { - content: "\e214" -} - -.glyphicon-knight:before { - content: "\e215" -} - -.glyphicon-baby-formula:before { - content: "\e216" -} - -.glyphicon-tent:before { - content: "\26fa" -} - -.glyphicon-blackboard:before { - content: "\e218" -} - -.glyphicon-bed:before { - content: "\e219" -} - -.glyphicon-apple:before { - content: "\f8ff" -} - -.glyphicon-erase:before { - content: "\e221" -} - -.glyphicon-hourglass:before { - content: "\231b" -} - -.glyphicon-lamp:before { - content: "\e223" -} - -.glyphicon-duplicate:before { - content: "\e224" -} - -.glyphicon-piggy-bank:before { - content: "\e225" -} - -.glyphicon-scissors:before { - content: "\e226" -} - -.glyphicon-bitcoin:before { - content: "\e227" -} - -.glyphicon-btc:before { - content: "\e227" -} - -.glyphicon-xbt:before { - content: "\e227" -} - -.glyphicon-yen:before { - content: "\00a5" -} - -.glyphicon-jpy:before { - content: "\00a5" -} - -.glyphicon-ruble:before { - content: "\20bd" -} - -.glyphicon-rub:before { - content: "\20bd" -} - -.glyphicon-scale:before { - content: "\e230" -} - -.glyphicon-ice-lolly:before { - content: "\e231" -} - -.glyphicon-ice-lolly-tasted:before { - content: "\e232" -} - -.glyphicon-education:before { - content: "\e233" -} - -.glyphicon-option-horizontal:before { - content: "\e234" -} - -.glyphicon-option-vertical:before { - content: "\e235" -} - -.glyphicon-menu-hamburger:before { - content: "\e236" -} - -.glyphicon-modal-window:before { - content: "\e237" -} - -.glyphicon-oil:before { - content: "\e238" -} - -.glyphicon-grain:before { - content: "\e239" -} - -.glyphicon-sunglasses:before { - content: "\e240" -} - -.glyphicon-text-size:before { - content: "\e241" -} - -.glyphicon-text-color:before { - content: "\e242" -} - -.glyphicon-text-background:before { - content: "\e243" -} - -.glyphicon-object-align-top:before { - content: "\e244" -} - -.glyphicon-object-align-bottom:before { - content: "\e245" -} - -.glyphicon-object-align-horizontal:before { - content: "\e246" -} - -.glyphicon-object-align-left:before { - content: "\e247" -} - -.glyphicon-object-align-vertical:before { - content: "\e248" -} - -.glyphicon-object-align-right:before { - content: "\e249" -} - -.glyphicon-triangle-right:before { - content: "\e250" -} - -.glyphicon-triangle-left:before { - content: "\e251" -} - -.glyphicon-triangle-bottom:before { - content: "\e252" -} - -.glyphicon-triangle-top:before { - content: "\e253" -} - -.glyphicon-console:before { - content: "\e254" -} - -.glyphicon-superscript:before { - content: "\e255" -} - -.glyphicon-subscript:before { - content: "\e256" -} - -.glyphicon-menu-left:before { - content: "\e257" -} - -.glyphicon-menu-right:before { - content: "\e258" -} - -.glyphicon-menu-down:before { - content: "\e259" -} - -.glyphicon-menu-up:before { - content: "\e260" -} - -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -:after, :before { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -html { - font-size: 10px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0) -} - -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff -} - -button, input, select, textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit -} - -a { - color: #337ab7; - text-decoration: none -} - -a:focus, a:hover { - color: #23527c; - text-decoration: underline -} - -a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -figure { - margin: 0 -} - -img { - vertical-align: middle -} - -.carousel-inner>.item>a>img, .carousel-inner>.item>img, .img-responsive, - .thumbnail a>img, .thumbnail>img { - display: block; - max-width: 100%; - height: auto -} - -.img-rounded { - border-radius: 6px -} - -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out -} - -.img-circle { - border-radius: 50% -} - -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0 -} - -.sr-only-focusable:active, .sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto -} - -[role=button] { - cursor: pointer -} - -.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit -} - -.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, .h4 .small, - .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h1 .small, h1 small, - h2 .small, h2 small, h3 .small, h3 small, h4 .small, h4 small, h5 .small, - h5 small, h6 .small, h6 small { - font-weight: 400; - line-height: 1; - color: #777 -} - -.h1, .h2, .h3, h1, h2, h3 { - margin-top: 20px; - margin-bottom: 10px -} - -.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, h1 .small, - h1 small, h2 .small, h2 small, h3 .small, h3 small { - font-size: 65% -} - -.h4, .h5, .h6, h4, h5, h6 { - margin-top: 10px; - margin-bottom: 10px -} - -.h4 .small, .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h4 .small, - h4 small, h5 .small, h5 small, h6 .small, h6 small { - font-size: 75% -} - -.h1, h1 { - font-size: 36px -} - -.h2, h2 { - font-size: 30px -} - -.h3, h3 { - font-size: 24px -} - -.h4, h4 { - font-size: 18px -} - -.h5, h5 { - font-size: 14px -} - -.h6, h6 { - font-size: 12px -} - -p { - margin: 0 0 10px -} - -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4 -} - -@media ( min-width :768px) { - .lead { - font-size: 21px - } -} - -.small, small { - font-size: 85% -} - -.mark, mark { - padding: .2em; - background-color: #fcf8e3 -} - -.text-left { - text-align: left -} - -.text-right { - text-align: right -} - -.text-center { - text-align: center -} - -.text-justify { - text-align: justify -} - -.text-nowrap { - white-space: nowrap -} - -.text-lowercase { - text-transform: lowercase -} - -.text-uppercase { - text-transform: uppercase -} - -.text-capitalize { - text-transform: capitalize -} - -.text-muted { - color: #777 -} - -.text-primary { - color: #337ab7 -} - -a.text-primary:hover { - color: #286090 -} - -.text-success { - color: #3c763d -} - -a.text-success:hover { - color: #2b542c -} - -.text-info { - color: #31708f -} - -a.text-info:hover { - color: #245269 -} - -.text-warning { - color: #8a6d3b -} - -a.text-warning:hover { - color: #66512c -} - -.text-danger { - color: #a94442 -} - -a.text-danger:hover { - color: #843534 -} - -.bg-primary { - color: #fff; - background-color: #337ab7 -} - -a.bg-primary:hover { - background-color: #286090 -} - -.bg-success { - background-color: #dff0d8 -} - -a.bg-success:hover { - background-color: #c1e2b3 -} - -.bg-info { - background-color: #d9edf7 -} - -a.bg-info:hover { - background-color: #afd9ee -} - -.bg-warning { - background-color: #fcf8e3 -} - -a.bg-warning:hover { - background-color: #f7ecb5 -} - -.bg-danger { - background-color: #f2dede -} - -a.bg-danger:hover { - background-color: #e4b9b9 -} - -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee -} - -ol, ul { - margin-top: 0; - margin-bottom: 10px -} - -ol ol, ol ul, ul ol, ul ul { - margin-bottom: 0 -} - -.list-unstyled { - padding-left: 0; - list-style: none -} - -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none -} - -.list-inline>li { - display: inline-block; - padding-right: 5px; - padding-left: 5px -} - -dl { - margin-top: 0; - margin-bottom: 20px -} - -dd, dt { - line-height: 1.42857143 -} - -dt { - font-weight: 700 -} - -dd { - margin-left: 0 -} - -@media ( min-width :768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap - } - .dl-horizontal dd { - margin-left: 180px - } -} - -abbr[data-original-title], abbr[title] { - cursor: help; - border-bottom: 1px dotted #777 -} - -.initialism { - font-size: 90%; - text-transform: uppercase -} - -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee -} - -blockquote ol:last-child, blockquote p:last-child, blockquote ul:last-child - { - margin-bottom: 0 -} - -blockquote .small, blockquote footer, blockquote small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777 -} - -blockquote .small:before, blockquote footer:before, blockquote small:before - { - content: '\2014 \00A0' -} - -.blockquote-reverse, blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0 -} - -.blockquote-reverse .small:before, .blockquote-reverse footer:before, - .blockquote-reverse small:before, blockquote.pull-right .small:before, - blockquote.pull-right footer:before, blockquote.pull-right small:before - { - content: '' -} - -.blockquote-reverse .small:after, .blockquote-reverse footer:after, - .blockquote-reverse small:after, blockquote.pull-right .small:after, - blockquote.pull-right footer:after, blockquote.pull-right small:after { - content: '\00A0 \2014' -} - -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143 -} - -code, kbd, pre, samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace -} - -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px -} - -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25) -} - -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: 700; - -webkit-box-shadow: none; - box-shadow: none -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px -} - -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0 -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll -} - -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto -} - -@media ( min-width :768px) { - .container { - width: 750px - } -} - -@media ( min-width :992px) { - .container { - width: 970px - } -} - -@media ( min-width :1200px) { - .container { - width: 1170px - } -} - -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto -} - -.row { - margin-right: -15px; - margin-left: -15px -} - -.col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, - .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, - .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, - .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, - .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, - .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, - .col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, - .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px -} - -.col-xs-1, .col-xs-10, .col-xs-11, .col-xs-12, .col-xs-2, .col-xs-3, - .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9 { - float: left -} - -.col-xs-12 { - width: 100% -} - -.col-xs-11 { - width: 91.66666667% -} - -.col-xs-10 { - width: 83.33333333% -} - -.col-xs-9 { - width: 75% -} - -.col-xs-8 { - width: 66.66666667% -} - -.col-xs-7 { - width: 58.33333333% -} - -.col-xs-6 { - width: 50% -} - -.col-xs-5 { - width: 41.66666667% -} - -.col-xs-4 { - width: 33.33333333% -} - -.col-xs-3 { - width: 25% -} - -.col-xs-2 { - width: 16.66666667% -} - -.col-xs-1 { - width: 8.33333333% -} - -.col-xs-pull-12 { - right: 100% -} - -.col-xs-pull-11 { - right: 91.66666667% -} - -.col-xs-pull-10 { - right: 83.33333333% -} - -.col-xs-pull-9 { - right: 75% -} - -.col-xs-pull-8 { - right: 66.66666667% -} - -.col-xs-pull-7 { - right: 58.33333333% -} - -.col-xs-pull-6 { - right: 50% -} - -.col-xs-pull-5 { - right: 41.66666667% -} - -.col-xs-pull-4 { - right: 33.33333333% -} - -.col-xs-pull-3 { - right: 25% -} - -.col-xs-pull-2 { - right: 16.66666667% -} - -.col-xs-pull-1 { - right: 8.33333333% -} - -.col-xs-pull-0 { - right: auto -} - -.col-xs-push-12 { - left: 100% -} - -.col-xs-push-11 { - left: 91.66666667% -} - -.col-xs-push-10 { - left: 83.33333333% -} - -.col-xs-push-9 { - left: 75% -} - -.col-xs-push-8 { - left: 66.66666667% -} - -.col-xs-push-7 { - left: 58.33333333% -} - -.col-xs-push-6 { - left: 50% -} - -.col-xs-push-5 { - left: 41.66666667% -} - -.col-xs-push-4 { - left: 33.33333333% -} - -.col-xs-push-3 { - left: 25% -} - -.col-xs-push-2 { - left: 16.66666667% -} - -.col-xs-push-1 { - left: 8.33333333% -} - -.col-xs-push-0 { - left: auto -} - -.col-xs-offset-12 { - margin-left: 100% -} - -.col-xs-offset-11 { - margin-left: 91.66666667% -} - -.col-xs-offset-10 { - margin-left: 83.33333333% -} - -.col-xs-offset-9 { - margin-left: 75% -} - -.col-xs-offset-8 { - margin-left: 66.66666667% -} - -.col-xs-offset-7 { - margin-left: 58.33333333% -} - -.col-xs-offset-6 { - margin-left: 50% -} - -.col-xs-offset-5 { - margin-left: 41.66666667% -} - -.col-xs-offset-4 { - margin-left: 33.33333333% -} - -.col-xs-offset-3 { - margin-left: 25% -} - -.col-xs-offset-2 { - margin-left: 16.66666667% -} - -.col-xs-offset-1 { - margin-left: 8.33333333% -} - -.col-xs-offset-0 { - margin-left: 0 -} - -@media ( min-width :768px) { - .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, - .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9 { - float: left - } - .col-sm-12 { - width: 100% - } - .col-sm-11 { - width: 91.66666667% - } - .col-sm-10 { - width: 83.33333333% - } - .col-sm-9 { - width: 75% - } - .col-sm-8 { - width: 66.66666667% - } - .col-sm-7 { - width: 58.33333333% - } - .col-sm-6 { - width: 50% - } - .col-sm-5 { - width: 41.66666667% - } - .col-sm-4 { - width: 33.33333333% - } - .col-sm-3 { - width: 25% - } - .col-sm-2 { - width: 16.66666667% - } - .col-sm-1 { - width: 8.33333333% - } - .col-sm-pull-12 { - right: 100% - } - .col-sm-pull-11 { - right: 91.66666667% - } - .col-sm-pull-10 { - right: 83.33333333% - } - .col-sm-pull-9 { - right: 75% - } - .col-sm-pull-8 { - right: 66.66666667% - } - .col-sm-pull-7 { - right: 58.33333333% - } - .col-sm-pull-6 { - right: 50% - } - .col-sm-pull-5 { - right: 41.66666667% - } - .col-sm-pull-4 { - right: 33.33333333% - } - .col-sm-pull-3 { - right: 25% - } - .col-sm-pull-2 { - right: 16.66666667% - } - .col-sm-pull-1 { - right: 8.33333333% - } - .col-sm-pull-0 { - right: auto - } - .col-sm-push-12 { - left: 100% - } - .col-sm-push-11 { - left: 91.66666667% - } - .col-sm-push-10 { - left: 83.33333333% - } - .col-sm-push-9 { - left: 75% - } - .col-sm-push-8 { - left: 66.66666667% - } - .col-sm-push-7 { - left: 58.33333333% - } - .col-sm-push-6 { - left: 50% - } - .col-sm-push-5 { - left: 41.66666667% - } - .col-sm-push-4 { - left: 33.33333333% - } - .col-sm-push-3 { - left: 25% - } - .col-sm-push-2 { - left: 16.66666667% - } - .col-sm-push-1 { - left: 8.33333333% - } - .col-sm-push-0 { - left: auto - } - .col-sm-offset-12 { - margin-left: 100% - } - .col-sm-offset-11 { - margin-left: 91.66666667% - } - .col-sm-offset-10 { - margin-left: 83.33333333% - } - .col-sm-offset-9 { - margin-left: 75% - } - .col-sm-offset-8 { - margin-left: 66.66666667% - } - .col-sm-offset-7 { - margin-left: 58.33333333% - } - .col-sm-offset-6 { - margin-left: 50% - } - .col-sm-offset-5 { - margin-left: 41.66666667% - } - .col-sm-offset-4 { - margin-left: 33.33333333% - } - .col-sm-offset-3 { - margin-left: 25% - } - .col-sm-offset-2 { - margin-left: 16.66666667% - } - .col-sm-offset-1 { - margin-left: 8.33333333% - } - .col-sm-offset-0 { - margin-left: 0 - } -} - -@media ( min-width :992px) { - .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, - .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9 { - float: left - } - .col-md-12 { - width: 100% - } - .col-md-11 { - width: 91.66666667% - } - .col-md-10 { - width: 83.33333333% - } - .col-md-9 { - width: 75% - } - .col-md-8 { - width: 66.66666667% - } - .col-md-7 { - width: 58.33333333% - } - .col-md-6 { - width: 50% - } - .col-md-5 { - width: 41.66666667% - } - .col-md-4 { - width: 33.33333333% - } - .col-md-3 { - width: 25% - } - .col-md-2 { - width: 16.66666667% - } - .col-md-1 { - width: 8.33333333% - } - .col-md-pull-12 { - right: 100% - } - .col-md-pull-11 { - right: 91.66666667% - } - .col-md-pull-10 { - right: 83.33333333% - } - .col-md-pull-9 { - right: 75% - } - .col-md-pull-8 { - right: 66.66666667% - } - .col-md-pull-7 { - right: 58.33333333% - } - .col-md-pull-6 { - right: 50% - } - .col-md-pull-5 { - right: 41.66666667% - } - .col-md-pull-4 { - right: 33.33333333% - } - .col-md-pull-3 { - right: 25% - } - .col-md-pull-2 { - right: 16.66666667% - } - .col-md-pull-1 { - right: 8.33333333% - } - .col-md-pull-0 { - right: auto - } - .col-md-push-12 { - left: 100% - } - .col-md-push-11 { - left: 91.66666667% - } - .col-md-push-10 { - left: 83.33333333% - } - .col-md-push-9 { - left: 75% - } - .col-md-push-8 { - left: 66.66666667% - } - .col-md-push-7 { - left: 58.33333333% - } - .col-md-push-6 { - left: 50% - } - .col-md-push-5 { - left: 41.66666667% - } - .col-md-push-4 { - left: 33.33333333% - } - .col-md-push-3 { - left: 25% - } - .col-md-push-2 { - left: 16.66666667% - } - .col-md-push-1 { - left: 8.33333333% - } - .col-md-push-0 { - left: auto - } - .col-md-offset-12 { - margin-left: 100% - } - .col-md-offset-11 { - margin-left: 91.66666667% - } - .col-md-offset-10 { - margin-left: 83.33333333% - } - .col-md-offset-9 { - margin-left: 75% - } - .col-md-offset-8 { - margin-left: 66.66666667% - } - .col-md-offset-7 { - margin-left: 58.33333333% - } - .col-md-offset-6 { - margin-left: 50% - } - .col-md-offset-5 { - margin-left: 41.66666667% - } - .col-md-offset-4 { - margin-left: 33.33333333% - } - .col-md-offset-3 { - margin-left: 25% - } - .col-md-offset-2 { - margin-left: 16.66666667% - } - .col-md-offset-1 { - margin-left: 8.33333333% - } - .col-md-offset-0 { - margin-left: 0 - } -} - -@media ( min-width :1200px) { - .col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, - .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9 { - float: left - } - .col-lg-12 { - width: 100% - } - .col-lg-11 { - width: 91.66666667% - } - .col-lg-10 { - width: 83.33333333% - } - .col-lg-9 { - width: 75% - } - .col-lg-8 { - width: 66.66666667% - } - .col-lg-7 { - width: 58.33333333% - } - .col-lg-6 { - width: 50% - } - .col-lg-5 { - width: 41.66666667% - } - .col-lg-4 { - width: 33.33333333% - } - .col-lg-3 { - width: 25% - } - .col-lg-2 { - width: 16.66666667% - } - .col-lg-1 { - width: 8.33333333% - } - .col-lg-pull-12 { - right: 100% - } - .col-lg-pull-11 { - right: 91.66666667% - } - .col-lg-pull-10 { - right: 83.33333333% - } - .col-lg-pull-9 { - right: 75% - } - .col-lg-pull-8 { - right: 66.66666667% - } - .col-lg-pull-7 { - right: 58.33333333% - } - .col-lg-pull-6 { - right: 50% - } - .col-lg-pull-5 { - right: 41.66666667% - } - .col-lg-pull-4 { - right: 33.33333333% - } - .col-lg-pull-3 { - right: 25% - } - .col-lg-pull-2 { - right: 16.66666667% - } - .col-lg-pull-1 { - right: 8.33333333% - } - .col-lg-pull-0 { - right: auto - } - .col-lg-push-12 { - left: 100% - } - .col-lg-push-11 { - left: 91.66666667% - } - .col-lg-push-10 { - left: 83.33333333% - } - .col-lg-push-9 { - left: 75% - } - .col-lg-push-8 { - left: 66.66666667% - } - .col-lg-push-7 { - left: 58.33333333% - } - .col-lg-push-6 { - left: 50% - } - .col-lg-push-5 { - left: 41.66666667% - } - .col-lg-push-4 { - left: 33.33333333% - } - .col-lg-push-3 { - left: 25% - } - .col-lg-push-2 { - left: 16.66666667% - } - .col-lg-push-1 { - left: 8.33333333% - } - .col-lg-push-0 { - left: auto - } - .col-lg-offset-12 { - margin-left: 100% - } - .col-lg-offset-11 { - margin-left: 91.66666667% - } - .col-lg-offset-10 { - margin-left: 83.33333333% - } - .col-lg-offset-9 { - margin-left: 75% - } - .col-lg-offset-8 { - margin-left: 66.66666667% - } - .col-lg-offset-7 { - margin-left: 58.33333333% - } - .col-lg-offset-6 { - margin-left: 50% - } - .col-lg-offset-5 { - margin-left: 41.66666667% - } - .col-lg-offset-4 { - margin-left: 33.33333333% - } - .col-lg-offset-3 { - margin-left: 25% - } - .col-lg-offset-2 { - margin-left: 16.66666667% - } - .col-lg-offset-1 { - margin-left: 8.33333333% - } - .col-lg-offset-0 { - margin-left: 0 - } -} - -table { - background-color: transparent -} - -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left -} - -th { - text-align: left -} - -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px -} - -.table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, - .table>thead>tr>td, .table>thead>tr>th { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd -} - -.table>thead>tr>th { - vertical-align: bottom; - border-bottom: 2px solid #ddd -} - -.table>caption+thead>tr:first-child>td, .table>caption+thead>tr:first-child>th, - .table>colgroup+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, - .table>thead:first-child>tr:first-child>td, .table>thead:first-child>tr:first-child>th - { - border-top: 0 -} - -.table>tbody+tbody { - border-top: 2px solid #ddd -} - -.table .table { - background-color: #fff -} - -.table-condensed>tbody>tr>td, .table-condensed>tbody>tr>th, - .table-condensed>tfoot>tr>td, .table-condensed>tfoot>tr>th, - .table-condensed>thead>tr>td, .table-condensed>thead>tr>th { - padding: 5px -} - -.table-bordered { - border: 1px solid #ddd -} - -.table-bordered>tbody>tr>td, .table-bordered>tbody>tr>th, - .table-bordered>tfoot>tr>td, .table-bordered>tfoot>tr>th, - .table-bordered>thead>tr>td, .table-bordered>thead>tr>th { - border: 1px solid #ddd -} - -.table-bordered>thead>tr>td, .table-bordered>thead>tr>th { - border-bottom-width: 2px -} - -.table-striped>tbody>tr:nth-of-type(odd) { - background-color: #f9f9f9 -} - -.table-hover>tbody>tr:hover { - background-color: #f5f5f5 -} - -table col[class*=col-] { - position: static; - display: table-column; - float: none -} - -table td[class*=col-], table th[class*=col-] { - position: static; - display: table-cell; - float: none -} - -.table>tbody>tr.active>td, .table>tbody>tr.active>th, .table>tbody>tr>td.active, - .table>tbody>tr>th.active, .table>tfoot>tr.active>td, .table>tfoot>tr.active>th, - .table>tfoot>tr>td.active, .table>tfoot>tr>th.active, .table>thead>tr.active>td, - .table>thead>tr.active>th, .table>thead>tr>td.active, .table>thead>tr>th.active - { - background-color: #f5f5f5 -} - -.table-hover>tbody>tr.active:hover>td, .table-hover>tbody>tr.active:hover>th, - .table-hover>tbody>tr:hover>.active, .table-hover>tbody>tr>td.active:hover, - .table-hover>tbody>tr>th.active:hover { - background-color: #e8e8e8 -} - -.table>tbody>tr.success>td, .table>tbody>tr.success>th, .table>tbody>tr>td.success, - .table>tbody>tr>th.success, .table>tfoot>tr.success>td, .table>tfoot>tr.success>th, - .table>tfoot>tr>td.success, .table>tfoot>tr>th.success, .table>thead>tr.success>td, - .table>thead>tr.success>th, .table>thead>tr>td.success, .table>thead>tr>th.success - { - background-color: #dff0d8 -} - -.table-hover>tbody>tr.success:hover>td, .table-hover>tbody>tr.success:hover>th, - .table-hover>tbody>tr:hover>.success, .table-hover>tbody>tr>td.success:hover, - .table-hover>tbody>tr>th.success:hover { - background-color: #d0e9c6 -} - -.table>tbody>tr.info>td, .table>tbody>tr.info>th, .table>tbody>tr>td.info, - .table>tbody>tr>th.info, .table>tfoot>tr.info>td, .table>tfoot>tr.info>th, - .table>tfoot>tr>td.info, .table>tfoot>tr>th.info, .table>thead>tr.info>td, - .table>thead>tr.info>th, .table>thead>tr>td.info, .table>thead>tr>th.info - { - background-color: #d9edf7 -} - -.table-hover>tbody>tr.info:hover>td, .table-hover>tbody>tr.info:hover>th, - .table-hover>tbody>tr:hover>.info, .table-hover>tbody>tr>td.info:hover, - .table-hover>tbody>tr>th.info:hover { - background-color: #c4e3f3 -} - -.table>tbody>tr.warning>td, .table>tbody>tr.warning>th, .table>tbody>tr>td.warning, - .table>tbody>tr>th.warning, .table>tfoot>tr.warning>td, .table>tfoot>tr.warning>th, - .table>tfoot>tr>td.warning, .table>tfoot>tr>th.warning, .table>thead>tr.warning>td, - .table>thead>tr.warning>th, .table>thead>tr>td.warning, .table>thead>tr>th.warning - { - background-color: #fcf8e3 -} - -.table-hover>tbody>tr.warning:hover>td, .table-hover>tbody>tr.warning:hover>th, - .table-hover>tbody>tr:hover>.warning, .table-hover>tbody>tr>td.warning:hover, - .table-hover>tbody>tr>th.warning:hover { - background-color: #faf2cc -} - -.table>tbody>tr.danger>td, .table>tbody>tr.danger>th, .table>tbody>tr>td.danger, - .table>tbody>tr>th.danger, .table>tfoot>tr.danger>td, .table>tfoot>tr.danger>th, - .table>tfoot>tr>td.danger, .table>tfoot>tr>th.danger, .table>thead>tr.danger>td, - .table>thead>tr.danger>th, .table>thead>tr>td.danger, .table>thead>tr>th.danger - { - background-color: #f2dede -} - -.table-hover>tbody>tr.danger:hover>td, .table-hover>tbody>tr.danger:hover>th, - .table-hover>tbody>tr:hover>.danger, .table-hover>tbody>tr>td.danger:hover, - .table-hover>tbody>tr>th.danger:hover { - background-color: #ebcccc -} - -.table-responsive { - min-height: .01%; - overflow-x: auto -} - -@media screen and (max-width:767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd - } - .table-responsive>.table { - margin-bottom: 0 - } - .table-responsive>.table>tbody>tr>td, .table-responsive>.table>tbody>tr>th, - .table-responsive>.table>tfoot>tr>td, .table-responsive>.table>tfoot>tr>th, - .table-responsive>.table>thead>tr>td, .table-responsive>.table>thead>tr>th - { - white-space: nowrap - } - .table-responsive>.table-bordered { - border: 0 - } - .table-responsive>.table-bordered>tbody>tr>td:first-child, - .table-responsive>.table-bordered>tbody>tr>th:first-child, - .table-responsive>.table-bordered>tfoot>tr>td:first-child, - .table-responsive>.table-bordered>tfoot>tr>th:first-child, - .table-responsive>.table-bordered>thead>tr>td:first-child, - .table-responsive>.table-bordered>thead>tr>th:first-child { - border-left: 0 - } - .table-responsive>.table-bordered>tbody>tr>td:last-child, - .table-responsive>.table-bordered>tbody>tr>th:last-child, - .table-responsive>.table-bordered>tfoot>tr>td:last-child, - .table-responsive>.table-bordered>tfoot>tr>th:last-child, - .table-responsive>.table-bordered>thead>tr>td:last-child, - .table-responsive>.table-bordered>thead>tr>th:last-child { - border-right: 0 - } - .table-responsive>.table-bordered>tbody>tr:last-child>td, - .table-responsive>.table-bordered>tbody>tr:last-child>th, - .table-responsive>.table-bordered>tfoot>tr:last-child>td, - .table-responsive>.table-bordered>tfoot>tr:last-child>th { - border-bottom: 0 - } -} - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0 -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5 -} - -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: 700 -} - -input[type=search] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -input[type=checkbox], input[type=radio] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal -} - -input[type=file] { - display: block -} - -input[type=range] { - display: block; - width: 100% -} - -select[multiple], select[size] { - height: auto -} - -input[type=file]:focus, input[type=checkbox]:focus, input[type=radio]:focus - { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555 -} - -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow - ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out - .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s -} - -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px - rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px - rgba(102, 175, 233, .6) -} - -.form-control::-moz-placeholder { - color: #999; - opacity: 1 -} - -.form-control:-ms-input-placeholder { - color: #999 -} - -.form-control::-webkit-input-placeholder { - color: #999 -} - -.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control - { - background-color: #eee; - opacity: 1 -} - -.form-control[disabled], fieldset[disabled] .form-control { - cursor: not-allowed -} - -textarea.form-control { - height: auto -} - -input[type=search] { - -webkit-appearance: none -} - -@media screen and (-webkit-min-device-pixel-ratio:0) { - input[type=date], input[type=time], input[type=datetime-local], input[type=month] - { - line-height: 34px - } - .input-group-sm input[type=date], .input-group-sm input[type=time], - .input-group-sm input[type=datetime-local], .input-group-sm input[type=month], - input[type=date].input-sm, input[type=time].input-sm, input[type=datetime-local].input-sm, - input[type=month].input-sm { - line-height: 30px - } - .input-group-lg input[type=date], .input-group-lg input[type=time], - .input-group-lg input[type=datetime-local], .input-group-lg input[type=month], - input[type=date].input-lg, input[type=time].input-lg, input[type=datetime-local].input-lg, - input[type=month].input-lg { - line-height: 46px - } -} - -.form-group { - margin-bottom: 15px -} - -.checkbox, .radio { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px -} - -.checkbox label, .radio label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - cursor: pointer -} - -.checkbox input[type=checkbox], .checkbox-inline input[type=checkbox], - .radio input[type=radio], .radio-inline input[type=radio] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px -} - -.checkbox+.checkbox, .radio+.radio { - margin-top: -5px -} - -.checkbox-inline, .radio-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - vertical-align: middle; - cursor: pointer -} - -.checkbox-inline+.checkbox-inline, .radio-inline+.radio-inline { - margin-top: 0; - margin-left: 10px -} - -fieldset[disabled] input[type=checkbox], fieldset[disabled] input[type=radio], - input[type=checkbox].disabled, input[type=checkbox][disabled], input[type=radio].disabled, - input[type=radio][disabled] { - cursor: not-allowed -} - -.checkbox-inline.disabled, .radio-inline.disabled, fieldset[disabled] .checkbox-inline, - fieldset[disabled] .radio-inline { - cursor: not-allowed -} - -.checkbox.disabled label, .radio.disabled label, fieldset[disabled] .checkbox label, - fieldset[disabled] .radio label { - cursor: not-allowed -} - -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0 -} - -.form-control-static.input-lg, .form-control-static.input-sm { - padding-right: 0; - padding-left: 0 -} - -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.input-sm { - height: 30px; - line-height: 30px -} - -select[multiple].input-sm, textarea.input-sm { - height: auto -} - -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.form-group-sm .form-control { - height: 30px; - line-height: 30px -} - -select[multiple].form-group-sm .form-control, textarea.form-group-sm .form-control - { - height: auto -} - -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5 -} - -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.input-lg { - height: 46px; - line-height: 46px -} - -select[multiple].input-lg, textarea.input-lg { - height: auto -} - -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.form-group-lg .form-control { - height: 46px; - line-height: 46px -} - -select[multiple].form-group-lg .form-control, textarea.form-group-lg .form-control - { - height: auto -} - -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333 -} - -.has-feedback { - position: relative -} - -.has-feedback .form-control { - padding-right: 42.5px -} - -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none -} - -.input-lg+.form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px -} - -.input-sm+.form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px -} - -.has-success .checkbox, .has-success .checkbox-inline, .has-success .control-label, - .has-success .help-block, .has-success .radio, .has-success .radio-inline, - .has-success.checkbox label, .has-success.checkbox-inline label, - .has-success.radio label, .has-success.radio-inline label { - color: #3c763d -} - -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168 -} - -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d -} - -.has-success .form-control-feedback { - color: #3c763d -} - -.has-warning .checkbox, .has-warning .checkbox-inline, .has-warning .control-label, - .has-warning .help-block, .has-warning .radio, .has-warning .radio-inline, - .has-warning.checkbox label, .has-warning.checkbox-inline label, - .has-warning.radio label, .has-warning.radio-inline label { - color: #8a6d3b -} - -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b -} - -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b -} - -.has-warning .form-control-feedback { - color: #8a6d3b -} - -.has-error .checkbox, .has-error .checkbox-inline, .has-error .control-label, - .has-error .help-block, .has-error .radio, .has-error .radio-inline, - .has-error.checkbox label, .has-error.checkbox-inline label, .has-error.radio label, - .has-error.radio-inline label { - color: #a94442 -} - -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) -} - -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483 -} - -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442 -} - -.has-error .form-control-feedback { - color: #a94442 -} - -.has-feedback label ~.form-control-feedback { - top: 25px -} - -.has-feedback label.sr-only ~.form-control-feedback { - top: 0 -} - -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373 -} - -@media ( min-width :768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle - } - .form-inline .form-control-static { - display: inline-block - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle - } - .form-inline .input-group .form-control, .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn { - width: auto - } - .form-inline .input-group>.form-control { - width: 100% - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle - } - .form-inline .checkbox, .form-inline .radio { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle - } - .form-inline .checkbox label, .form-inline .radio label { - padding-left: 0 - } - .form-inline .checkbox input[type=checkbox], .form-inline .radio input[type=radio] - { - position: relative; - margin-left: 0 - } - .form-inline .has-feedback .form-control-feedback { - top: 0 - } -} - -.form-horizontal .checkbox, .form-horizontal .checkbox-inline, - .form-horizontal .radio, .form-horizontal .radio-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0 -} - -.form-horizontal .checkbox, .form-horizontal .radio { - min-height: 27px -} - -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px -} - -@media ( min-width :768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right - } -} - -.form-horizontal .has-feedback .form-control-feedback { - right: 15px -} - -@media ( min-width :768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 14.33px - } -} - -@media ( min-width :768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px - } -} - -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px -} - -.btn.active.focus, .btn.active:focus, .btn.focus, .btn:active.focus, - .btn:active:focus, .btn:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px -} - -.btn.focus, .btn:focus, .btn:hover { - color: #333; - text-decoration: none -} - -.btn.active, .btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) -} - -.btn.disabled, .btn[disabled], fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity = 65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65 -} - -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc -} - -.btn-default.active, .btn-default.focus, .btn-default:active, - .btn-default:focus, .btn-default:hover, .open>.dropdown-toggle.btn-default - { - color: #333; - background-color: #e6e6e6; - border-color: #adadad -} - -.btn-default.active, .btn-default:active, .open>.dropdown-toggle.btn-default - { - background-image: none -} - -.btn-default.disabled, .btn-default.disabled.active, .btn-default.disabled.focus, - .btn-default.disabled:active, .btn-default.disabled:focus, .btn-default.disabled:hover, - .btn-default[disabled], .btn-default[disabled].active, .btn-default[disabled].focus, - .btn-default[disabled]:active, .btn-default[disabled]:focus, - .btn-default[disabled]:hover, fieldset[disabled] .btn-default, fieldset[disabled] .btn-default.active, - fieldset[disabled] .btn-default.focus, fieldset[disabled] .btn-default:active, - fieldset[disabled] .btn-default:focus, fieldset[disabled] .btn-default:hover - { - background-color: #fff; - border-color: #ccc -} - -.btn-default .badge { - color: #fff; - background-color: #333 -} - -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4 -} - -.btn-primary.active, .btn-primary.focus, .btn-primary:active, - .btn-primary:focus, .btn-primary:hover, .open>.dropdown-toggle.btn-primary - { - color: #fff; - background-color: #286090; - border-color: #204d74 -} - -.btn-primary.active, .btn-primary:active, .open>.dropdown-toggle.btn-primary - { - background-image: none -} - -.btn-primary.disabled, .btn-primary.disabled.active, .btn-primary.disabled.focus, - .btn-primary.disabled:active, .btn-primary.disabled:focus, .btn-primary.disabled:hover, - .btn-primary[disabled], .btn-primary[disabled].active, .btn-primary[disabled].focus, - .btn-primary[disabled]:active, .btn-primary[disabled]:focus, - .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary, fieldset[disabled] .btn-primary.active, - fieldset[disabled] .btn-primary.focus, fieldset[disabled] .btn-primary:active, - fieldset[disabled] .btn-primary:focus, fieldset[disabled] .btn-primary:hover - { - background-color: #337ab7; - border-color: #2e6da4 -} - -.btn-primary .badge { - color: #337ab7; - background-color: #fff -} - -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c -} - -.btn-success.active, .btn-success.focus, .btn-success:active, - .btn-success:focus, .btn-success:hover, .open>.dropdown-toggle.btn-success - { - color: #fff; - background-color: #449d44; - border-color: #398439 -} - -.btn-success.active, .btn-success:active, .open>.dropdown-toggle.btn-success - { - background-image: none -} - -.btn-success.disabled, .btn-success.disabled.active, .btn-success.disabled.focus, - .btn-success.disabled:active, .btn-success.disabled:focus, .btn-success.disabled:hover, - .btn-success[disabled], .btn-success[disabled].active, .btn-success[disabled].focus, - .btn-success[disabled]:active, .btn-success[disabled]:focus, - .btn-success[disabled]:hover, fieldset[disabled] .btn-success, fieldset[disabled] .btn-success.active, - fieldset[disabled] .btn-success.focus, fieldset[disabled] .btn-success:active, - fieldset[disabled] .btn-success:focus, fieldset[disabled] .btn-success:hover - { - background-color: #5cb85c; - border-color: #4cae4c -} - -.btn-success .badge { - color: #5cb85c; - background-color: #fff -} - -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da -} - -.btn-info.active, .btn-info.focus, .btn-info:active, .btn-info:focus, - .btn-info:hover, .open>.dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc -} - -.btn-info.active, .btn-info:active, .open>.dropdown-toggle.btn-info { - background-image: none -} - -.btn-info.disabled, .btn-info.disabled.active, .btn-info.disabled.focus, - .btn-info.disabled:active, .btn-info.disabled:focus, .btn-info.disabled:hover, - .btn-info[disabled], .btn-info[disabled].active, .btn-info[disabled].focus, - .btn-info[disabled]:active, .btn-info[disabled]:focus, .btn-info[disabled]:hover, - fieldset[disabled] .btn-info, fieldset[disabled] .btn-info.active, - fieldset[disabled] .btn-info.focus, fieldset[disabled] .btn-info:active, - fieldset[disabled] .btn-info:focus, fieldset[disabled] .btn-info:hover - { - background-color: #5bc0de; - border-color: #46b8da -} - -.btn-info .badge { - color: #5bc0de; - background-color: #fff -} - -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236 -} - -.btn-warning.active, .btn-warning.focus, .btn-warning:active, - .btn-warning:focus, .btn-warning:hover, .open>.dropdown-toggle.btn-warning - { - color: #fff; - background-color: #ec971f; - border-color: #d58512 -} - -.btn-warning.active, .btn-warning:active, .open>.dropdown-toggle.btn-warning - { - background-image: none -} - -.btn-warning.disabled, .btn-warning.disabled.active, .btn-warning.disabled.focus, - .btn-warning.disabled:active, .btn-warning.disabled:focus, .btn-warning.disabled:hover, - .btn-warning[disabled], .btn-warning[disabled].active, .btn-warning[disabled].focus, - .btn-warning[disabled]:active, .btn-warning[disabled]:focus, - .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning, fieldset[disabled] .btn-warning.active, - fieldset[disabled] .btn-warning.focus, fieldset[disabled] .btn-warning:active, - fieldset[disabled] .btn-warning:focus, fieldset[disabled] .btn-warning:hover - { - background-color: #f0ad4e; - border-color: #eea236 -} - -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff -} - -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a -} - -.btn-danger.active, .btn-danger.focus, .btn-danger:active, .btn-danger:focus, - .btn-danger:hover, .open>.dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925 -} - -.btn-danger.active, .btn-danger:active, .open>.dropdown-toggle.btn-danger - { - background-image: none -} - -.btn-danger.disabled, .btn-danger.disabled.active, .btn-danger.disabled.focus, - .btn-danger.disabled:active, .btn-danger.disabled:focus, .btn-danger.disabled:hover, - .btn-danger[disabled], .btn-danger[disabled].active, .btn-danger[disabled].focus, - .btn-danger[disabled]:active, .btn-danger[disabled]:focus, .btn-danger[disabled]:hover, - fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger.active, - fieldset[disabled] .btn-danger.focus, fieldset[disabled] .btn-danger:active, - fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:hover - { - background-color: #d9534f; - border-color: #d43f3a -} - -.btn-danger .badge { - color: #d9534f; - background-color: #fff -} - -.btn-link { - font-weight: 400; - color: #337ab7; - border-radius: 0 -} - -.btn-link, .btn-link.active, .btn-link:active, .btn-link[disabled], - fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none -} - -.btn-link, .btn-link:active, .btn-link:focus, .btn-link:hover { - border-color: transparent -} - -.btn-link:focus, .btn-link:hover { - color: #23527c; - text-decoration: underline; - background-color: transparent -} - -.btn-link[disabled]:focus, .btn-link[disabled]:hover, fieldset[disabled] .btn-link:focus, - fieldset[disabled] .btn-link:hover { - color: #777; - text-decoration: none -} - -.btn-group-lg>.btn, .btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -.btn-group-sm>.btn, .btn-sm { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -.btn-group-xs>.btn, .btn-xs { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -.btn-block { - display: block; - width: 100% -} - -.btn-block+.btn-block { - margin-top: 5px -} - -input[type=button].btn-block, input[type=reset].btn-block, input[type=submit].btn-block - { - width: 100% -} - -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear -} - -.fade.in { - opacity: 1 -} - -.collapse { - display: none -} - -.collapse.in { - display: block -} - -tr.collapse.in { - display: table-row -} - -tbody.collapse.in { - display: table-row-group -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility -} - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-right: 4px solid transparent; - border-left: 4px solid transparent -} - -.dropdown, .dropup { - position: relative -} - -.dropdown-toggle:focus { - outline: 0 -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175) -} - -.dropdown-menu.pull-right { - right: 0; - left: auto -} - -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5 -} - -.dropdown-menu>li>a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: 400; - line-height: 1.42857143; - color: #333; - white-space: nowrap -} - -.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover { - color: #262626; - text-decoration: none; - background-color: #f5f5f5 -} - -.dropdown-menu>.active>a, .dropdown-menu>.active>a:focus, .dropdown-menu>.active>a:hover - { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0 -} - -.dropdown-menu>.disabled>a, .dropdown-menu>.disabled>a:focus, - .dropdown-menu>.disabled>a:hover { - color: #777 -} - -.dropdown-menu>.disabled>a:focus, .dropdown-menu>.disabled>a:hover { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) -} - -.open>.dropdown-menu { - display: block -} - -.open>a { - outline: 0 -} - -.dropdown-menu-right { - right: 0; - left: auto -} - -.dropdown-menu-left { - right: auto; - left: 0 -} - -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990 -} - -.pull-right>.dropdown-menu { - right: 0; - left: auto -} - -.dropup .caret, .navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px solid -} - -.dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px -} - -@media ( min-width :768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0 - } -} - -.btn-group, .btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle -} - -.btn-group-vertical>.btn, .btn-group>.btn { - position: relative; - float: left -} - -.btn-group-vertical>.btn.active, .btn-group-vertical>.btn:active, - .btn-group-vertical>.btn:focus, .btn-group-vertical>.btn:hover, - .btn-group>.btn.active, .btn-group>.btn:active, .btn-group>.btn:focus, - .btn-group>.btn:hover { - z-index: 2 -} - -.btn-group .btn+.btn, .btn-group .btn+.btn-group, .btn-group .btn-group+.btn, - .btn-group .btn-group+.btn-group { - margin-left: -1px -} - -.btn-toolbar { - margin-left: -5px -} - -.btn-toolbar .btn-group, .btn-toolbar .input-group { - float: left -} - -.btn-toolbar>.btn, .btn-toolbar>.btn-group, .btn-toolbar>.input-group { - margin-left: 5px -} - -.btn-group>.btn:not (:first-child ):not (:last-child ):not (.dropdown-toggle - ){ - border-radius: 0 -} - -.btn-group>.btn:first-child { - margin-left: 0 -} - -.btn-group>.btn:first-child:not (:last-child ):not (.dropdown-toggle ){ - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.btn-group>.btn:last-child:not (:first-child ), .btn-group>.dropdown-toggle:not - (:first-child ){ - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group>.btn-group { - float: left -} - -.btn-group>.btn-group:not (:first-child ):not (:last-child )>.btn { - border-radius: 0 -} - -.btn-group>.btn-group:first-child:not (:last-child )>.btn:last-child, - .btn-group>.btn-group:first-child:not (:last-child )>.dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.btn-group>.btn-group:last-child:not (:first-child )>.btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { - outline: 0 -} - -.btn-group>.btn+.dropdown-toggle { - padding-right: 8px; - padding-left: 8px -} - -.btn-group>.btn-lg+.dropdown-toggle { - padding-right: 12px; - padding-left: 12px -} - -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125) -} - -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none -} - -.btn .caret { - margin-left: 0 -} - -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0 -} - -.dropup .btn-lg .caret { - border-width: 0 5px 5px -} - -.btn-group-vertical>.btn, .btn-group-vertical>.btn-group, - .btn-group-vertical>.btn-group>.btn { - display: block; - float: none; - width: 100%; - max-width: 100% -} - -.btn-group-vertical>.btn-group>.btn { - float: none -} - -.btn-group-vertical>.btn+.btn, .btn-group-vertical>.btn+.btn-group, - .btn-group-vertical>.btn-group+.btn, .btn-group-vertical>.btn-group+.btn-group - { - margin-top: -1px; - margin-left: 0 -} - -.btn-group-vertical>.btn:not (:first-child ):not (:last-child ){ - border-radius: 0 -} - -.btn-group-vertical>.btn:first-child:not (:last-child ){ - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group-vertical>.btn:last-child:not (:first-child ){ - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px -} - -.btn-group-vertical>.btn-group:not (:first-child ):not (:last-child )>.btn - { - border-radius: 0 -} - -.btn-group-vertical>.btn-group:first-child:not (:last-child )>.btn:last-child, - .btn-group-vertical>.btn-group:first-child:not (:last-child )>.dropdown-toggle - { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.btn-group-vertical>.btn-group:last-child:not (:first-child )>.btn:first-child - { - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate -} - -.btn-group-justified>.btn, .btn-group-justified>.btn-group { - display: table-cell; - float: none; - width: 1% -} - -.btn-group-justified>.btn-group .btn { - width: 100% -} - -.btn-group-justified>.btn-group .dropdown-menu { - left: auto -} - -[data-toggle=buttons]>.btn input[type=checkbox], [data-toggle=buttons]>.btn input[type=radio], - [data-toggle=buttons]>.btn-group>.btn input[type=checkbox], [data-toggle=buttons]>.btn-group>.btn input[type=radio] - { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none -} - -.input-group { - position: relative; - display: table; - border-collapse: separate -} - -.input-group[class*=col-] { - float: none; - padding-right: 0; - padding-left: 0 -} - -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0 -} - -.input-group-lg>.form-control, .input-group-lg>.input-group-addon, - .input-group-lg>.input-group-btn>.btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px -} - -select.input-group-lg>.form-control, select.input-group-lg>.input-group-addon, - select.input-group-lg>.input-group-btn>.btn { - height: 46px; - line-height: 46px -} - -select[multiple].input-group-lg>.form-control, select[multiple].input-group-lg>.input-group-addon, - select[multiple].input-group-lg>.input-group-btn>.btn, textarea.input-group-lg>.form-control, - textarea.input-group-lg>.input-group-addon, textarea.input-group-lg>.input-group-btn>.btn - { - height: auto -} - -.input-group-sm>.form-control, .input-group-sm>.input-group-addon, - .input-group-sm>.input-group-btn>.btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px -} - -select.input-group-sm>.form-control, select.input-group-sm>.input-group-addon, - select.input-group-sm>.input-group-btn>.btn { - height: 30px; - line-height: 30px -} - -select[multiple].input-group-sm>.form-control, select[multiple].input-group-sm>.input-group-addon, - select[multiple].input-group-sm>.input-group-btn>.btn, textarea.input-group-sm>.form-control, - textarea.input-group-sm>.input-group-addon, textarea.input-group-sm>.input-group-btn>.btn - { - height: auto -} - -.input-group .form-control, .input-group-addon, .input-group-btn { - display: table-cell -} - -.input-group .form-control:not (:first-child ):not (:last-child ), - .input-group-addon:not (:first-child ):not (:last-child ), - .input-group-btn:not (:first-child ):not (:last-child ){ - border-radius: 0 -} - -.input-group-addon, .input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle -} - -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: 400; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px -} - -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px -} - -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px -} - -.input-group-addon input[type=checkbox], .input-group-addon input[type=radio] - { - margin-top: 0 -} - -.input-group .form-control:first-child, .input-group-addon:first-child, - .input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group>.btn, - .input-group-btn:first-child>.dropdown-toggle, .input-group-btn:last-child>.btn-group:not - (:last-child )>.btn, .input-group-btn:last-child>.btn:not (:last-child - ):not (.dropdown-toggle ){ - border-top-right-radius: 0; - border-bottom-right-radius: 0 -} - -.input-group-addon:first-child { - border-right: 0 -} - -.input-group .form-control:last-child, .input-group-addon:last-child, - .input-group-btn:first-child>.btn-group:not (:first-child )>.btn, - .input-group-btn:first-child>.btn:not (:first-child ), .input-group-btn:last-child>.btn, - .input-group-btn:last-child>.btn-group>.btn, .input-group-btn:last-child>.dropdown-toggle - { - border-top-left-radius: 0; - border-bottom-left-radius: 0 -} - -.input-group-addon:last-child { - border-left: 0 -} - -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap -} - -.input-group-btn>.btn { - position: relative -} - -.input-group-btn>.btn+.btn { - margin-left: -1px -} - -.input-group-btn>.btn:active, .input-group-btn>.btn:focus, - .input-group-btn>.btn:hover { - z-index: 2 -} - -.input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group - { - margin-right: -1px -} - -.input-group-btn:last-child>.btn, .input-group-btn:last-child>.btn-group - { - margin-left: -1px -} - -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none -} - -.nav>li { - position: relative; - display: block -} - -.nav>li>a { - position: relative; - display: block; - padding: 10px 15px -} - -.nav>li>a:focus, .nav>li>a:hover { - text-decoration: none; - background-color: #eee -} - -.nav>li.disabled>a { - color: #777 -} - -.nav>li.disabled>a:focus, .nav>li.disabled>a:hover { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent -} - -.nav .open>a, .nav .open>a:focus, .nav .open>a:hover { - background-color: #eee; - border-color: #337ab7 -} - -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5 -} - -.nav>li>a>img { - max-width: none -} - -.nav-tabs { - border-bottom: 1px solid #ddd -} - -.nav-tabs>li { - float: left; - margin-bottom: -1px -} - -.nav-tabs>li>a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0 -} - -.nav-tabs>li>a:hover { - border-color: #eee #eee #ddd -} - -.nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover - { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent -} - -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0 -} - -.nav-tabs.nav-justified>li { - float: none -} - -.nav-tabs.nav-justified>li>a { - margin-bottom: 5px; - text-align: center -} - -.nav-tabs.nav-justified>.dropdown .dropdown-menu { - top: auto; - left: auto -} - -@media ( min-width :768px) { - .nav-tabs.nav-justified>li { - display: table-cell; - width: 1% - } - .nav-tabs.nav-justified>li>a { - margin-bottom: 0 - } -} - -.nav-tabs.nav-justified>li>a { - margin-right: 0; - border-radius: 4px -} - -.nav-tabs.nav-justified>.active>a, .nav-tabs.nav-justified>.active>a:focus, - .nav-tabs.nav-justified>.active>a:hover { - border: 1px solid #ddd -} - -@media ( min-width :768px) { - .nav-tabs.nav-justified>li>a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0 - } - .nav-tabs.nav-justified>.active>a, .nav-tabs.nav-justified>.active>a:focus, - .nav-tabs.nav-justified>.active>a:hover { - border-bottom-color: #fff - } -} - -.nav-pills>li { - float: left -} - -.nav-pills>li>a { - border-radius: 4px -} - -.nav-pills>li+li { - margin-left: 2px -} - -.nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover - { - color: #fff; - background-color: #337ab7 -} - -.nav-stacked>li { - float: none -} - -.nav-stacked>li+li { - margin-top: 2px; - margin-left: 0 -} - -.nav-justified { - width: 100% -} - -.nav-justified>li { - float: none -} - -.nav-justified>li>a { - margin-bottom: 5px; - text-align: center -} - -.nav-justified>.dropdown .dropdown-menu { - top: auto; - left: auto -} - -@media ( min-width :768px) { - .nav-justified>li { - display: table-cell; - width: 1% - } - .nav-justified>li>a { - margin-bottom: 0 - } -} - -.nav-tabs-justified { - border-bottom: 0 -} - -.nav-tabs-justified>li>a { - margin-right: 0; - border-radius: 4px -} - -.nav-tabs-justified>.active>a, .nav-tabs-justified>.active>a:focus, - .nav-tabs-justified>.active>a:hover { - border: 1px solid #ddd -} - -@media ( min-width :768px) { - .nav-tabs-justified>li>a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0 - } - .nav-tabs-justified>.active>a, .nav-tabs-justified>.active>a:focus, - .nav-tabs-justified>.active>a:hover { - border-bottom-color: #fff - } -} - -.tab-content>.tab-pane { - display: none -} - -.tab-content>.active { - display: block -} - -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent -} - -@media ( min-width :768px) { - .navbar { - border-radius: 4px - } -} - -@media ( min-width :768px) { - .navbar-header { - float: left - } -} - -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1) -} - -.navbar-collapse.in { - overflow-y: auto -} - -@media ( min-width :768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important - } - .navbar-collapse.in { - overflow-y: visible - } - .navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse { - padding-right: 0; - padding-left: 0 - } -} - -.navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse - { - max-height: 340px -} - -@media ( max-device-width :480px)and (orientation:landscape) { - .navbar-fixed-bottom .navbar-collapse, .navbar-fixed-top .navbar-collapse - { - max-height: 200px - } -} - -.container-fluid>.navbar-collapse, .container-fluid>.navbar-header, - .container>.navbar-collapse, .container>.navbar-header { - margin-right: -15px; - margin-left: -15px -} - -@media ( min-width :768px) { - .container-fluid>.navbar-collapse, .container-fluid>.navbar-header, - .container>.navbar-collapse, .container>.navbar-header { - margin-right: 0; - margin-left: 0 - } -} - -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px -} - -@media ( min-width :768px) { - .navbar-static-top { - border-radius: 0 - } -} - -.navbar-fixed-bottom, .navbar-fixed-top { - position: fixed; - right: 0; - left: 0; - z-index: 1030 -} - -@media ( min-width :768px) { - .navbar-fixed-bottom, .navbar-fixed-top { - border-radius: 0 - } -} - -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px -} - -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0 -} - -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px -} - -.navbar-brand:focus, .navbar-brand:hover { - text-decoration: none -} - -.navbar-brand>img { - display: block -} - -@media ( min-width :768px) { - .navbar>.container .navbar-brand, .navbar>.container-fluid .navbar-brand - { - margin-left: -15px - } -} - -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px -} - -.navbar-toggle:focus { - outline: 0 -} - -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px -} - -.navbar-toggle .icon-bar+.icon-bar { - margin-top: 4px -} - -@media ( min-width :768px) { - .navbar-toggle { - display: none - } -} - -.navbar-nav { - margin: 7.5px -15px -} - -.navbar-nav>li>a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px -} - -@media ( max-width :767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none - } - .navbar-nav .open .dropdown-menu .dropdown-header, .navbar-nav .open .dropdown-menu>li>a - { - padding: 5px 15px 5px 25px - } - .navbar-nav .open .dropdown-menu>li>a { - line-height: 20px - } - .navbar-nav .open .dropdown-menu>li>a:focus, .navbar-nav .open .dropdown-menu>li>a:hover - { - background-image: none - } -} - -@media ( min-width :768px) { - .navbar-nav { - float: left; - margin: 0 - } - .navbar-nav>li { - float: left - } - .navbar-nav>li>a { - padding-top: 15px; - padding-bottom: 15px - } -} - -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 - rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 - rgba(255, 255, 255, .1) -} - -@media ( min-width :768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle - } - .navbar-form .form-control-static { - display: inline-block - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle - } - .navbar-form .input-group .form-control, .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn { - width: auto - } - .navbar-form .input-group>.form-control { - width: 100% - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .checkbox, .navbar-form .radio { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle - } - .navbar-form .checkbox label, .navbar-form .radio label { - padding-left: 0 - } - .navbar-form .checkbox input[type=checkbox], .navbar-form .radio input[type=radio] - { - position: relative; - margin-left: 0 - } - .navbar-form .has-feedback .form-control-feedback { - top: 0 - } -} - -@media ( max-width :767px) { - .navbar-form .form-group { - margin-bottom: 5px - } - .navbar-form .form-group:last-child { - margin-bottom: 0 - } -} - -@media ( min-width :768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none - } -} - -.navbar-nav>li>.dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0 -} - -.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0 -} - -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px -} - -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px -} - -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px -} - -.navbar-text { - margin-top: 15px; - margin-bottom: 15px -} - -@media ( min-width :768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px - } -} - -@media ( min-width :768px) { - .navbar-left { - float: left !important - } - .navbar-right { - float: right !important; - margin-right: -15px - } - .navbar-right ~.navbar-right { - margin-right: 0 - } -} - -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7 -} - -.navbar-default .navbar-brand { - color: #777 -} - -.navbar-default .navbar-brand:focus, .navbar-default .navbar-brand:hover - { - color: #5e5e5e; - background-color: transparent -} - -.navbar-default .navbar-text { - color: #777 -} - -.navbar-default .navbar-nav>li>a { - color: #777 -} - -.navbar-default .navbar-nav>li>a:focus, .navbar-default .navbar-nav>li>a:hover - { - color: #333; - background-color: transparent -} - -.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, - .navbar-default .navbar-nav>.active>a:hover { - color: #555; - background-color: #e7e7e7 -} - -.navbar-default .navbar-nav>.disabled>a, .navbar-default .navbar-nav>.disabled>a:focus, - .navbar-default .navbar-nav>.disabled>a:hover { - color: #ccc; - background-color: transparent -} - -.navbar-default .navbar-toggle { - border-color: #ddd -} - -.navbar-default .navbar-toggle:focus, .navbar-default .navbar-toggle:hover - { - background-color: #ddd -} - -.navbar-default .navbar-toggle .icon-bar { - background-color: #888 -} - -.navbar-default .navbar-collapse, .navbar-default .navbar-form { - border-color: #e7e7e7 -} - -.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, - .navbar-default .navbar-nav>.open>a:hover { - color: #555; - background-color: #e7e7e7 -} - -@media ( max-width :767px) { - .navbar-default .navbar-nav .open .dropdown-menu>li>a { - color: #777 - } - .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>li>a:hover { - color: #333; - background-color: transparent - } - .navbar-default .navbar-nav .open .dropdown-menu>.active>a, - .navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover { - color: #555; - background-color: #e7e7e7 - } - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a, - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus, - .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover { - color: #ccc; - background-color: transparent - } -} - -.navbar-default .navbar-link { - color: #777 -} - -.navbar-default .navbar-link:hover { - color: #333 -} - -.navbar-default .btn-link { - color: #777 -} - -.navbar-default .btn-link:focus, .navbar-default .btn-link:hover { - color: #333 -} - -.navbar-default .btn-link[disabled]:focus, .navbar-default .btn-link[disabled]:hover, - fieldset[disabled] .navbar-default .btn-link:focus, fieldset[disabled] .navbar-default .btn-link:hover - { - color: #ccc -} - -.navbar-inverse { - background-color: #222; - border-color: #080808 -} - -.navbar-inverse .navbar-brand { - color: #9d9d9d -} - -.navbar-inverse .navbar-brand:focus, .navbar-inverse .navbar-brand:hover - { - color: #fff; - background-color: transparent -} - -.navbar-inverse .navbar-text { - color: #9d9d9d -} - -.navbar-inverse .navbar-nav>li>a { - color: #9d9d9d -} - -.navbar-inverse .navbar-nav>li>a:focus, .navbar-inverse .navbar-nav>li>a:hover - { - color: #fff; - background-color: transparent -} - -.navbar-inverse .navbar-nav>.active>a, .navbar-inverse .navbar-nav>.active>a:focus, - .navbar-inverse .navbar-nav>.active>a:hover { - color: #fff; - background-color: #080808 -} - -.navbar-inverse .navbar-nav>.disabled>a, .navbar-inverse .navbar-nav>.disabled>a:focus, - .navbar-inverse .navbar-nav>.disabled>a:hover { - color: #444; - background-color: transparent -} - -.navbar-inverse .navbar-toggle { - border-color: #333 -} - -.navbar-inverse .navbar-toggle:focus, .navbar-inverse .navbar-toggle:hover - { - background-color: #333 -} - -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff -} - -.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { - border-color: #101010 -} - -.navbar-inverse .navbar-nav>.open>a, .navbar-inverse .navbar-nav>.open>a:focus, - .navbar-inverse .navbar-nav>.open>a:hover { - color: #fff; - background-color: #080808 -} - -@media ( max-width :767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header { - border-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a { - color: #9d9d9d - } - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover { - color: #fff; - background-color: transparent - } - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a, - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover { - color: #fff; - background-color: #080808 - } - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a, - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus, - .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover { - color: #444; - background-color: transparent - } -} - -.navbar-inverse .navbar-link { - color: #9d9d9d -} - -.navbar-inverse .navbar-link:hover { - color: #fff -} - -.navbar-inverse .btn-link { - color: #9d9d9d -} - -.navbar-inverse .btn-link:focus, .navbar-inverse .btn-link:hover { - color: #fff -} - -.navbar-inverse .btn-link[disabled]:focus, .navbar-inverse .btn-link[disabled]:hover, - fieldset[disabled] .navbar-inverse .btn-link:focus, fieldset[disabled] .navbar-inverse .btn-link:hover - { - color: #444 -} - -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px -} - -.breadcrumb>li { - display: inline-block -} - -.breadcrumb>li+li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0" -} - -.breadcrumb>.active { - color: #777 -} - -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px -} - -.pagination>li { - display: inline -} - -.pagination>li>a, .pagination>li>span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd -} - -.pagination>li:first-child>a, .pagination>li:first-child>span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px -} - -.pagination>li:last-child>a, .pagination>li:last-child>span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px -} - -.pagination>li>a:focus, .pagination>li>a:hover, .pagination>li>span:focus, - .pagination>li>span:hover { - color: #23527c; - background-color: #eee; - border-color: #ddd -} - -.pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, - .pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover - { - z-index: 2; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7 -} - -.pagination>.disabled>a, .pagination>.disabled>a:focus, .pagination>.disabled>a:hover, - .pagination>.disabled>span, .pagination>.disabled>span:focus, - .pagination>.disabled>span:hover { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd -} - -.pagination-lg>li>a, .pagination-lg>li>span { - padding: 10px 16px; - font-size: 18px -} - -.pagination-lg>li:first-child>a, .pagination-lg>li:first-child>span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px -} - -.pagination-lg>li:last-child>a, .pagination-lg>li:last-child>span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px -} - -.pagination-sm>li>a, .pagination-sm>li>span { - padding: 5px 10px; - font-size: 12px -} - -.pagination-sm>li:first-child>a, .pagination-sm>li:first-child>span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px -} - -.pagination-sm>li:last-child>a, .pagination-sm>li:last-child>span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px -} - -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none -} - -.pager li { - display: inline -} - -.pager li>a, .pager li>span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px -} - -.pager li>a:focus, .pager li>a:hover { - text-decoration: none; - background-color: #eee -} - -.pager .next>a, .pager .next>span { - float: right -} - -.pager .previous>a, .pager .previous>span { - float: left -} - -.pager .disabled>a, .pager .disabled>a:focus, .pager .disabled>a:hover, - .pager .disabled>span { - color: #777; - cursor: not-allowed; - background-color: #fff -} - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em -} - -a.label:focus, a.label:hover { - color: #fff; - text-decoration: none; - cursor: pointer -} - -.label:empty { - display: none -} - -.btn .label { - position: relative; - top: -1px -} - -.label-default { - background-color: #777 -} - -.label-default[href]:focus, .label-default[href]:hover { - background-color: #5e5e5e -} - -.label-primary { - background-color: #337ab7 -} - -.label-primary[href]:focus, .label-primary[href]:hover { - background-color: #286090 -} - -.label-success { - background-color: #5cb85c -} - -.label-success[href]:focus, .label-success[href]:hover { - background-color: #449d44 -} - -.label-info { - background-color: #5bc0de -} - -.label-info[href]:focus, .label-info[href]:hover { - background-color: #31b0d5 -} - -.label-warning { - background-color: #f0ad4e -} - -.label-warning[href]:focus, .label-warning[href]:hover { - background-color: #ec971f -} - -.label-danger { - background-color: #d9534f -} - -.label-danger[href]:focus, .label-danger[href]:hover { - background-color: #c9302c -} - -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #777; - border-radius: 10px -} - -.badge:empty { - display: none -} - -.btn .badge { - position: relative; - top: -1px -} - -.btn-group-xs>.btn .badge, .btn-xs .badge { - top: 0; - padding: 1px 5px -} - -a.badge:focus, a.badge:hover { - color: #fff; - text-decoration: none; - cursor: pointer -} - -.list-group-item.active>.badge, .nav-pills>.active>a>.badge { - color: #337ab7; - background-color: #fff -} - -.list-group-item>.badge { - float: right -} - -.list-group-item>.badge+.badge { - margin-right: 5px -} - -.nav-pills>li>a>.badge { - margin-left: 3px -} - -.jumbotron { - padding: 30px 15px; - margin-bottom: 30px; - color: inherit; - background-color: #eee -} - -.jumbotron .h1, .jumbotron h1 { - color: inherit -} - -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200 -} - -.jumbotron>hr { - border-top-color: #d5d5d5 -} - -.container .jumbotron, .container-fluid .jumbotron { - border-radius: 6px -} - -.jumbotron .container { - max-width: 100% -} - -@media screen and (min-width:768px) { - .jumbotron { - padding: 48px 0 - } - .container .jumbotron, .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px - } - .jumbotron .h1, .jumbotron h1 { - font-size: 63px - } -} - -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out -} - -.thumbnail a>img, .thumbnail>img { - margin-right: auto; - margin-left: auto -} - -a.thumbnail.active, a.thumbnail:focus, a.thumbnail:hover { - border-color: #337ab7 -} - -.thumbnail .caption { - padding: 9px; - color: #333 -} - -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px -} - -.alert h4 { - margin-top: 0; - color: inherit -} - -.alert .alert-link { - font-weight: 700 -} - -.alert>p, .alert>ul { - margin-bottom: 0 -} - -.alert>p+p { - margin-top: 5px -} - -.alert-dismissable, .alert-dismissible { - padding-right: 35px -} - -.alert-dismissable .close, .alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit -} - -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6 -} - -.alert-success hr { - border-top-color: #c9e2b3 -} - -.alert-success .alert-link { - color: #2b542c -} - -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1 -} - -.alert-info hr { - border-top-color: #a6e1ec -} - -.alert-info .alert-link { - color: #245269 -} - -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc -} - -.alert-warning hr { - border-top-color: #f7e1b5 -} - -.alert-warning .alert-link { - color: #66512c -} - -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1 -} - -.alert-danger hr { - border-top-color: #e4b9c0 -} - -.alert-danger .alert-link { - color: #843534 -} - -@ --webkit-keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -@ --o-keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -@ -keyframes progress-bar-stripes { - from {background-position: 40px 0 -} - -to { - background-position: 0 0 -} - -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1) -} - -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease -} - -.progress-bar-striped, .progress-striped .progress-bar { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px -} - -.progress-bar.active, .progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite -} - -.progress-bar-success { - background-color: #5cb85c -} - -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-info { - background-color: #5bc0de -} - -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-warning { - background-color: #f0ad4e -} - -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.progress-bar-danger { - background-color: #d9534f -} - -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) - 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, - transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, - rgba(255, 255, 255, .15) 75%, transparent 75%, transparent) -} - -.media { - margin-top: 15px -} - -.media:first-child { - margin-top: 0 -} - -.media, .media-body { - overflow: hidden; - zoom: 1 -} - -.media-body { - width: 10000px -} - -.media-object { - display: block -} - -.media-right, .media>.pull-right { - padding-left: 10px -} - -.media-left, .media>.pull-left { - padding-right: 10px -} - -.media-body, .media-left, .media-right { - display: table-cell; - vertical-align: top -} - -.media-middle { - vertical-align: middle -} - -.media-bottom { - vertical-align: bottom -} - -.media-heading { - margin-top: 0; - margin-bottom: 5px -} - -.media-list { - padding-left: 0; - list-style: none -} - -.list-group { - padding-left: 0; - margin-bottom: 20px -} - -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd -} - -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px -} - -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px -} - -a.list-group-item { - color: #555 -} - -a.list-group-item .list-group-item-heading { - color: #333 -} - -a.list-group-item:focus, a.list-group-item:hover { - color: #555; - text-decoration: none; - background-color: #f5f5f5 -} - -.list-group-item.disabled, .list-group-item.disabled:focus, - .list-group-item.disabled:hover { - color: #777; - cursor: not-allowed; - background-color: #eee -} - -.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, - .list-group-item.disabled:hover .list-group-item-heading { - color: inherit -} - -.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, - .list-group-item.disabled:hover .list-group-item-text { - color: #777 -} - -.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover - { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7 -} - -.list-group-item.active .list-group-item-heading, .list-group-item.active .list-group-item-heading>.small, - .list-group-item.active .list-group-item-heading>small, - .list-group-item.active:focus .list-group-item-heading, - .list-group-item.active:focus .list-group-item-heading>.small, - .list-group-item.active:focus .list-group-item-heading>small, - .list-group-item.active:hover .list-group-item-heading, - .list-group-item.active:hover .list-group-item-heading>.small, - .list-group-item.active:hover .list-group-item-heading>small { - color: inherit -} - -.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, - .list-group-item.active:hover .list-group-item-text { - color: #c7ddef -} - -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8 -} - -a.list-group-item-success { - color: #3c763d -} - -a.list-group-item-success .list-group-item-heading { - color: inherit -} - -a.list-group-item-success:focus, a.list-group-item-success:hover { - color: #3c763d; - background-color: #d0e9c6 -} - -a.list-group-item-success.active, a.list-group-item-success.active:focus, - a.list-group-item-success.active:hover { - color: #fff; - background-color: #3c763d; - border-color: #3c763d -} - -.list-group-item-info { - color: #31708f; - background-color: #d9edf7 -} - -a.list-group-item-info { - color: #31708f -} - -a.list-group-item-info .list-group-item-heading { - color: inherit -} - -a.list-group-item-info:focus, a.list-group-item-info:hover { - color: #31708f; - background-color: #c4e3f3 -} - -a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover - { - color: #fff; - background-color: #31708f; - border-color: #31708f -} - -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3 -} - -a.list-group-item-warning { - color: #8a6d3b -} - -a.list-group-item-warning .list-group-item-heading { - color: inherit -} - -a.list-group-item-warning:focus, a.list-group-item-warning:hover { - color: #8a6d3b; - background-color: #faf2cc -} - -a.list-group-item-warning.active, a.list-group-item-warning.active:focus, - a.list-group-item-warning.active:hover { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b -} - -.list-group-item-danger { - color: #a94442; - background-color: #f2dede -} - -a.list-group-item-danger { - color: #a94442 -} - -a.list-group-item-danger .list-group-item-heading { - color: inherit -} - -a.list-group-item-danger:focus, a.list-group-item-danger:hover { - color: #a94442; - background-color: #ebcccc -} - -a.list-group-item-danger.active, a.list-group-item-danger.active:focus, - a.list-group-item-danger.active:hover { - color: #fff; - background-color: #a94442; - border-color: #a94442 -} - -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px -} - -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3 -} - -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05) -} - -.panel-body { - padding: 15px -} - -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel-heading>.dropdown .dropdown-toggle { - color: inherit -} - -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit -} - -.panel-title>.small, .panel-title>.small>a, .panel-title>a, .panel-title>small, - .panel-title>small>a { - color: inherit -} - -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.list-group, .panel>.panel-collapse>.list-group { - margin-bottom: 0 -} - -.panel>.list-group .list-group-item, .panel>.panel-collapse>.list-group .list-group-item - { - border-width: 1px 0; - border-radius: 0 -} - -.panel>.list-group:first-child .list-group-item:first-child, .panel>.panel-collapse>.list-group:first-child .list-group-item:first-child - { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.list-group:last-child .list-group-item:last-child, .panel>.panel-collapse>.list-group:last-child .list-group-item:last-child - { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel-heading+.list-group .list-group-item:first-child { - border-top-width: 0 -} - -.list-group+.panel-footer { - border-top-width: 0 -} - -.panel>.panel-collapse>.table, .panel>.table, .panel>.table-responsive>.table - { - margin-bottom: 0 -} - -.panel>.panel-collapse>.table caption, .panel>.table caption, .panel>.table-responsive>.table caption - { - padding-right: 15px; - padding-left: 15px -} - -.panel>.table-responsive:first-child>.table:first-child, .panel>.table:first-child - { - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child, .panel>.table:first-child>thead:first-child>tr:first-child - { - border-top-left-radius: 3px; - border-top-right-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child, - .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child td:first-child, - .panel>.table:first-child>tbody:first-child>tr:first-child th:first-child, - .panel>.table:first-child>thead:first-child>tr:first-child td:first-child, - .panel>.table:first-child>thead:first-child>tr:first-child th:first-child - { - border-top-left-radius: 3px -} - -.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child, - .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child, - .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child, - .panel>.table:first-child>tbody:first-child>tr:first-child td:last-child, - .panel>.table:first-child>tbody:first-child>tr:first-child th:last-child, - .panel>.table:first-child>thead:first-child>tr:first-child td:last-child, - .panel>.table:first-child>thead:first-child>tr:first-child th:last-child - { - border-top-right-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child, .panel>.table:last-child - { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child, .panel>.table:last-child>tfoot:last-child>tr:last-child - { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child, - .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child, - .panel>.table:last-child>tbody:last-child>tr:last-child td:first-child, - .panel>.table:last-child>tbody:last-child>tr:last-child th:first-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child - { - border-bottom-left-radius: 3px -} - -.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child, - .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child, - .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child, - .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child, - .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child { - border-bottom-right-radius: 3px -} - -.panel>.panel-body+.table, .panel>.panel-body+.table-responsive, .panel>.table+.panel-body, - .panel>.table-responsive+.panel-body { - border-top: 1px solid #ddd -} - -.panel>.table>tbody:first-child>tr:first-child td, .panel>.table>tbody:first-child>tr:first-child th - { - border-top: 0 -} - -.panel>.table-bordered, .panel>.table-responsive>.table-bordered { - border: 0 -} - -.panel>.table-bordered>tbody>tr>td:first-child, .panel>.table-bordered>tbody>tr>th:first-child, - .panel>.table-bordered>tfoot>tr>td:first-child, .panel>.table-bordered>tfoot>tr>th:first-child, - .panel>.table-bordered>thead>tr>td:first-child, .panel>.table-bordered>thead>tr>th:first-child, - .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child, - .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child, - .panel>.table-responsive>.table-bordered>thead>tr>td:first-child, - .panel>.table-responsive>.table-bordered>thead>tr>th:first-child { - border-left: 0 -} - -.panel>.table-bordered>tbody>tr>td:last-child, .panel>.table-bordered>tbody>tr>th:last-child, - .panel>.table-bordered>tfoot>tr>td:last-child, .panel>.table-bordered>tfoot>tr>th:last-child, - .panel>.table-bordered>thead>tr>td:last-child, .panel>.table-bordered>thead>tr>th:last-child, - .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child, .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child, - .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child, .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child, - .panel>.table-responsive>.table-bordered>thead>tr>td:last-child, .panel>.table-responsive>.table-bordered>thead>tr>th:last-child - { - border-right: 0 -} - -.panel>.table-bordered>tbody>tr:first-child>td, .panel>.table-bordered>tbody>tr:first-child>th, - .panel>.table-bordered>thead>tr:first-child>td, .panel>.table-bordered>thead>tr:first-child>th, - .panel>.table-responsive>.table-bordered>tbody>tr:first-child>td, - .panel>.table-responsive>.table-bordered>tbody>tr:first-child>th, - .panel>.table-responsive>.table-bordered>thead>tr:first-child>td, - .panel>.table-responsive>.table-bordered>thead>tr:first-child>th { - border-bottom: 0 -} - -.panel>.table-bordered>tbody>tr:last-child>td, .panel>.table-bordered>tbody>tr:last-child>th, - .panel>.table-bordered>tfoot>tr:last-child>td, .panel>.table-bordered>tfoot>tr:last-child>th, - .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td, .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th, - .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td, .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th - { - border-bottom: 0 -} - -.panel>.table-responsive { - margin-bottom: 0; - border: 0 -} - -.panel-group { - margin-bottom: 20px -} - -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px -} - -.panel-group .panel+.panel { - margin-top: 5px -} - -.panel-group .panel-heading { - border-bottom: 0 -} - -.panel-group .panel-heading+.panel-collapse>.list-group, .panel-group .panel-heading+.panel-collapse>.panel-body - { - border-top: 1px solid #ddd -} - -.panel-group .panel-footer { - border-top: 0 -} - -.panel-group .panel-footer+.panel-collapse .panel-body { - border-bottom: 1px solid #ddd -} - -.panel-default { - border-color: #ddd -} - -.panel-default>.panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd -} - -.panel-default>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #ddd -} - -.panel-default>.panel-heading .badge { - color: #f5f5f5; - background-color: #333 -} - -.panel-default>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #ddd -} - -.panel-primary { - border-color: #337ab7 -} - -.panel-primary>.panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7 -} - -.panel-primary>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #337ab7 -} - -.panel-primary>.panel-heading .badge { - color: #337ab7; - background-color: #fff -} - -.panel-primary>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #337ab7 -} - -.panel-success { - border-color: #d6e9c6 -} - -.panel-success>.panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6 -} - -.panel-success>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #d6e9c6 -} - -.panel-success>.panel-heading .badge { - color: #dff0d8; - background-color: #3c763d -} - -.panel-success>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #d6e9c6 -} - -.panel-info { - border-color: #bce8f1 -} - -.panel-info>.panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1 -} - -.panel-info>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #bce8f1 -} - -.panel-info>.panel-heading .badge { - color: #d9edf7; - background-color: #31708f -} - -.panel-info>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #bce8f1 -} - -.panel-warning { - border-color: #faebcc -} - -.panel-warning>.panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc -} - -.panel-warning>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #faebcc -} - -.panel-warning>.panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b -} - -.panel-warning>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #faebcc -} - -.panel-danger { - border-color: #ebccd1 -} - -.panel-danger>.panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1 -} - -.panel-danger>.panel-heading+.panel-collapse>.panel-body { - border-top-color: #ebccd1 -} - -.panel-danger>.panel-heading .badge { - color: #f2dede; - background-color: #a94442 -} - -.panel-danger>.panel-footer+.panel-collapse>.panel-body { - border-bottom-color: #ebccd1 -} - -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden -} - -.embed-responsive .embed-responsive-item, .embed-responsive embed, - .embed-responsive iframe, .embed-responsive object, .embed-responsive video - { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0 -} - -.embed-responsive-16by9 { - padding-bottom: 56.25% -} - -.embed-responsive-4by3 { - padding-bottom: 75% -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05) -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15) -} - -.well-lg { - padding: 24px; - border-radius: 6px -} - -.well-sm { - padding: 9px; - border-radius: 3px -} - -.close { - float: right; - font-size: 21px; - font-weight: 700; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity = 20); - opacity: .2 -} - -.close:focus, .close:hover { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity = 50); - opacity: .5 -} - -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: 0 0; - border: 0 -} - -.modal-open { - overflow: hidden -} - -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0 -} - -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%) -} - -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0) -} - -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto -} - -.modal-dialog { - position: relative; - width: auto; - margin: 10px -} - -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5) -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000 -} - -.modal-backdrop.fade { - filter: alpha(opacity = 0); - opacity: 0 -} - -.modal-backdrop.in { - filter: alpha(opacity = 50); - opacity: .5 -} - -.modal-header { - min-height: 16.43px; - padding: 15px; - border-bottom: 1px solid #e5e5e5 -} - -.modal-header .close { - margin-top: -2px -} - -.modal-title { - margin: 0; - line-height: 1.42857143 -} - -.modal-body { - position: relative; - padding: 15px -} - -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5 -} - -.modal-footer .btn+.btn { - margin-bottom: 0; - margin-left: 5px -} - -.modal-footer .btn-group .btn+.btn { - margin-left: -1px -} - -.modal-footer .btn-block+.btn-block { - margin-left: 0 -} - -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll -} - -@media ( min-width :768px) { - .modal-dialog { - width: 600px; - margin: 30px auto - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5) - } - .modal-sm { - width: 300px - } -} - -@media ( min-width :992px) { - .modal-lg { - width: 900px - } -} - -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: 400; - line-height: 1.4; - filter: alpha(opacity = 0); - opacity: 0 -} - -.tooltip.in { - filter: alpha(opacity = 90); - opacity: .9 -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px -} - -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - text-decoration: none; - background-color: #000; - border-radius: 4px -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000 -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000 -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000 -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000 -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-weight: 400; - line-height: 1.42857143; - text-align: left; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2) -} - -.popover.top { - margin-top: -10px -} - -.popover.right { - margin-left: 10px -} - -.popover.bottom { - margin-top: 10px -} - -.popover.left { - margin-left: -10px -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0 -} - -.popover-content { - padding: 9px 14px -} - -.popover>.arrow, .popover>.arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid -} - -.popover>.arrow { - border-width: 11px -} - -.popover>.arrow:after { - content: ""; - border-width: 10px -} - -.popover.top>.arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0 -} - -.popover.top>.arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0 -} - -.popover.right>.arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0 -} - -.popover.right>.arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0 -} - -.popover.bottom>.arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25) -} - -.popover.bottom>.arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff -} - -.popover.left>.arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25) -} - -.popover.left>.arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff -} - -.carousel { - position: relative -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden -} - -.carousel-inner>.item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left -} - -.carousel-inner>.item>a>img, .carousel-inner>.item>img { - line-height: 1 -} - -@media all and (transform-3d) , ( -webkit-transform-3d ) { - .carousel-inner>.item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000; - perspective: 1000 - } - .carousel-inner>.item.active.right, .carousel-inner>.item.next { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0) - } - .carousel-inner>.item.active.left, .carousel-inner>.item.prev { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0) - } - .carousel-inner>.item.active, .carousel-inner>.item.next.left, - .carousel-inner>.item.prev.right { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0) - } -} - -.carousel-inner>.active, .carousel-inner>.next, .carousel-inner>.prev { - display: block -} - -.carousel-inner>.active { - left: 0 -} - -.carousel-inner>.next, .carousel-inner>.prev { - position: absolute; - top: 0; - width: 100% -} - -.carousel-inner>.next { - left: 100% -} - -.carousel-inner>.prev { - left: -100% -} - -.carousel-inner>.next.left, .carousel-inner>.prev.right { - left: 0 -} - -.carousel-inner>.active.left { - left: -100% -} - -.carousel-inner>.active.right { - left: 100% -} - -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - filter: alpha(opacity = 50); - opacity: .5 -} - -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), - to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0, - rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', - endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x -} - -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), - to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0, - rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', - endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x -} - -.carousel-control:focus, .carousel-control:hover { - color: #fff; - text-decoration: none; - filter: alpha(opacity = 90); - outline: 0; - opacity: .9 -} - -.carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next, .carousel-control .icon-prev { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block -} - -.carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev - { - left: 50%; - margin-left: -10px -} - -.carousel-control .glyphicon-chevron-right, .carousel-control .icon-next - { - right: 50%; - margin-right: -10px -} - -.carousel-control .icon-next, .carousel-control .icon-prev { - width: 20px; - height: 20px; - margin-top: -10px; - font-family: serif; - line-height: 1 -} - -.carousel-control .icon-prev:before { - content: '\2039' -} - -.carousel-control .icon-next:before { - content: '\203a' -} - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none -} - -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px -} - -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff -} - -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6) -} - -.carousel-caption .btn { - text-shadow: none -} - -@media screen and (min-width:768px) { - .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next, .carousel-control .icon-prev { - width: 30px; - height: 30px; - margin-top: -15px; - font-size: 30px - } - .carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev - { - margin-left: -15px - } - .carousel-control .glyphicon-chevron-right, .carousel-control .icon-next - { - margin-right: -15px - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px - } - .carousel-indicators { - bottom: 20px - } -} - -.btn-group-vertical>.btn-group:after, .btn-group-vertical>.btn-group:before, - .btn-toolbar:after, .btn-toolbar:before, .clearfix:after, .clearfix:before, - .container-fluid:after, .container-fluid:before, .container:after, - .container:before, .dl-horizontal dd:after, .dl-horizontal dd:before, - .form-horizontal .form-group:after, .form-horizontal .form-group:before, - .modal-footer:after, .modal-footer:before, .nav:after, .nav:before, - .navbar-collapse:after, .navbar-collapse:before, .navbar-header:after, - .navbar-header:before, .navbar:after, .navbar:before, .pager:after, - .pager:before, .panel-body:after, .panel-body:before, .row:after, .row:before - { - display: table; - content: " " -} - -.btn-group-vertical>.btn-group:after, .btn-toolbar:after, .clearfix:after, - .container-fluid:after, .container:after, .dl-horizontal dd:after, - .form-horizontal .form-group:after, .modal-footer:after, .nav:after, - .navbar-collapse:after, .navbar-header:after, .navbar:after, .pager:after, - .panel-body:after, .row:after { - clear: both -} - -.center-block { - display: block; - margin-right: auto; - margin-left: auto -} - -.pull-right { - float: right !important -} - -.pull-left { - float: left !important -} - -.hide { - display: none !important -} - -.show { - display: block !important -} - -.invisible { - visibility: hidden -} - -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0 -} - -.hidden { - display: none !important -} - -.affix { - position: fixed -} - -@ --ms-viewport { - width: device-width -} - -.visible-lg, .visible-md, .visible-sm, .visible-xs { - display: none !important -} - -.visible-lg-block, .visible-lg-inline, .visible-lg-inline-block, - .visible-md-block, .visible-md-inline, .visible-md-inline-block, - .visible-sm-block, .visible-sm-inline, .visible-sm-inline-block, - .visible-xs-block, .visible-xs-inline, .visible-xs-inline-block { - display: none !important -} - -@media ( max-width :767px) { - .visible-xs { - display: block !important - } - table.visible-xs { - display: table - } - tr.visible-xs { - display: table-row !important - } - td.visible-xs, th.visible-xs { - display: table-cell !important - } -} - -@media ( max-width :767px) { - .visible-xs-block { - display: block !important - } -} - -@media ( max-width :767px) { - .visible-xs-inline { - display: inline !important - } -} - -@media ( max-width :767px) { - .visible-xs-inline-block { - display: inline-block !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm { - display: block !important - } - table.visible-sm { - display: table - } - tr.visible-sm { - display: table-row !important - } - td.visible-sm, th.visible-sm { - display: table-cell !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-block { - display: block !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-inline { - display: inline !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .visible-sm-inline-block { - display: inline-block !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md { - display: block !important - } - table.visible-md { - display: table - } - tr.visible-md { - display: table-row !important - } - td.visible-md, th.visible-md { - display: table-cell !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-block { - display: block !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-inline { - display: inline !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .visible-md-inline-block { - display: inline-block !important - } -} - -@media ( min-width :1200px) { - .visible-lg { - display: block !important - } - table.visible-lg { - display: table - } - tr.visible-lg { - display: table-row !important - } - td.visible-lg, th.visible-lg { - display: table-cell !important - } -} - -@media ( min-width :1200px) { - .visible-lg-block { - display: block !important - } -} - -@media ( min-width :1200px) { - .visible-lg-inline { - display: inline !important - } -} - -@media ( min-width :1200px) { - .visible-lg-inline-block { - display: inline-block !important - } -} - -@media ( max-width :767px) { - .hidden-xs { - display: none !important - } -} - -@media ( min-width :768px)and (max-width:991px) { - .hidden-sm { - display: none !important - } -} - -@media ( min-width :992px)and (max-width:1199px) { - .hidden-md { - display: none !important - } -} - -@media ( min-width :1200px) { - .hidden-lg { - display: none !important - } -} - -.visible-print { - display: none !important -} - -@media print { - .visible-print { - display: block !important - } - table.visible-print { - display: table - } - tr.visible-print { - display: table-row !important - } - td.visible-print, th.visible-print { - display: table-cell !important - } -} - -.visible-print-block { - display: none !important -} - -@media print { - .visible-print-block { - display: block !important - } -} - -.visible-print-inline { - display: none !important -} - -@media print { - .visible-print-inline { - display: inline !important - } -} - -.visible-print-inline-block { - display: none !important -} - -@media print { - .visible-print-inline-block { - display: inline-block !important - } -} - -@media print { - .hidden-print { - display: none !important - } -} \ No newline at end of file diff --git a/file-server/embedding-gziped-files-into-app/assets/js/jquery-2.1.1.js b/file-server/embedding-gziped-files-into-app/assets/js/jquery-2.1.1.js deleted file mode 100644 index 9f7b3d38..00000000 --- a/file-server/embedding-gziped-files-into-app/assets/js/jquery-2.1.1.js +++ /dev/null @@ -1,9190 +0,0 @@ -/*! - * jQuery JavaScript Library v2.1.1 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-05-01T17:11Z - */ - -(function( global, factory ) { - - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Can't do this because several apps including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// Support: Firefox 18+ -// - -var arr = []; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var support = {}; - - - -var - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - version = "2.1.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android<4.1 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; - }, - - isPlainObject: function( obj ) { - // Not plain objects: - // - Any object or value whose internal [[Class]] property is not "[object Object]" - // - DOM nodes - // - window - if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.constructor && - !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { - return false; - } - - // If the function hasn't returned already, we're confident that - // |obj| is a plain object, created by {} or constructed with new Object - return true; - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - // Support: Android < 4.0, iOS < 6 (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call(obj) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - var script, - indirect = eval; - - code = jQuery.trim( code ); - - if ( code ) { - // If the code includes a valid, prologue position - // strict mode pragma, execute code by injecting a - // script tag into the document. - if ( code.indexOf("use strict") === 1 ) { - script = document.createElement("script"); - script.text = code; - document.head.appendChild( script ).parentNode.removeChild( script ); - } else { - // Otherwise, avoid the DOM node creation, insertion - // and removal by using an indirect global eval - indirect( code ); - } - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); - - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -function isArraylike( obj ) { - var length = obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.nodeType === 1 && length ) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v1.10.19 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-04-18 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }; - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - - context = context || document; - results = results || []; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; - } - - if ( documentIsHTML && !seed ) { - - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== strundefined && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent !== parent.top ) { - // IE11 does not have attachEvent, so all must suffer - if ( parent.addEventListener ) { - parent.addEventListener( "unload", function() { - setDocument(); - }, false ); - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", function() { - setDocument(); - }); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowclip^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome<14 -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = "<a href='#'></a>"; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = "<input/>"; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - - -var rneedsContext = jQuery.expr.match.needsContext; - -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - -var risSimple = /^.[^:#\[\.,]*$/; - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); -}; - -jQuery.fn.extend({ - find: function( selector ) { - var i, - len = this.length, - ret = [], - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -}); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.extend({ - dir: function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }, - - sibling: function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - } -}); - -jQuery.fn.extend({ - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter(function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.unique( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return elem.contentDocument || jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.unique( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -}); -var rnotwhite = (/\S+/g); - - - -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); - - -// The deferred used on DOM ready -var readyList; - -jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; -}; - -jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } -}); - -/** - * The ready event handler and self cleanup method - */ -function completed() { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - jQuery.ready(); -} - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); - - } else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); - } - } - return readyList.promise( obj ); -}; - -// Kick off the DOM ready check even if the user does not -jQuery.ready.promise(); - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - len ? fn( elems[0], key ) : emptyGet; -}; - - -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( owner ) { - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - /* jshint -W018 */ - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - -function Data() { - // Support: Android < 4, - // Old WebKit does not have Object.preventExtensions/freeze method, - // return new empty object instead with no [[set]] accessor - Object.defineProperty( this.cache = {}, 0, { - get: function() { - return {}; - } - }); - - this.expando = jQuery.expando + Math.random(); -} - -Data.uid = 1; -Data.accepts = jQuery.acceptData; - -Data.prototype = { - key: function( owner ) { - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return the key for a frozen object. - if ( !Data.accepts( owner ) ) { - return 0; - } - - var descriptor = {}, - // Check if the owner object already has a cache key - unlock = owner[ this.expando ]; - - // If not, create one - if ( !unlock ) { - unlock = Data.uid++; - - // Secure it in a non-enumerable, non-writable property - try { - descriptor[ this.expando ] = { value: unlock }; - Object.defineProperties( owner, descriptor ); - - // Support: Android < 4 - // Fallback to a less secure definition - } catch ( e ) { - descriptor[ this.expando ] = unlock; - jQuery.extend( owner, descriptor ); - } - } - - // Ensure the cache object - if ( !this.cache[ unlock ] ) { - this.cache[ unlock ] = {}; - } - - return unlock; - }, - set: function( owner, data, value ) { - var prop, - // There may be an unlock assigned to this node, - // if there is no entry for this "owner", create one inline - // and set the unlock as though an owner entry had always existed - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - // Handle: [ owner, key, value ] args - if ( typeof data === "string" ) { - cache[ data ] = value; - - // Handle: [ owner, { properties } ] args - } else { - // Fresh assignments by object are shallow copied - if ( jQuery.isEmptyObject( cache ) ) { - jQuery.extend( this.cache[ unlock ], data ); - // Otherwise, copy the properties one-by-one to the cache object - } else { - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } - } - } - return cache; - }, - get: function( owner, key ) { - // Either a valid cache is found, or will be created. - // New caches will be created and the unlock returned, - // allowing direct access to the newly created - // empty data object. A valid owner object must be provided. - var cache = this.cache[ this.key( owner ) ]; - - return key === undefined ? - cache : cache[ key ]; - }, - access: function( owner, key, value ) { - var stored; - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ((key && typeof key === "string") && value === undefined) ) { - - stored = this.get( owner, key ); - - return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase(key) ); - } - - // [*]When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, name, camel, - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - if ( key === undefined ) { - this.cache[ unlock ] = {}; - - } else { - // Support array or space separated string of keys - if ( jQuery.isArray( key ) ) { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = key.concat( key.map( jQuery.camelCase ) ); - } else { - camel = jQuery.camelCase( key ); - // Try the string as a key before any manipulation - if ( key in cache ) { - name = [ key, camel ]; - } else { - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - name = camel; - name = name in cache ? - [ name ] : ( name.match( rnotwhite ) || [] ); - } - } - - i = name.length; - while ( i-- ) { - delete cache[ name[ i ] ]; - } - } - }, - hasData: function( owner ) { - return !jQuery.isEmptyObject( - this.cache[ owner[ this.expando ] ] || {} - ); - }, - discard: function( owner ) { - if ( owner[ this.expando ] ) { - delete this.cache[ owner[ this.expando ] ]; - } - } -}; -var data_priv = new Data(); - -var data_user = new Data(); - - - -/* - Implementation Summary - - 1. Enforce API surface and semantic compatibility with 1.9.x branch - 2. Improve the module's maintainability by reducing the storage - paths to a single mechanism. - 3. Use the same single mechanism to support "private" and "user" data. - 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) - 5. Avoid exposing implementation details on user objects (eg. expando properties) - 6. Provide a clear path for implementation upgrade to WeakMap in 2014 -*/ -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - data_user.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend({ - hasData: function( elem ) { - return data_user.hasData( elem ) || data_priv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return data_user.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - data_user.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to data_priv methods, these can be deprecated. - _data: function( elem, name, data ) { - return data_priv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - data_priv.remove( elem, name ); - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = data_user.get( elem ); - - if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - data_priv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - data_user.set( this, key ); - }); - } - - return access( this, function( value ) { - var data, - camelKey = jQuery.camelCase( key ); - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - // Attempt to get data from the cache - // with the key as-is - data = data_user.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to get data from the cache - // with the key camelized - data = data_user.get( elem, camelKey ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, camelKey, undefined ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each(function() { - // First, attempt to store a copy or reference of any - // data that might've been store with a camelCased key. - var data = data_user.get( this, camelKey ); - - // For HTML5 data-* attribute interop, we have to - // store property names with dashes in a camelCase form. - // This might not apply to all properties...* - data_user.set( this, camelKey, value ); - - // *... In the case of properties that might _actually_ - // have dashes, we need to also store a copy of that - // unchanged property. - if ( key.indexOf("-") !== -1 && data !== undefined ) { - data_user.set( this, key, value ); - } - }); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each(function() { - data_user.remove( this, key ); - }); - } -}); - - -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = data_priv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = data_priv.access( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return data_priv.get( elem, key ) || data_priv.access( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - data_priv.remove( elem, [ type + "queue", key ] ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = data_priv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); - }; - -var rcheckableType = (/^(?:checkbox|radio)$/i); - - - -(function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // #11217 - WebKit loses check when the name is after the checked attribute - // Support: Windows Web Apps (WWA) - // `name` and `type` need .setAttribute for WWA - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE9-IE11+ - div.innerHTML = "<textarea>x</textarea>"; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -})(); -var strundefined = typeof undefined; - - - -support.focusinBubbles = "onfocusin" in window; - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.hasData( elem ) && data_priv.get( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - data_priv.remove( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG <use> instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } - - return handlerQueue; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: Cordova 2.5 (WebKit) (#13255) - // All events should have a target; Cordova deviceready doesn't - if ( !event.target ) { - event.target = document; - } - - // Support: Safari 6.0+, Chrome < 28 - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } -}; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && e.preventDefault ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && e.stopPropagation ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -// Support: Chrome 15+ -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// Create "bubbling" focus and blur events -// Support: Firefox, Chrome, Safari -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - data_priv.remove( doc, fix ); - - } else { - data_priv.access( doc, fix, attaches ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -}); - - -var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /^$|\/(?:java|ecma)script/i, - rscriptTypeMasked = /^true\/(.*)/, - rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - - // Support: IE 9 - option: [ 1, "<select multiple='multiple'>", "</select>" ], - - thead: [ 1, "<table>", "</table>" ], - col: [ 2, "<table><colgroup>", "</colgroup></table>" ], - tr: [ 2, "<table><tbody>", "</tbody></table>" ], - td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], - - _default: [ 0, "", "" ] - }; - -// Support: IE 9 -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: 1.x compatibility -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute("type"); - } - - return elem; -} - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - data_priv.set( - elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) - ); - } -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( data_priv.hasData( src ) ) { - pdataOld = data_priv.access( src ); - pdataCur = data_priv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( data_user.hasData( src ) ) { - udataOld = data_user.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - data_user.set( dest, udataCur ); - } -} - -function getAll( context, tag ) { - var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : - context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; -} - -// Support: IE >= 9 -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Support: IE >= 9 - // Fix Cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - buildFragment: function( elems, context, scripts, selection ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Fixes #12346 - // Support: Webkit, IE - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - }, - - cleanData: function( elems ) { - var data, elem, type, key, - special = jQuery.event.special, - i = 0; - - for ( ; (elem = elems[ i ]) !== undefined; i++ ) { - if ( jQuery.acceptData( elem ) ) { - key = elem[ data_priv.expando ]; - - if ( key && (data = data_priv.cache[ key ]) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - if ( data_priv.cache[ key ] ) { - // Discard any remaining `private` data - delete data_priv.cache[ key ]; - } - } - } - // Discard any remaining `user` data - delete data_user.cache[ elem[ data_user.expando ] ]; - } - } -}); - -jQuery.fn.extend({ - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each(function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - }); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1></$2>" ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var arg = arguments[ 0 ]; - - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; - - jQuery.cleanData( getAll( this ) ); - - if ( arg ) { - arg.replaceChild( elem, this ); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - self.domManip( args, callback ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } - } - } - } - - return this; - } -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: QtWebKit - // .get() because push.apply(_, arraylike) throws - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - - -var iframe, - elemdisplay = {}; - -/** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ -// Called only from within defaultDisplay -function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? - - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; -} - -/** - * Try to determine the default display value of an element - * @param {String} nodeName - */ -function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); - - // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse - doc = iframe[ 0 ].contentDocument; - - // Support: IE - doc.write(); - doc.close(); - - display = actualDisplay( nodeName, doc ); - iframe.detach(); - } - - // Store the correct default display - elemdisplay[ nodeName ] = display; - } - - return display; -} -var rmargin = (/^margin/); - -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); - }; - - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - style = elem.style; - - computed = computed || getStyles( elem ); - - // Support: IE9 - // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - } - - if ( computed ) { - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // Support: iOS < 6 - // A tribute to the "awesome hack by Dean Edwards" - // iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - // Support: IE - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - // Hook not needed (or it's not possible to use it due to missing dependency), - // remove it. - // Since there are no other hooks for marginRight, remove the whole object. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - - return (this.get = hookFn).apply( this, arguments ); - } - }; -} - - -(function() { - var pixelPositionVal, boxSizingReliableVal, - docElem = document.documentElement, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - if ( !div.style ) { - return; - } - - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" + - "position:absolute"; - container.appendChild( div ); - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computePixelPositionAndBoxSizingReliable() { - div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + - "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + - "border:1px;padding:1px;width:4px;position:absolute"; - div.innerHTML = ""; - docElem.appendChild( container ); - - var divStyle = window.getComputedStyle( div, null ); - pixelPositionVal = divStyle.top !== "1%"; - boxSizingReliableVal = divStyle.width === "4px"; - - docElem.removeChild( container ); - } - - // Support: node.js jsdom - // Don't assume that getComputedStyle is a property of the global object - if ( window.getComputedStyle ) { - jQuery.extend( support, { - pixelPosition: function() { - // This test is executed only once but we still do memoizing - // since we can use the boxSizingReliable pre-computing. - // No need to check if the test was already performed, though. - computePixelPositionAndBoxSizingReliable(); - return pixelPositionVal; - }, - boxSizingReliable: function() { - if ( boxSizingReliableVal == null ) { - computePixelPositionAndBoxSizingReliable(); - } - return boxSizingReliableVal; - }, - reliableMarginRight: function() { - // Support: Android 2.3 - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. (#3333) - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // This support function is only executed once so no memoizing is needed. - var ret, - marginDiv = div.appendChild( document.createElement( "div" ) ); - - // Reset CSS: box-sizing; display; margin; border; padding - marginDiv.style.cssText = div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - docElem.appendChild( container ); - - ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight ); - - docElem.removeChild( container ); - - return ret; - } - }); - } -})(); - - -// A method for quickly swapping in/out CSS properties to get correct calculations. -jQuery.swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), - rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name[0].toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); - } - - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } else { - // at this point, extra isn't content, so add padding - val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var valueIsBorderBox = true, - val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name, styles ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && - ( support.boxSizingReliable() || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles - ) - ) + "px"; -} - -function showHide( elements, show ) { - var display, elem, hidden, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - values[ index ] = data_priv.get( elem, "olddisplay" ); - display = elem.style.display; - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) ); - } - } else { - hidden = isHidden( elem ); - - if ( display !== "none" || !hidden ) { - data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": "cssFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set. See: #7116 - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, - // but it would mean to define eight (for every problematic property) identical functions - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - style[ name ] = value; - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - } -}); - -jQuery.each([ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? - jQuery.swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - }) : - getWidthOrHeight( elem, name, extra ); - } - }, - - set: function( elem, value, extra ) { - var styles = extra && getStyles( elem ); - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - styles - ) : 0 - ); - } - }; -}); - -// Support: Android 2.3 -jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, - function( elem, computed ) { - if ( computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, - curCSS, [ elem, "marginRight" ] ); - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each({ - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -}); - -jQuery.fn.extend({ - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( jQuery.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each(function() { - if ( isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - if ( tween.elem[ tween.prop ] != null && - (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { - return tween.elem[ tween.prop ]; - } - - // passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE9 -// Panic based approach to setting things on disconnected nodes - -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - } -}; - -jQuery.fx = Tween.prototype.init; - -// Back Compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), - rrun = /queueHooks$/, - animationPrefilters = [ defaultPrefilter ], - tweeners = { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ), - target = tween.cur(), - parts = rfxnum.exec( value ), - unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && - rfxnum.exec( jQuery.css( tween.elem, prop ) ), - scale = 1, - maxIterations = 20; - - if ( start && start[ 3 ] !== unit ) { - // Trust units reported by jQuery.css - unit = unit || start[ 3 ]; - - // Make sure we update the tween properties later on - parts = parts || []; - - // Iteratively approximate from a nonzero starting point - start = +target || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } - - // Update tween properties - if ( parts ) { - start = tween.start = +start || +target || 0; - tween.unit = unit; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[ 1 ] ? - start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : - +parts[ 2 ]; - } - - return tween; - } ] - }; - -// Animations created synchronously will run synchronously -function createFxNow() { - setTimeout(function() { - fxNow = undefined; - }); - return ( fxNow = jQuery.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4 ; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( (tween = collection[ index ].call( animation, prop, value )) ) { - - // we're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - /* jshint validthis: true */ - var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHidden( elem ), - dataShow = data_priv.get( elem, "fxshow" ); - - // handle queue: false promises - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function() { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE9-10 do not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - display = jQuery.css( elem, "display" ); - - // Test default display if display is currently "none" - checkDisplay = display === "none" ? - data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; - - if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { - style.display = "inline-block"; - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always(function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - }); - } - - // show/hide pass - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.exec( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - - // Any non-fx value stops us from restoring the original display value - } else { - display = undefined; - } - } - - if ( !jQuery.isEmptyObject( orig ) ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = data_priv.access( elem, "fxshow", {} ); - } - - // store state if its toggle - enables .stop().toggle() to "reverse" - if ( toggle ) { - dataShow.hidden = !hidden; - } - if ( hidden ) { - jQuery( elem ).show(); - } else { - anim.done(function() { - jQuery( elem ).hide(); - }); - } - anim.done(function() { - var prop; - - data_priv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( prop in orig ) { - tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - - // If this is a noop like .hide().hide(), restore an overwritten display value - } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { - style.display = display; - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( jQuery.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always( function() { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ]); - - if ( percent < 1 && length ) { - return remaining; - } else { - deferred.resolveWith( elem, [ animation ] ); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { specialEasing: {} }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // resolve when we played the last frame - // otherwise, reject - if ( gotoEnd ) { - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - }), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length ; index++ ) { - result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( jQuery.isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - }) - ); - - // attach callbacks from options - return animation.progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweener: function( props, callback ) { - if ( jQuery.isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length ; index++ ) { - prop = props[ index ]; - tweeners[ prop ] = tweeners[ prop ] || []; - tweeners[ prop ].unshift( callback ); - } - }, - - prefilter: function( callback, prepend ) { - if ( prepend ) { - animationPrefilters.unshift( callback ); - } else { - animationPrefilters.push( callback ); - } - } -}); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - jQuery.isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( jQuery.isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend({ - fadeTo: function( speed, to, easing, callback ) { - - // show any hidden elements after setting opacity to 0 - return this.filter( isHidden ).css( "opacity", 0 ).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || data_priv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each(function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = data_priv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - }); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each(function() { - var index, - data = data_priv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // enable finishing flag on private data - data.finish = true; - - // empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // turn off finishing flag - delete data.finish; - }); - } -}); - -jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -}); - -// Generate shortcuts for custom animations -jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -}); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = jQuery.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - // Checks the timer has not already been removed - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - if ( timer() ) { - jQuery.fx.start(); - } else { - jQuery.timers.pop(); - } -}; - -jQuery.fx.interval = 13; - -jQuery.fx.start = function() { - if ( !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } -}; - -jQuery.fx.stop = function() { - clearInterval( timerId ); - timerId = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); -}; - - -(function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: iOS 5.1, Android 4.x, Android 2.3 - // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) - support.checkOn = input.value !== ""; - - // Must access the parent to make an option select properly - // Support: IE9, IE10 - support.optSelected = opt.selected; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Check if an input maintains its value after becoming a radio - // Support: IE9, IE10 - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -})(); - - -var nodeHook, boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend({ - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - } -}); - -jQuery.extend({ - attr: function( elem, name, value ) { - var hooks, ret, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === strundefined ) { - return jQuery.prop( elem, name, value ); - } - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - - } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var name, propName, - i = 0, - attrNames = value && value.match( rnotwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { - propName = jQuery.propFix[ name ] || name; - - // Boolean attributes get special treatment (#10870) - if ( jQuery.expr.match.bool.test( name ) ) { - // Set corresponding property to false - elem[ propName ] = false; - } - - elem.removeAttribute( name ); - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - jQuery.nodeName( elem, "input" ) ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - } -}); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle; - if ( !isXML ) { - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ name ]; - attrHandle[ name ] = ret; - ret = getter( elem, name, isXML ) != null ? - name.toLowerCase() : - null; - attrHandle[ name ] = handle; - } - return ret; - }; -}); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i; - -jQuery.fn.extend({ - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each(function() { - delete this[ jQuery.propFix[ name ] || name ]; - }); - } -}); - -jQuery.extend({ - propFix: { - "for": "htmlFor", - "class": "className" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? - ret : - ( elem[ name ] = value ); - - } else { - return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? - ret : - elem[ name ]; - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? - elem.tabIndex : - -1; - } - } - } -}); - -// Support: IE9+ -// Selectedness for an option in an optgroup can be inaccurate -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - } - }; -} - -jQuery.each([ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -}); - - - - -var rclass = /[\t\r\n\f]/g; - -jQuery.fn.extend({ - addClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call( this, j, this.className ) ); - }); - } - - if ( proceed ) { - // The disjunction here is for better compressibility (see removeClass) - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - " " - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = jQuery.trim( cur ); - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, clazz, j, finalValue, - proceed = arguments.length === 0 || typeof value === "string" && value, - i = 0, - len = this.length; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call( this, j, this.className ) ); - }); - } - if ( proceed ) { - classes = ( value || "" ).match( rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - "" - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = value ? jQuery.trim( cur ) : ""; - if ( elem.className !== finalValue ) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value; - - if ( typeof stateVal === "boolean" && type === "string" ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - classNames = value.match( rnotwhite ) || []; - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( type === strundefined || type === "boolean" ) { - if ( this.className ) { - // store className if set - data_priv.set( this, "__className__", this.className ); - } - - // If the element has a class name or if we're passed "false", - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - } -}); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend({ - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - // Support: IE10-11+ - // option.text throws exceptions (#14686, #14858) - jQuery.trim( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one" || index < 0, - values = one ? null : [], - max = one ? index + 1 : options.length, - i = index < 0 ? - max : - one ? index : 0; - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // IE6-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - // Don't return options that are disabled or in a disabled optgroup - ( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && - ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) { - optionSet = true; - } - } - - // force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -}); - -// Radios and checkboxes getter/setter -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - // Support: Webkit - // "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - }; - } -}); - - - - -// Return jQuery for attributes-only inclusion - - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; -}); - -jQuery.fn.extend({ - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - } -}); - - -var nonce = jQuery.now(); - -var rquery = (/\?/); - - - -// Support: Android 2.3 -// Workaround failure to string-cast null input -jQuery.parseJSON = function( data ) { - return JSON.parse( data + "" ); -}; - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE9 - try { - tmp = new DOMParser(); - xml = tmp.parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rts = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat("*"); - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set -try { - ajaxLocation = location.href; -} catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; -} - -// Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - while ( (dataType = dataTypes[i++]) ) { - // Prepend if requested - if ( dataType[0] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); - - // Otherwise append - } else { - (structure[ dataType ] = structure[ dataType ] || []).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - }); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s[ "throws" ] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend({ - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: ajaxLocation, - type: "GET", - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - // URL without anti-cache param - cacheURL, - // Response headers - responseHeadersString, - responseHeaders, - // timeout handle - timeoutTimer, - // Cross-domain detection vars - parts, - // To know if global events are to be dispatched - fireGlobals, - // Loop variable - i, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks("once memory"), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( (match = rheaders.exec( responseHeadersString )) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - var lname = name.toLowerCase(); - if ( !state ) { - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( state < 2 ) { - for ( code in map ) { - // Lazy-add the new callback in a way that preserves old ones - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } else { - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ).complete = completeDeferred.add; - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) - .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ); - s.crossDomain = !!( parts && - ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || - ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== - ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) - ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger("ajaxStart"); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - cacheURL = s.url; - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add anti-cache in url if needed - if ( s.cache === false ) { - s.url = rts.test( cacheURL ) ? - - // If there is already a '_' parameter, set its value - cacheURL.replace( rts, "$1_=" + nonce++ ) : - - // Otherwise add one to the end - cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; - } - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout(function() { - jqXHR.abort("timeout"); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch ( e ) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader("etag"); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger("ajaxStop"); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - url: url, - type: method, - dataType: type, - data: data, - success: callback - }); - }; -}); - -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -}); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax({ - url: url, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); -}; - - -jQuery.fn.extend({ - wrapAll: function( html ) { - var wrap; - - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapAll( html.call(this, i) ); - }); - } - - if ( this[ 0 ] ) { - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function( i ) { - jQuery( this ).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function( i ) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - } -}); - - -jQuery.expr.filters.hidden = function( elem ) { - // Support: Opera <= 12.12 - // Opera reports offsetWidths and offsetHeights less than zero on some elements - return elem.offsetWidth <= 0 && elem.offsetHeight <= 0; -}; -jQuery.expr.filters.visible = function( elem ) { - return !jQuery.expr.filters.hidden( elem ); -}; - - - - -var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( jQuery.isArray( obj ) ) { - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - // Item is non-scalar (array or object), encode its numeric index. - buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); - } - }); - - } else if ( !traditional && jQuery.type( obj ) === "object" ) { - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, value ) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); - s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if ( traditional === undefined ) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ).replace( r20, "+" ); -}; - -jQuery.fn.extend({ - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map(function() { - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - }) - .filter(function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - }) - .map(function( i, elem ) { - var val = jQuery( this ).val(); - - return val == null ? - null : - jQuery.isArray( val ) ? - jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }) : - { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }).get(); - } -}); - - -jQuery.ajaxSettings.xhr = function() { - try { - return new XMLHttpRequest(); - } catch( e ) {} -}; - -var xhrId = 0, - xhrCallbacks = {}, - xhrSuccessStatus = { - // file protocol always yields status code 0, assume 200 - 0: 200, - // Support: IE9 - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -// Support: IE9 -// Open requests must be manually aborted on unload (#5280) -if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ](); - } - }); -} - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport(function( options ) { - var callback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(), - id = ++xhrId; - - xhr.open( options.type, options.url, options.async, options.username, options.password ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers["X-Requested-With"] ) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - delete xhrCallbacks[ id ]; - callback = xhr.onload = xhr.onerror = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - complete( - // file: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - // Support: IE9 - // Accessing binary-data responseText throws an exception - // (#11426) - typeof xhr.responseText === "string" ? { - text: xhr.responseText - } : undefined, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - xhr.onerror = callback("error"); - - // Create the abort callback - callback = xhrCallbacks[ id ] = callback("abort"); - - try { - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -// Install script dataType -jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /(?:java|ecma)script/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -}); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -}); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery("<script>").prop({ - async: true, - charset: s.scriptCharset, - src: s.url - }).on( - "load error", - callback = function( evt ) { - script.remove(); - callback = null; - if ( evt ) { - complete( evt.type === "error" ? 404 : 200, evt.type ); - } - } - ); - document.head.appendChild( script[ 0 ] ); - }, - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -}); - - - - -var oldCallbacks = [], - rjsonp = /(=)\?(?=&|$)|\?\?/; - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? - "url" : - typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if ( jsonProp ) { - s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); - } else if ( s.jsonp !== false ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - overwritten = window[ callbackName ]; - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); - - - - -// data: string of html -// context (optional): If specified, the fragment will be created in this context, defaults to document -// keepScripts (optional): If true, will include scripts passed in the html string -jQuery.parseHTML = function( data, context, keepScripts ) { - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec( data ), - scripts = !keepScripts && []; - - // Single tag - if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ); - - if ( scripts && scripts.length ) { - jQuery( scripts ).remove(); - } - - return jQuery.merge( [], parsed.childNodes ); -}; - - -// Keep a copy of the old load method -var _load = jQuery.fn.load; - -/** - * Load a url into a page - */ -jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - var selector, type, response, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = jQuery.trim( url.slice( off ) ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // If we have elements to modify, make the request - if ( self.length > 0 ) { - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - self.html( selector ? - - // If a selector was specified, locate the right elements in a dummy div - // Exclude scripts to avoid IE 'Permission Denied' errors - jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : - - // Otherwise use the full result - responseText ); - - }).complete( callback && function( jqXHR, status ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - }); - } - - return this; -}; - - - - -jQuery.expr.filters.animated = function( elem ) { - return jQuery.grep(jQuery.timers, function( fn ) { - return elem === fn.elem; - }).length; -}; - - - - -var docElem = window.document.documentElement; - -/** - * Gets a window from an element - */ -function getWindow( elem ) { - return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; -} - -jQuery.offset = { - setOffset: function( elem, options, i ) { - var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, - position = jQuery.css( elem, "position" ), - curElem = jQuery( elem ), - props = {}; - - // Set position first, in-case top/left are set even on static elem - if ( position === "static" ) { - elem.style.position = "relative"; - } - - curOffset = curElem.offset(); - curCSSTop = jQuery.css( elem, "top" ); - curCSSLeft = jQuery.css( elem, "left" ); - calculatePosition = ( position === "absolute" || position === "fixed" ) && - ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; - - // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if ( calculatePosition ) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - - } else { - curTop = parseFloat( curCSSTop ) || 0; - curLeft = parseFloat( curCSSLeft ) || 0; - } - - if ( jQuery.isFunction( options ) ) { - options = options.call( elem, i, curOffset ); - } - - if ( options.top != null ) { - props.top = ( options.top - curOffset.top ) + curTop; - } - if ( options.left != null ) { - props.left = ( options.left - curOffset.left ) + curLeft; - } - - if ( "using" in options ) { - options.using.call( elem, props ); - - } else { - curElem.css( props ); - } - } -}; - -jQuery.fn.extend({ - offset: function( options ) { - if ( arguments.length ) { - return options === undefined ? - this : - this.each(function( i ) { - jQuery.offset.setOffset( this, options, i ); - }); - } - - var docElem, win, - elem = this[ 0 ], - box = { top: 0, left: 0 }, - doc = elem && elem.ownerDocument; - - if ( !doc ) { - return; - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if ( !jQuery.contains( docElem, elem ) ) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== strundefined ) { - box = elem.getBoundingClientRect(); - } - win = getWindow( doc ); - return { - top: box.top + win.pageYOffset - docElem.clientTop, - left: box.left + win.pageXOffset - docElem.clientLeft - }; - }, - - position: function() { - if ( !this[ 0 ] ) { - return; - } - - var offsetParent, offset, - elem = this[ 0 ], - parentOffset = { top: 0, left: 0 }; - - // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent - if ( jQuery.css( elem, "position" ) === "fixed" ) { - // We assume that getBoundingClientRect is available when computed position is fixed - offset = elem.getBoundingClientRect(); - - } else { - // Get *real* offsetParent - offsetParent = this.offsetParent(); - - // Get correct offsets - offset = this.offset(); - if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { - parentOffset = offsetParent.offset(); - } - - // Add offsetParent borders - parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); - parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); - } - - // Subtract parent offsets and element margins - return { - top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), - left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) - }; - }, - - offsetParent: function() { - return this.map(function() { - var offsetParent = this.offsetParent || docElem; - - while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { - offsetParent = offsetParent.offsetParent; - } - - return offsetParent || docElem; - }); - } -}); - -// Create scrollLeft and scrollTop methods -jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { - var top = "pageYOffset" === prop; - - jQuery.fn[ method ] = function( val ) { - return access( this, function( elem, method, val ) { - var win = getWindow( elem ); - - if ( val === undefined ) { - return win ? win[ prop ] : elem[ method ]; - } - - if ( win ) { - win.scrollTo( - !top ? val : window.pageXOffset, - top ? val : window.pageYOffset - ); - - } else { - elem[ method ] = val; - } - }, method, val, arguments.length, null ); - }; -}); - -// Add the top/left cssHooks using jQuery.fn.position -// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 -// getComputedStyle returns percent when specified for top/left/bottom/right -// rather than make the css module depend on the offset module, we just check for it here -jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, - function( elem, computed ) { - if ( computed ) { - computed = curCSS( elem, prop ); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( computed ) ? - jQuery( elem ).position()[ prop ] + "px" : - computed; - } - } - ); -}); - - -// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods -jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { - // margin is only for outerHeight, outerWidth - jQuery.fn[ funcName ] = function( margin, value ) { - var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), - extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); - - return access( this, function( elem, type, value ) { - var doc; - - if ( jQuery.isWindow( elem ) ) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement[ "client" + name ]; - } - - // Get document width or height - if ( elem.nodeType === 9 ) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], - // whichever is greatest - return Math.max( - elem.body[ "scroll" + name ], doc[ "scroll" + name ], - elem.body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, extra ) : - - // Set width or height on the element - jQuery.style( elem, type, value, extra ); - }, type, chainable ? margin : undefined, chainable, null ); - }; - }); -}); - - -// The number of elements contained in the matched element set -jQuery.fn.size = function() { - return this.length; -}; - -jQuery.fn.andSelf = jQuery.fn.addBack; - - - - -// Register as a named AMD module, since jQuery can be concatenated with other -// files that may use define, but not via a proper concatenation script that -// understands anonymous AMD modules. A named AMD is safest and most robust -// way to register. Lowercase jquery is used because AMD module names are -// derived from file names, and jQuery is normally delivered in a lowercase -// file name. Do this after creating the global so that if an AMD module wants -// to call noConflict to hide this version of jQuery, it will work. - -// Note that for maximum portability, libraries that are not jQuery should -// declare themselves as anonymous modules, and avoid setting a global if an -// AMD loader is present. jQuery is a special case. For more information, see -// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon - -if ( typeof define === "function" && define.amd ) { - define( "jquery", [], function() { - return jQuery; - }); -} - - - - -var - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$; - -jQuery.noConflict = function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; -}; - -// Expose jQuery and $ identifiers, even in -// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) -// and CommonJS for browser emulators (#13566) -if ( typeof noGlobal === strundefined ) { - window.jQuery = window.$ = jQuery; -} - - - - -return jQuery; - -})); diff --git a/file-server/embedding-gziped-files-into-app/bindata_gzip.go b/file-server/embedding-gziped-files-into-app/bindata_gzip.go deleted file mode 100644 index 8c6619bd..00000000 --- a/file-server/embedding-gziped-files-into-app/bindata_gzip.go +++ /dev/null @@ -1,3774 +0,0 @@ -// Code generated by bindata. DO NOT EDIT. -// sources: -// assets\css\bootstrap.min.css -// assets\favicon.ico -// assets\js\jquery-2.1.1.js - -package main - - -import ( - "fmt" - "os" - "strings" - "time" -) - - -type gzipAsset struct { - bytes []byte - info gzipFileInfoEx -} - -type gzipFileInfoEx interface { - os.FileInfo - MD5Checksum() string -} - -type gzipBindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time - md5checksum string -} - -func (fi gzipBindataFileInfo) Name() string { - return fi.name -} -func (fi gzipBindataFileInfo) Size() int64 { - return fi.size -} -func (fi gzipBindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi gzipBindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi gzipBindataFileInfo) MD5Checksum() string { - return fi.md5checksum -} -func (fi gzipBindataFileInfo) IsDir() bool { - return false -} -func (fi gzipBindataFileInfo) Sys() interface{} { - return nil -} - -var _gzipBindataAssetscssbootstrapmincss = []byte( - "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\xef\x8f\xe3\x38\x92\x20\xfa\xb9\x1a\xe8\xff\x41\x5b\x8d\x41\x57" + - "\x4d\x59\x2e\xf9\x77\xda\x89\xce\xb7\xfb\xe6\x0e\xb7\x03\xdc\xec\x97\x9b\x0f\x07\xf4\xf4\x7b\xa0\x25\xda\xd6\x94" + - "\x2c\x69\x24\x39\x2b\xb3\xfb\xf6\xfe\xf6\x83\xf8\x4b\x41\x32\x48\xd1\x4e\x77\xcf\xdc\x62\xb7\xee\x7a\x9c\x62\x44" + - "\x30\x18\x0c\x06\x83\x41\x32\xf8\xf9\xf7\xff\xf4\xed\x37\xd1\xef\xa3\xff\xb7\xaa\xba\xb6\x6b\x48\x1d\x3d\x2f\xa6" + - "\x8b\xe9\x32\xfa\x70\xea\xba\x7a\xf7\xf9\xf3\x91\x76\x7b\x59\x36\x4d\xab\xf3\x47\x06\xfe\x87\xaa\x7e\x6d\xf2\xe3" + - "\xa9\x8b\xe6\xc9\x6c\x16\xcf\x93\xd9\x2a\xfa\xf3\xd7\xbc\xeb\x68\x33\x89\xfe\x58\xa6\x53\x06\xf5\xdf\xf3\x94\x96" + - "\x2d\xcd\xa2\x4b\x99\xd1\x26\xfa\xd3\x1f\xff\xcc\xc9\xb6\x3d\xdd\xbc\x3b\x5d\xf6\x3d\xc5\xcf\xdd\xd7\x7d\xfb\x59" + - "\x55\xf2\x79\x5f\x54\xfb\xcf\x67\xd2\x76\xb4\xf9\xfc\xdf\xff\xf8\x87\xff\xfa\x6f\xff\xe3\xbf\xb2\x4a\x3f\x47\x9f" + - "\x7f\xff\x4f\x51\x59\x35\x67\x52\xe4\x3f\xd3\x69\xda\xb6\x3d\xb3\xc9\x74\x1e\xfd\x2f\x46\x5b\x54\x17\xfd\xaf\xe8" + - "\x98\x77\xd3\xbc\xfa\xac\x60\xa3\xdf\x7f\xfe\xf6\x9b\x53\x77\x2e\xa2\x5f\xbe\xfd\xe6\xdd\xa1\x2a\xbb\xf8\x40\xce" + - "\x79\xf1\xba\x8b\x5a\x52\xb6\x71\x4b\x9b\xfc\xf0\xf8\xed\x37\xef\xe2\xaf\x74\xff\x25\xef\xe2\x8e\xbe\x74\x71\x9b" + - "\xff\x4c\x63\x92\xfd\xf5\xd2\x76\xbb\x68\x96\x24\xbf\x63\x10\xe7\xd6\x51\xfa\xed\x37\xff\xfe\xed\x37\xdf\x7e\xb3" + - "\xaf\xb2\x57\x56\xcd\x99\x34\xc7\xbc\xdc\x45\x89\x28\x20\x4d\x97\xa7\x05\x9d\x44\xa4\xcd\x33\x3a\x89\x32\xda\x91" + - "\xbc\x68\x27\xd1\x21\x3f\xa6\xa4\xee\xf2\xaa\x64\xbf\x2f\x0d\x9d\x44\x87\xaa\x62\xb2\x3c\x51\x92\xb1\xff\x3d\x36" + - "\xd5\xa5\x9e\x30\xb2\x79\x39\x89\xce\xb4\xbc\x4c\xa2\x92\x3c\x4f\xa2\x96\xa6\x1c\xb7\xbd\x9c\xcf\xa4\xe1\x95\x67" + - "\x79\x5b\x17\xe4\x75\x17\xed\x8b\x2a\xfd\x22\x39\xb8\x64\x79\x35\x89\x52\x52\x3e\x93\x76\x12\xd5\x4d\x75\x6c\x68" + - "\xdb\x4e\xa2\xe7\x3c\xa3\x95\x8e\x97\x97\x45\x5e\xd2\x98\xa1\xf7\xed\x7e\xa6\x3d\xfb\xa4\x88\x49\x91\x1f\xcb\x5d" + - "\xb4\x27\x2d\xed\x21\x20\xe9\x5d\x59\x75\xd1\x87\x1f\xd3\xaa\xec\x9a\xaa\x68\x7f\x8a\x3e\x6a\x24\xcb\xaa\xa4\x3d" + - "\xa9\x13\xed\x35\x67\x10\xcc\x8f\xa7\x3c\xcb\x68\xf9\xd3\x24\xea\xe8\xb9\x2e\x48\x47\x23\x0b\x4f\x56\xc3\x4a\xf6" + - "\x24\xfd\xd2\xcb\xa3\xcc\xe2\xb4\x2a\xaa\x66\x17\x75\x0d\x29\xdb\x9a\x34\xb4\xec\x24\xe4\x8e\xa4\x5d\xfe\xdc\x8b" + - "\x7b\x77\xaa\x9e\x69\xc3\x30\xab\x4b\xd7\x33\x0d\x3a\x65\xbf\x6f\x7e\xec\xf2\xae\xa0\x3f\x71\xd2\x55\x93\xd1\x26" + - "\xde\x57\x5d\x57\x9d\x77\xd1\xac\x7e\x89\xb2\xaa\xeb\x68\x26\x7b\x77\x12\xb5\x5d\x53\x95\xc7\x41\x93\xbe\x8a\xe6" + - "\x6c\x12\x49\x34\x3b\x94\x43\x71\xdb\xbd\x16\x74\x17\xe5\x1d\x29\xf2\x54\x00\x9c\x66\x9a\x86\x4c\xd7\x1b\x7a\x8e" + - "\x92\x47\x85\x92\xff\x4c\x77\xd1\x9c\x9e\x05\xf8\x99\x34\x5f\x18\x82\x68\xed\x77\x49\xc2\x80\x07\x39\xec\xa2\xef" + - "\x0e\x07\x59\x7d\x7b\x26\x05\xd0\x74\x4e\xed\x41\x29\x68\x7b\xe9\x1b\x71\xa9\x19\x44\x5d\xb5\x79\xaf\x3d\xbb\xa8" + - "\xa1\x05\xe9\x05\x66\x70\xb1\x59\x31\xb5\x67\xca\xa0\x3a\x2e\x40\x21\x64\x05\x5d\x55\xef\xa2\x78\xba\x52\x8d\x69" + - "\x2f\x7b\x21\x69\x2e\xe2\x78\x3a\x1f\x0a\xf3\xf3\x11\x74\xc3\xd0\x4d\xed\xf3\x91\x2b\xd7\xae\xa9\xaa\x8e\xeb\x55" + - "\xdf\xa9\x87\xa2\xfa\xba\x8b\xb8\xfe\x08\x50\x3e\x82\x34\xf9\xce\xe8\x39\x5a\x26\xf5\x8b\x94\x3e\xd7\x05\xad\x35" + - "\x72\xe0\xef\xab\x97\xbe\xe1\x79\x79\xdc\x45\xbd\x1e\xd3\x92\x7d\xe3\x23\xbf\xfa\xd9\x57\xee\x28\x12\x95\xd6\x82" + - "\xa7\x81\x6b\x72\xe9\x2a\x51\x98\x56\xbd\x41\xf8\xb2\xcf\xfa\x41\x49\x27\x51\x4b\xce\xb5\x6d\xaa\xce\x55\x59\xb5" + - "\x35\x49\xe9\x64\xf8\x69\xf4\xd6\x4c\x49\x72\x7f\xe9\xba\xde\x28\xe4\x65\x7d\xe9\x26\x51\x55\x77\xdc\x82\x44\x2d" + - "\x2d\x68\xda\xf5\x63\xed\xa5\x23\x0d\x25\xba\xad\x92\xf4\x7a\x03\x70\xa2\x4d\xde\x3d\x0e\x6a\x27\xbe\x68\x15\x18" + - "\x6d\x7a\xce\xdb\x7c\x5f\x50\x83\x07\x5e\x25\x57\x87\xde\x74\xb2\xd1\x7a\xa8\x9a\xb3\x36\xb6\x25\x34\xb3\xd3\x8c" + - "\xed\x1f\xbb\xd7\x9a\xfe\xc0\xbf\xff\x34\x81\xdf\x1a\xda\xd2\x4e\xff\xd4\x5e\xf6\xe7\xbc\xe3\xa3\x58\xf6\x26\xa9" + - "\x6b\x4a\x1a\x52\xa6\x74\x17\x71\x32\xac\x39\x97\xa6\xed\xdb\x53\x57\x79\xd9\xd1\x46\xab\xfe\xc7\x2c\x6f\xc9\xbe" + - "\xa0\xd9\x4f\x1a\x23\xea\x2b\x1f\x86\x82\x40\x46\x0f\xe4\x52\xe8\x02\xd9\xed\x98\x9e\x1c\xaa\xf4\xd2\xc6\x79\x59" + - "\xf6\xc6\x9b\xd1\xb0\x0b\xf8\x00\x24\x59\xc6\x54\x86\x8f\x68\x43\xef\x19\x26\x83\xd3\x06\x20\x9f\xd8\x20\x0c\x97" + - "\x41\x7a\xa2\xe9\x97\x7d\xf5\x62\x08\x8b\x64\x79\xa5\x0b\x06\xea\xaa\x32\x79\xb8\x96\xeb\xc5\xee\x92\xa1\x21\x36" + - "\x5f\xe5\xe5\xbc\xa7\xcd\x4f\xbb\x9d\xac\x9f\xb5\x3f\x6e\xeb\xbc\x8c\x35\x45\x75\x80\x57\x97\x4e\x07\xff\xf6\x9b" + - "\x77\x70\x08\x83\xa1\x04\x35\x82\x92\x26\x3d\xb9\x1b\x7e\x9f\xf1\xfd\xe8\xd0\xb7\x5e\xd3\x0f\x39\x2d\x32\x27\x63" + - "\x43\xfb\xf8\x87\x38\xed\x31\x0b\x4c\x22\x2e\x8c\x8c\xa6\x55\x43\x7a\x03\x2e\x24\x82\x71\x02\xc6\x18\x63\xa8\xa5" + - "\x9d\xae\x7a\xd3\xc5\x8a\x9e\xa3\xe9\x7a\xce\xfe\x67\xb3\xa2\xe7\x47\x68\x13\xa2\x79\xfd\x02\x95\xb3\x9f\x14\xdb" + - "\xaa\xc8\xb3\xa8\xcd\x8b\x67\x35\x80\x0a\x7a\xa4\x65\x16\xa0\xd4\x9a\xe5\x41\xed\xa1\xb4\x56\xbe\x49\xb6\xeb\x07" + - "\x24\x9c\xb3\x7b\x7b\x68\x56\xda\xfb\x07\x05\xa9\x5b\xda\x77\x19\xff\x25\xd1\xb3\x49\xd4\x9d\x0c\x6e\x59\xd9\xbb" + - "\xde\xcd\xfc\x1f\xd5\xa5\xe9\x65\x87\xb8\xab\xa7\xd5\xbe\xfe\xdc\xdb\x86\x55\xbc\xaf\xf2\x82\x36\xcc\x65\xd1\xdc" + - "\xd6\xb6\x49\x3f\xa7\x6d\xfb\xb9\xf7\xd5\x98\x9f\xda\xfb\x9f\xff\x7c\xa6\x59\x4e\xa2\xba\xc9\x4b\x2e\xff\xdf\x4f" + - "\xa2\x1d\x39\x30\x37\x6f\xb7\xa7\x87\x4a\xcc\x10\x70\x96\x8f\xfe\x29\x3f\xd7\x55\xd3\x91\x92\x19\x62\x6e\x3e\xdb" + - "\x13\xc9\x7a\x81\xf5\xfd\x6a\x02\x40\x97\x20\x89\x2c\x7c\x6d\x18\xf8\xc8\xb8\xcb\xbf\xfd\xe6\x5d\x2f\x24\xd2\x3b" + - "\x56\xbd\xb9\xef\x28\xef\x73\xce\xdb\xa0\x90\x3b\xee\xf5\x73\x97\x80\xa3\xfc\x78\x6a\xe8\xe1\x27\xde\x66\xd9\x54" + - "\x36\x8e\x76\xd1\xfb\xe8\xc3\xfb\x88\x74\x5d\xf3\xa1\x87\xf9\x18\xbd\xff\xf8\x5e\x62\x0d\x1e\xda\x08\x26\x03\xd2" + - "\x50\x59\x85\xff\xdf\x0f\xef\xff\x4a\x9e\x49\x9b\x36\x79\xdd\xed\xde\xff\x24\x65\xae\x4a\xbf\x7b\xef\xa0\x2c\xe9" + - "\x30\x27\xf8\x6f\x97\xaa\xa3\x6c\x7e\xe6\x60\xf6\x68\xf8\x6e\xbb\xdd\x32\xe9\xd5\xe4\x48\xe3\x7d\x43\xc9\x97\x38" + - "\x2f\x7b\x67\x7f\x17\x91\xe7\x2a\xcf\x04\xb9\xae\x77\xea\x39\x11\xe5\xe3\x32\x6d\x8e\xb9\xb7\x1f\x33\xdd\x17\xc0" + - "\xf9\xf9\x38\x89\x3a\xc1\xda\x08\x61\xe9\x3d\xbd\x3b\x93\x97\xf8\x6b\x9e\x75\x27\xbe\x32\xb1\x7b\xef\x34\x9f\x44" + - "\xa7\xc5\x24\xe2\x23\xec\x5d\xd5\xd4\x27\x52\xb6\xbb\x68\xc1\xf8\xff\x9a\x67\xd5\xd7\xfe\x2f\x0d\xda\x62\x81\xc9" + - "\x4c\xe7\x00\xcc\xf4\xa6\x77\x7a\xb0\xb9\x98\x96\xe4\x79\x4f\x1a\x43\x14\xdc\x5c\x71\x80\x7d\x57\x3e\x4d\x53\xd2" + - "\xd0\x6e\x12\x4d\xb3\xa6\xaa\x2f\xf5\x13\xf8\x08\x7b\x22\xee\xaa\x3a\xc6\x87\x8e\xa4\x56\x90\x3d\x2d\x9c\xbd\x97" + - "\xf4\xa6\x85\x03\x0e\xb6\xc5\x6d\x47\x10\xfa\x1c\xad\xb7\x2c\xf2\xe7\xc9\x14\x85\xe2\x10\x17\x08\x57\x03\x5e\x27" + - "\xcd\x00\x29\xf0\xed\xe4\x6c\x41\x96\x65\x16\x4d\x66\xec\xfe\x59\xf8\x91\x29\xb5\xbd\xca\xef\xff\x5b\xf1\x5a\x9f" + - "\xf2\xb4\x2a\xdb\xe8\x5f\x49\x71\x28\xf2\xf2\xd8\x7e\xdf\xeb\x41\xdb\xa4\xbb\xe8\xd2\x14\x1f\xa6\xd3\xcf\x3d\x4a" + - "\xfb\xf9\xa8\x40\xe3\x93\x04\x8d\x1b\x7a\xbc\x14\xa4\x99\xd2\xaa\xfb\x78\x1b\xda\xff\xf3\x5d\x4e\x0f\xf9\xcb\xc7" + - "\xbe\x59\xbd\x5b\x48\xba\x0f\xdf\xd3\xf3\x9e\x66\x19\xcd\xe2\xaa\xa6\x65\x3f\x07\x7e\xff\xb1\x5f\xfd\xbe\x0b\x27" + - "\xfc\xb5\x3a\x1c\xe6\x1f\x23\x49\x90\xfd\x79\x13\x11\x9d\xc6\xd5\x24\xba\x0e\x50\xe8\x9a\x0b\xbd\xa9\x35\xed\xf3" + - "\xf1\xbb\x01\xe0\xff\x57\x00\xa2\x5c\x93\x5d\xfb\x7c\xfc\xfe\xa3\xe8\xfa\xa9\x42\xf2\xac\xf7\xd8\x22\x6d\xc6\x67" + - "\x79\x67\x04\x20\x50\x6b\xe0\xa2\x97\xfb\xa9\x8f\xe6\x24\xbe\xe4\xcb\x57\xcd\xa5\x9d\x41\x3f\x8a\xd3\x38\x57\x55" + - "\x77\x62\x13\x33\x29\xbb\x9c\x14\x39\x69\x69\xa6\x3c\xb5\xaa\x7d\xb1\xe0\x8e\x0d\x79\x6d\x53\xa2\x16\x20\x43\xe3" + - "\x63\x36\x31\xe7\xed\x17\x38\xd3\x0e\x96\xfe\x2f\x73\xf2\xde\xc6\xa9\x8b\x4b\xeb\x82\xdf\x23\xf0\xf4\xd2\x08\xf0" + - "\x49\xa4\x7f\xae\x5c\x64\x12\x92\x22\x84\xce\x79\xe9\xae\x79\x3e\x9b\x23\x28\x69\x51\x5d\x32\x17\xca\x3a\x99\x61" + - "\xec\x96\xcf\xb4\xa8\x6a\xea\xc2\xda\x24\x5b\x4c\x28\xb4\x4c\xf3\xc2\x8d\x73\x40\x70\x8e\x05\x69\x5d\xed\xa1\x09" + - "\xca\xdc\xf9\xd2\xe6\xa9\x1b\x05\x13\x01\xf7\x89\xdd\x38\x0b\x04\xe7\x44\x49\xd3\xb9\x51\x56\x58\x35\x1d\x69\xdc" + - "\x18\x6b\x07\x46\x4c\xcf\x75\xf7\xea\xc6\xdb\x20\x78\x97\x96\x7a\x6a\x7a\x40\x30\x0e\x79\x71\x76\x63\x60\xdd\xd9" + - "\x9d\xe2\x82\x34\x47\x97\x12\xd0\x64\x96\xa0\x58\x6e\x78\xac\x37\xfb\x5a\xf2\xd6\x2d\x68\x54\xa5\x2b\xd7\x60\xa5" + - "\xc9\x0c\xeb\xcb\x86\x9e\xab\x67\x4f\x43\x96\x08\xce\xcf\x55\x75\x8e\xf3\xd2\x8d\x84\x69\x00\x43\xaa\x2e\x9e\xe6" + - "\x60\x5a\x50\x1d\x0e\x6e\x04\xac\xfb\xdb\xfc\x58\x12\xd7\x48\xa3\xc9\x0c\x53\x80\xb4\x3a\xba\x11\xd0\xfe\x6f\x48" + - "\xeb\xee\xcc\x39\xd6\xf9\xa7\xea\xec\x96\xf2\x1c\xeb\xfe\x43\x5e\x78\x30\xb0\xbe\xef\x72\x5f\x1d\x68\xef\x57\xc4" + - "\x65\xff\x68\x32\xc7\xfa\x3e\xab\xbe\x96\x45\x45\xb2\x98\x14\xee\xae\x9c\x63\x0a\x20\x31\xdd\x58\x98\x02\x5c\x6a" + - "\x3f\x0e\xa6\x03\x79\xb9\xaf\x5e\xdc\x28\x98\x0a\xf4\xb3\x77\x9c\xe6\x4d\xea\x93\x39\xa6\x0a\x0d\xad\x29\x71\x4b" + - "\x62\x81\xe9\x42\x43\x0f\x0d\xf5\x28\xd0\x02\x53\x87\xde\x14\x78\x85\xbe\xc0\x54\xa2\xf7\x43\xdc\x18\x98\x4a\x1c" + - "\x0a\xe2\x1e\x0d\x0b\x4c\x25\xfa\x05\x58\x7d\xaa\x4a\xea\x9e\xad\x16\x98\x42\x3c\x57\xc5\xe5\x4c\xbd\x43\x7c\x81" + - "\xa9\x84\xc0\xeb\xf5\xc9\x8d\x88\xe9\x85\x40\xbc\xd4\x6e\x34\x4c\x37\xfe\xd6\xa4\x55\xe6\x56\x8b\x05\xa6\x16\x7b" + - "\xe2\x47\x5a\xa2\x13\x84\x47\xf2\x4b\x74\x86\x20\x47\xb7\xcc\x97\x98\x3e\xec\x2b\xcf\x04\xb1\xc4\xf4\xa1\xc7\x38" + - "\x93\xc6\x83\x85\xe9\x04\x0b\xd8\xb8\x51\x30\x75\x48\xc9\x99\x36\xc4\x8d\x83\xa9\x02\x8b\xba\x3b\x31\x30\x1d\xd8" + - "\x57\x85\xdb\x9a\x2c\xb1\xee\xe7\x9b\x50\x6e\x1c\x74\x82\xa0\x2f\x9d\xf4\xd2\x5d\x88\x2b\x54\x05\x7a\x44\x1e\x85" + - "\x70\xe2\x61\x9a\xc0\xf6\x93\xe2\x82\x1e\x3c\xf5\x61\xfa\xc0\xf1\x52\x5a\x76\x1e\xaf\x69\x85\xe9\x05\xc7\x6c\xfc" + - "\x4d\xc4\x54\x83\x23\xfe\xf5\xd2\x76\xf9\xc1\xed\xdb\xad\x30\x15\xf1\xba\x43\x2b\x4c\x41\xf2\x32\xa3\x65\x37\x22" + - "\x18\x7c\x0e\x61\x88\x23\xed\x43\xdd\x49\x92\xd2\x7e\x26\x8e\xd9\x06\xb1\x1b\x17\x5d\x27\xe4\x69\x77\x69\xdc\x66" + - "\x63\x8d\xe9\xcc\x99\xd4\x71\x3f\x42\x3d\x3d\xb8\x46\xfb\x9e\xef\xc3\x3b\x71\xb0\x5e\xef\x7c\xc3\x7a\x8d\x75\x37" + - "\xcd\x72\x0f\x06\xba\x56\x38\x11\x9f\x08\xb0\x6e\x66\x7b\x38\x6e\x14\xac\x83\xbd\x6e\xef\x1a\xeb\xd8\xb6\xa3\x75" + - "\xbc\x27\xe9\x97\xaf\xa4\x71\xdb\x90\x35\xd6\xaf\x07\xd2\x76\xe3\xa8\x1b\xac\x77\xc7\xb1\x30\x7b\xc0\xa2\x11\x4e" + - "\x0c\x4c\x1b\x6a\x72\x69\xdd\x02\xd9\x60\xca\xd0\x76\x95\x7b\x2a\xdd\x60\xca\x70\xa8\x1a\x7f\x5b\x30\x7d\x60\xc2" + - "\x1b\xc5\xc4\xd7\x90\xb4\x1e\xc7\xc4\xb4\x83\xfe\x95\xa6\x6e\xb5\xdd\xa0\xab\x88\x13\x7d\x6e\xaa\x11\x23\xbc\xc1" + - "\xb4\x43\x62\xfa\x8d\xcd\x03\xa6\x1d\x75\x71\x69\xd9\x9a\xc7\x8d\x86\x06\x0a\xf2\x72\x14\x0f\x53\x12\xbe\x5a\x1c" + - "\x41\xc4\x54\xa5\xfa\x32\x82\x84\x69\xcb\xdf\x2e\xb4\xed\x72\xb1\xa8\x73\xa3\x62\x3a\x93\x97\x87\x6a\x04\x0d\x55" + - "\x98\xb4\xa1\xb4\x6c\x4f\x95\xa7\x1b\x30\x75\x11\x72\x19\x59\x40\x3c\x60\x6a\x53\x7d\x19\x45\xc3\x1d\xcc\x72\x0c" + - "\x6f\x8b\x29\x0c\x69\x9a\xea\xab\x5f\x47\xb7\xa8\x83\xc1\xf0\xfc\x1a\xba\x45\x67\x19\x86\xe8\xf1\xb9\xb7\xa8\x77" + - "\xc1\xb0\xbc\x2e\xfe\x16\x53\x19\x36\x77\x78\x97\x49\x5b\x4c\x5d\x1a\xca\x4e\xa6\x1d\x2e\x85\x3b\x74\xb0\xc5\x14" + - "\x46\x20\xb2\xd3\x43\x6e\x4c\xd4\xc2\xbc\xa4\x05\x39\x93\x51\xfd\x9e\xa1\x91\xbe\x63\xee\xee\xc0\x19\x1a\xe8\x2b" + - "\x28\x71\xae\xb3\x66\x68\x98\xef\x90\xbb\xa7\xe1\x59\x82\xce\xf5\xaf\x94\x6d\x3d\xb8\xb1\x30\xe1\xf7\x58\x69\x51" + - "\xb9\x67\x9f\x19\x1a\x20\xfc\x4a\x9a\x32\x2f\x8f\x23\xc2\xc3\x44\x5f\x17\xa4\xf4\x54\x86\x1a\x77\x52\xd0\x32\x73" + - "\xc7\x30\x67\x68\x9c\xb0\x21\x65\x56\x39\x63\x8b\x33\x34\x4a\x98\x56\xe7\x33\x75\x3b\x59\x33\x34\x54\x78\x26\xc7" + - "\x92\x7a\x70\xd0\xe0\xb7\x98\x75\xdc\x43\x73\x86\x46\x0c\x25\x9e\x6f\x70\xce\xd0\xb8\x61\x43\xbb\xaf\xd4\xc7\x26" + - "\xee\x0d\x56\x75\xdd\xf7\x73\xea\x09\x3a\xcf\xd0\xe0\xe1\xa1\x2a\xd8\x36\xa4\x57\xb7\xd0\x28\xa2\xc0\xf4\xea\x32" + - "\x1a\x4a\x14\xf6\x40\x9e\xf3\x73\x23\xe3\xb1\x24\x86\x7c\xaa\x9a\xfc\xe7\xaa\xec\x3c\xe8\x78\x88\x31\x73\x3a\x39" + - "\x33\x34\xc2\xb8\xbf\x14\xc5\xa9\x6a\xdc\x4d\x44\xa3\x8c\x7b\xea\x36\x75\x33\x34\xca\x98\xf6\xd2\x38\xe4\x29\xe9" + - "\xdc\xdd\x80\x06\x1b\xbb\xd3\xe5\xbc\x6f\x7d\x1a\x8a\x46\x1a\x05\x9a\x57\x41\xd1\x60\xe3\x89\x94\x99\x7f\x8e\x9b" + - "\xa1\x01\x47\x86\xe7\x9b\x53\x67\x68\xd0\x91\xa1\xf9\x1a\x87\x29\x09\x43\xf2\x36\x0d\x8d\x39\x72\x5f\x21\x64\x1a" + - "\x9f\xa1\xe1\x47\x0d\xdf\xdb\x54\x34\x0e\xa9\xa1\x7b\x9a\x8c\x86\x24\x35\x64\x7f\xd3\x31\x2d\x3a\x16\xd5\xde\xad" + - "\x78\x68\x68\xf2\x6b\x43\x4b\xf7\xae\xd8\x0c\x0d\x4b\x76\xa4\xfd\xe2\x8c\xc6\xcd\xd0\x80\xe4\x21\x2f\x3c\x71\x97" + - "\x19\x1a\x8d\xdc\x37\x39\x3d\xa4\xc4\x63\xd1\xd0\x80\x64\xef\xda\x70\xef\xd6\x89\x87\xc6\x24\x33\xd2\x9e\xf6\x95" + - "\x67\xfd\x34\x43\x23\x93\x35\xa9\x69\x93\x16\xb9\xbb\xa7\xd1\xf0\x24\xdb\x59\xf4\xef\xfa\xcd\xd0\x28\x65\x91\x97" + - "\xce\xf5\xff\x0c\x8f\x50\x9e\x2a\x8f\x13\x80\x46\x28\xeb\x4b\x7b\xaa\xdd\xfb\x5e\x33\x34\x44\x79\x69\x3d\xa2\xc3" + - "\x3a\xf8\xb8\xf7\x08\x0d\xeb\xda\xb6\xf2\x4c\x8c\x68\x94\xb1\xc7\x88\xf7\xaf\x31\x29\xea\x13\xd9\x7b\x66\x64\x34" + - "\xd6\x68\x62\xfb\xdc\xed\x19\x1a\x75\x94\x14\xf8\x69\x1c\x27\x2a\x1a\x73\x80\xa8\xfe\x9a\xd1\xf5\x81\xe4\xbd\xeb" + - "\x9a\x7c\x7f\xe9\xdc\x7b\x16\x33\x34\x02\x69\xe3\xfb\x79\x40\x35\xa2\x64\xe1\x2a\xea\xd6\x0b\x34\x22\x49\x5f\x6a" + - "\x52\x7a\x70\xf0\x9d\x4d\x7e\xee\xca\x6f\x35\xd1\x50\xa4\x42\xf5\x58\x6b\x34\x1c\x59\x54\x47\xcf\xe6\xf0\x6c\x8d" + - "\xee\x75\x16\x9e\x0d\xd5\x19\x1a\xbd\xec\xab\xf1\x6c\x27\xcf\xd0\xf0\x65\x49\xbf\xc6\x5f\xf3\x32\xab\xbe\xba\xf1" + - "\x70\xcf\x35\xad\x3c\x26\x10\x0f\x63\x12\x77\x80\x71\x86\x46\x31\xbd\xee\x26\x1a\xc4\xec\xeb\xf0\xb0\x85\x6e\x67" + - "\xb0\xa3\x6e\x6e\x1c\x4c\x17\xe8\x8b\x17\x07\x8d\x5b\xb6\xd4\xa3\xac\x68\xcc\xf2\x50\x54\x75\xfd\x1a\x67\xee\x03" + - "\x47\x74\x86\x86\x2e\x05\xa2\x5f\x18\x68\x04\x53\x60\xfa\x0f\x41\xcc\xf0\x50\xe6\x50\xa9\x1b\x11\x0d\x67\x72\x44" + - "\x6f\x67\xa3\xd1\xcc\xb4\xa1\x59\xde\xf5\xeb\x20\x4f\x2b\x31\x2d\xe1\x57\x47\x3c\x96\x16\x8f\x67\x5e\xba\x82\x36" + - "\xee\x79\x18\x0d\x65\xf2\xc3\xb8\x4e\x1c\x34\x86\x99\x56\xe7\xba\xa1\x6d\xeb\xe9\x3c\x34\x88\x49\x49\xe3\x9f\xc4" + - "\xd1\x10\x26\x43\xf1\x1a\x6d\x34\x80\xd9\x55\x5f\x7d\xed\x42\xe7\x9a\x8e\x74\xee\xe9\x05\x0d\x5b\xb6\x99\x7f\xd7" + - "\x68\x86\x46\x2d\x4f\xa3\x58\xa8\xed\xb8\xec\xd9\xe1\x6f\x0f\x8b\xe8\x2e\x08\x3b\x91\xdb\x76\xb4\xf1\x55\x88\xfb" + - "\x29\x17\xb6\x74\x29\xf6\x6e\xa5\x42\x63\x96\x1c\x71\x15\xcf\xdc\x68\xb8\x9f\xd2\xa3\xad\x7d\x68\xb8\x73\xd2\xa3" + - "\x6d\x7c\x68\xe8\x22\x45\xde\xee\x8d\x7d\xbb\xe5\x33\x34\x6a\xd9\xd0\x63\xde\x76\xfc\x0a\xc0\x08\x3a\xba\x73\x5e" + - "\x54\x97\x6c\xf4\x7c\xcd\x0c\x0d\x43\x72\x5c\xff\x29\x9b\xd9\x16\x53\x84\xae\xa1\x34\x4e\xab\x32\xf7\x59\x96\x2d" + - "\x7e\x7c\x8a\xd2\x38\xa3\x69\x9e\x5d\x2a\xe7\x91\x4d\x3a\x4f\x50\x63\xe1\xe4\x72\x8e\x06\x4a\x7b\xfb\xec\x3d\x4a" + - "\x35\x47\xa3\xa5\xbd\x75\x1e\x41\x43\x97\x21\xf4\x99\x16\x1e\x8f\x69\x8e\x86\x4d\x7b\xd5\x71\x63\xa0\x2b\x11\xd2" + - "\xba\x63\x29\x73\x34\x5c\x4a\x0a\xea\x9e\xc2\xe7\x68\xf8\x92\xfe\xed\xc2\x6e\x82\x3b\xbb\x77\x8e\x46\x30\xbf\xe4" + - "\xa5\xf3\x1c\xcb\x1c\x0d\x5f\xfe\xed\xe2\x59\x97\xe2\x47\x77\x6b\xe2\x76\x68\xe7\x68\xdc\x72\x9f\xb7\x27\xf7\x7e" + - "\xe5\x1c\x8d\x58\x7e\x29\x7d\x91\x92\x39\x1a\xb0\xdc\x93\xfd\x6b\x7c\xa8\x9a\xf3\xa5\x70\x9e\x66\x99\xa3\xf1\xca" + - "\xce\x1d\xf7\x9d\xaf\x0f\xd8\x61\xeb\x7d\x41\xd2\x2f\xde\xe5\xf9\x1c\x0d\x53\xee\xdd\x73\xed\x1c\x0d\x4d\x92\xba" + - "\x76\x8e\x85\xc3\xc3\x01\x3b\xbf\x4c\x1b\x4f\x90\x62\x8e\x06\x24\x4f\xd5\xa5\xf1\x1d\x7b\x9e\x2f\x66\xd8\x11\xf2" + - "\x82\x9c\xdd\xfd\x8a\x46\x24\xb3\x4b\x5d\x78\xe3\x91\x73\x34\x1e\x59\xe7\xc7\xe3\x6b\xbc\x27\xee\x58\xc3\x1c\x0d" + - "\x48\xb6\x69\xde\xb6\x55\xe3\x36\x75\x68\x34\x72\x9f\x77\x69\xe5\x5e\x49\xcd\xd1\x50\xe4\xbe\x73\x1e\x55\xc2\x11" + - "\x5e\xf6\x6e\xfd\x46\x11\x5e\x9d\x43\x35\x49\x08\xd6\xfa\xbf\x3a\xad\x9b\x03\xa1\xb9\xec\x9d\xca\x36\x4f\xf6\x19" + - "\x8e\x72\x1d\x02\xbb\xf1\xe0\x6c\x38\x1a\x42\xcd\x53\x1a\x17\x55\x51\xb8\x6d\x35\x1a\x39\x55\x68\x71\xd7\x5b\x6d" + - "\xf7\xc0\x43\x03\xa7\x34\xbb\xa4\xfc\x6a\xa0\x13\x0d\xdd\x6f\x67\xa9\x31\x02\xb6\x12\xe6\x68\xc8\x54\xa0\x8f\x6d" + - "\x63\xcc\xd1\xe0\xe9\x99\x96\x97\xf8\x44\xce\xfb\x4b\x73\xf4\xcc\x1d\x68\x10\xf5\x5c\x65\xa4\x18\x59\xa2\xcf\xd1" + - "\x58\x6a\xe5\xbc\x5f\x41\xe7\x68\x20\xf5\xd8\x10\xcf\xe0\x42\x83\xa8\xed\xa5\x64\xe6\xc9\xed\x33\xcf\xf1\x83\x9d" + - "\x32\xf7\x89\x1b\x0d\x3d\xde\xd9\xa3\xf1\xbb\x6f\x4e\x3c\xf4\x1c\x78\x8f\x07\x6e\x12\x3a\x91\x51\xcd\xd9\xff\x95" + - "\xa6\x9d\x38\xa5\xe7\x39\xe0\x33\x47\xa3\xaa\x1a\xb6\xc8\x56\xe1\x24\x80\x29\x8f\x46\x20\x40\x7d\xd1\x98\xab\x46" + - "\xc4\xb7\x59\x31\x47\xcf\x88\x6a\xe8\xa3\x63\x00\x0d\xe2\x6a\x24\xbc\xdb\x2d\x73\xfc\x00\x69\x93\x93\xf2\x58\xd0" + - "\x11\x5c\xfc\x0c\xa9\xc4\xf5\xb6\x1c\x0d\xed\x2a\xd4\x91\xae\x43\xa3\xba\x0a\xd9\xa7\x35\x68\x50\x37\xad\xca\xb6" + - "\xf2\x98\x63\x3c\x94\x7b\xa9\x69\x23\x2e\x28\x3b\x11\xd1\xd9\xf8\xb2\x1f\x43\x43\x4d\x53\x6f\xd6\xfc\x22\x45\xcf" + - "\x19\xf6\x68\x23\xbd\x88\x69\x10\xc3\xf3\x85\x6d\xe7\x68\xd8\x96\xa1\x79\x16\x20\x43\xc8\xf6\xf7\xac\xf0\x57\x4a" + - "\x6e\x21\xea\xc0\xae\xea\xff\xba\x35\xea\x09\xab\x44\x82\x97\xa4\xd6\x32\x4e\x74\xa4\x8e\x4f\xf9\xf1\x54\xb0\xe5" + - "\xba\xb8\x5c\xdc\x1c\xf7\xe4\x43\x32\x89\xc4\xff\x93\x57\x41\x55\x66\x2a\xed\x26\xe7\xfb\x7f\xa5\xc5\x33\xed\xed" + - "\x42\xf4\x6f\xf4\x42\xdf\x4f\x22\xf5\x61\x12\xfd\x4b\x93\x93\x62\x62\x24\xc9\x82\xec\x2c\x39\x3b\xfa\x55\xce\xe9" + - "\x72\xfe\xb0\xda\xcc\x96\x0b\x90\x3c\xe6\xbb\xc5\x62\xf1\x88\xe6\x6e\xfa\xee\x70\x38\x48\x0e\xf5\xa4\x35\x68\xaa" + - "\x1a\x8d\x79\x90\xa4\x06\x70\x05\xbe\x6a\x8c\xe9\x09\x6c\x88\xd0\x28\xc9\xde\x86\xec\x37\x8f\x32\x45\x0d\xcc\x63" + - "\x00\xf3\x4f\xed\x58\xfe\x16\x3d\xa9\x94\x24\x31\x5f\xac\xe6\x9b\x14\x25\x01\x52\x21\x40\x3a\x0c\x5d\xe5\xa4\xea" + - "\x4e\x79\x29\xb2\x4d\x3d\xc2\xef\xab\xfa\x85\x25\xc7\x88\x86\xeb\xb1\xe9\xa5\x8d\x1b\x76\x92\xa4\xaf\x1b\x40\xc7" + - "\xd5\xe1\xd0\xd2\x6e\x17\xc5\x73\x95\xef\x08\xc9\x88\xa4\x72\xb4\x88\x8c\x01\x66\x32\xa7\x73\x9e\x65\xc3\x2d\xda" + - "\x94\x34\xd5\xa5\xa5\x05\x4f\xdb\xf2\x34\xcd\x3b\x7a\x7e\x22\x4f\x2c\x35\x01\x5e\xc8\x8b\xf2\xf3\x31\x6e\x68\x5b" + - "\x57\x65\x9b\x3f\xd3\x09\xbb\xe0\x7e\xba\x9c\xf7\x25\xc9\x8b\x48\xe2\xab\x2f\x4f\x92\x19\x3d\x77\x19\x4f\x45\xa2" + - "\xe5\x33\x78\xc4\x53\xbf\xf0\xfa\x7a\xd5\x12\x29\x29\xc4\x88\x6a\x48\x96\x5f\xda\x5d\xb4\x56\x12\x61\x90\x03\x2b" + - "\xbf\xf8\xae\x3d\x8f\xd4\xad\xa5\xbe\x19\x1f\x0d\xb8\xfa\xe3\xd9\x55\xbe\xcb\xb2\xec\xd1\x6e\xc6\xd2\xb0\x00\x0d" + - "\x29\xe5\x9d\x6e\x52\x14\xd1\x74\xde\x46\x94\xb4\x34\xce\xcb\xb8\xba\xb0\x41\x10\x57\x21\x50\x23\x20\x50\x74\xfc" + - "\x14\x03\x26\xe3\x95\x4a\x33\x26\xb2\x6c\x71\x8d\x63\xf3\x68\x34\x17\xc6\x4b\x7c\x93\x19\xc0\xe4\x67\x95\x27\x06" + - "\x34\x5a\xde\x4c\x97\x22\xa1\x54\x69\x65\xdb\xc4\x55\x59\x70\x8b\x36\x5c\x6b\x27\xfb\xb6\x2a\x2e\x1d\xbb\xd6\x2e" + - "\xbb\x8d\x93\x57\x1d\x52\x1b\xf9\x8a\x60\xb2\x9b\x58\x94\x9a\xc9\xc5\x98\x25\x2b\xf2\x7a\x17\x35\x34\xed\xa0\x71" + - "\xc5\x32\xdc\x48\xde\xf8\x48\x25\xfd\x12\x50\x66\xa3\x43\x8a\x06\x53\x30\x34\xa3\xed\x48\x97\xa7\xa0\x11\x52\xd7" + - "\x4c\xdd\xd3\x32\x77\x59\x89\xb8\x06\xb6\xc1\x38\xf9\xb1\xa9\x0a\x95\x56\x8b\x5b\x30\x34\x23\xd6\xf4\x34\x9b\x44" + - "\xd3\xd3\xbc\xff\xcf\xa2\xff\xcf\xb2\xff\xcf\xaa\xff\xcf\x7a\x12\xf5\x85\x32\x8d\x48\x5f\xd2\x17\x9c\xd6\xe3\x26" + - "\x5a\x26\x01\x58\x61\x49\x00\xa6\x33\x67\xbe\xb1\xe9\x69\x16\x4d\xd9\xe1\xd4\x9e\x81\x59\xa4\x7e\xce\xc1\xe7\xf9" + - "\xf0\x79\x01\x3e\x2f\x86\xcf\x4b\xf9\xb9\xb7\x46\xa7\xe5\x50\xb0\x02\xf0\xab\xe1\xf3\x1a\x7c\x5e\xcb\xcf\x80\x15" + - "\xc5\x09\xcb\x93\x32\x7c\x56\x9c\x00\x46\x06\x3e\x06\x36\xa2\x81\x87\x81\x85\x9e\x96\xe2\x01\xb0\x20\x39\x18\xa4" + - "\x3c\x9a\x52\x41\x5a\x99\xcd\x66\x83\x77\xeb\xd0\x8f\xa1\xe3\x75\x36\xa4\xd2\xbb\x4b\xa7\x0c\x34\xfa\x76\x2b\x22" + - "\xa1\xd2\x34\x5d\xa4\xf5\xea\x77\x8a\x3b\x5d\x63\x75\x2d\x85\x2d\x9d\x05\xb4\x74\x09\x78\xbf\x55\x6f\xa0\xf6\x61" + - "\x1d\x1f\x05\x76\xbb\xca\xcd\x08\xfb\x54\x64\x95\x04\x00\x0b\x30\xe5\xb1\x3e\x9e\x5b\x10\xb0\x85\x0b\xa5\x05\x30" + - "\x0d\xe5\x12\xca\x80\xb5\xc1\xf4\x49\x1f\x00\xc4\x8a\xb5\xc1\x84\x80\x34\xd6\xba\x9d\x10\x10\x83\xbb\x52\xeb\x9e" + - "\x4a\x94\x68\xdd\x50\xc8\xdc\x49\x8e\x49\x04\xd2\x5c\x83\x4f\x72\xa0\x2c\x50\xb3\xb3\x14\xe4\x45\x8e\xae\x0f\xd1" + - "\x39\x2f\xf9\xac\x1f\xed\x36\xeb\x87\xfa\xe5\x23\xab\x73\xa8\x5d\x93\xd0\xac\x67\x4f\x25\xdb\x91\xbd\x86\xa7\xe1" + - "\x1c\xba\xec\x4c\x9a\x2f\x93\x48\xe5\xf6\x1c\xb2\xb1\xcd\x79\xfe\x35\xcc\x55\x48\x0f\x0f\x74\x21\x09\x30\x2f\xb3" + - "\x5f\xc5\x31\x7c\xf6\x97\x70\xdf\xfa\x8f\x1a\x14\xcf\xd5\x6b\x82\xb1\xaf\x1a\x1c\xbf\x3d\x69\x01\xf2\xcf\x1a\xa4" + - "\xb8\xf4\x68\x81\x8a\xef\x1a\x6c\x59\x7d\x6d\x08\xef\xd6\xaf\xa7\xbc\xa3\x2c\x55\x1b\x4b\x0f\xd3\x7f\xd7\x9b\x53" + - "\x7d\xa5\x4d\x4a\x5a\x3a\x10\x06\xd9\x22\x55\xa9\x86\x73\xa9\x6b\x0f\x8e\x2a\xd5\x1b\x4a\x6a\x76\x19\xf6\x67\x1c" + - "\x69\x28\xd6\xb0\xce\x17\x99\xed\x0c\x31\xab\x0c\xa2\x6e\x72\x95\x83\x57\x5f\x5a\x48\xcf\x5f\x83\xc3\x56\x11\x0f" + - "\xeb\x64\x9b\x68\x44\xdb\x4b\x9a\xd2\xb6\xd5\x89\xa6\x9b\xf5\x22\xd3\x89\x0a\x38\x8c\xe8\x7e\xb5\x9c\xa7\x1a\xd1" + - "\xbc\x3c\x54\x3a\xc5\xd9\x26\x79\x38\xe8\x14\x7b\x20\x8c\xdc\x72\x35\x5f\x6f\x35\x72\xe2\x0a\x83\x06\xf6\x40\xd6" + - "\xd9\x62\xaf\x53\x14\x70\x08\xd1\xf5\x7a\x35\x33\x78\xcc\x48\x79\x34\xa0\xc8\x76\xb9\x5c\xce\x75\x9a\x1c\x0c\x21" + - "\xf9\xb0\x5c\xac\x16\x72\x6c\x4f\xf7\x47\xb4\x7b\xa4\xff\x6d\x0f\x37\xa3\xe3\x06\x7c\x50\x15\x82\xa6\xf7\xe0\xfe" + - "\xa8\xf5\x1f\x02\x9f\x1d\x0e\x49\xf6\x00\xab\xb1\x3b\x12\x41\x4b\x67\x74\xbe\x5f\x80\x6a\x54\x8f\x62\x75\x6c\x69" + - "\x76\xd0\x9a\x62\x74\x2d\x82\x43\x0e\xd9\x76\x70\xb7\xf7\x47\xad\x8f\xc7\xac\x13\x01\x08\xfe\x6a\x0e\x1b\x9a\xee" + - "\x57\xa0\x1a\xd0\xeb\x18\xf8\x3c\xa3\x19\x85\xb5\x58\xdd\x8f\x60\xd1\xe5\x7e\xbb\x57\x1a\xcb\x92\xd8\xf1\xf3\x3d" + - "\xd0\xf6\xaa\xc9\x64\x0b\xbd\x81\x1d\xcb\x1d\x1c\x25\xc6\x3a\x45\xcb\x11\x6d\xad\x4e\xaa\x62\x12\x5d\x0a\xcb\xcf" + - "\x48\xfc\x4e\x46\x55\x44\x3d\x62\x55\x44\x17\x8e\x2f\xc8\xe8\x94\x24\xa2\x52\x31\x96\x4f\xe3\x52\xb2\xa4\x5b\x5a" + - "\x02\x4e\x1e\xe3\x8b\xc4\x8c\xd7\x82\xbc\x5c\x2a\x12\xc1\x91\xf9\xa2\xd7\x85\x2a\xea\xe5\x5f\xe2\x95\x5c\xe4\x8e" + - "\xd2\x7b\x2a\x72\xff\xda\x5a\xd6\xd5\x88\x25\x81\xb6\x32\x13\xf5\xad\x94\x74\xb2\x30\x79\xce\x07\x79\x66\xd9\x24" + - "\xca\x90\xfc\xb9\xc3\x9a\x5c\x02\x76\xb6\x4b\x0d\xf2\x79\x6b\x1e\x87\x10\x4c\xa0\xc7\x90\x15\x20\xf4\x2f\x99\x79" + - "\x77\x28\x2a\xd2\xf1\x79\x5a\x66\x5c\x64\x2b\xd5\xb5\x50\x31\x74\xfd\xf9\x2e\x2d\x28\x69\x00\x96\x35\x97\x0f\x5f" + - "\x07\x7c\x5a\x14\x79\xdd\xe6\x2d\xaf\x07\x9b\x7e\x79\xea\x41\x83\x51\xe1\xe6\x68\x6d\x9e\x3d\x24\x9a\xa7\xc3\x52" + - "\x73\x66\xa4\x23\x71\xd5\xe4\xc7\xbc\x24\x45\xcc\x13\x75\x4e\x22\x33\xaf\xba\x5c\x61\x9e\x68\x51\x3b\xc6\x10\x8f" + - "\x7c\x69\x53\x6a\x5e\xe6\x2c\xf1\x5b\x7b\x36\xfd\xa8\x2d\x8f\xc4\x8c\x4d\xf6\x43\xe6\x4e\xdd\xc7\xea\xc7\x9c\xb1" + - "\xbc\xe1\xae\x26\xe6\x46\x6e\xa6\x2b\x6d\xe0\x2b\xbd\xb4\x87\x3d\xa8\xaf\x2a\x76\x05\x69\xbb\x38\x3d\xe5\x45\x36" + - "\x89\x40\x49\xed\x2a\xb8\x40\x14\x91\xd0\xd7\x31\xe6\x01\x96\xf4\x37\xc1\x27\xf9\x7a\x00\xf8\x34\x78\xa3\x76\x78" + - "\x4d\x4f\x13\x1f\x18\xcf\x1d\xba\xc9\xe2\x45\x84\xc8\x11\x96\xb0\x12\x88\x22\x1a\xad\xc2\xfc\xdf\xff\x65\x9e\xcc" + - "\x96\xd1\x5f\x92\xe4\x5f\x92\xef\xd5\x14\xa1\x70\xe3\x86\x3e\xd3\xa6\xd5\xe8\x4d\xeb\x4b\x51\x00\x87\xd7\xb0\x31" + - "\x33\xd4\xc8\x24\x8f\x98\x6b\x0c\x83\x6f\xca\x42\x81\x4e\xb7\x74\x22\x71\xb3\x68\x8a\x06\x03\xd1\x65\xc4\xf2\x9f" + - "\xda\x40\x2e\x09\xc3\x76\xeb\x75\x69\x19\x6c\x21\x98\xb3\x4f\x20\x90\xb7\x7b\x3c\x7d\x22\x99\x10\xdb\x26\x9e\xf6" + - "\x72\x08\x6f\x73\x05\x11\x6f\x6b\x15\x19\x6f\x63\xbd\x94\x00\xa1\xc8\xd0\xc3\x5e\x03\x23\xa6\x8d\xb2\xcd\x24\xcb" + - "\x1a\xe9\xd5\x79\x17\xa3\x66\x2e\x4c\xff\x54\x14\xf6\x16\xc0\x9f\x68\x59\x54\x93\xe8\x4f\x55\x49\xd2\x6a\x12\xfd" + - "\x81\xed\x3a\x92\x76\x12\xbd\xff\x43\x75\x69\x72\xda\x44\xff\x46\xbf\xbe\x07\x0f\x05\x00\xea\xba\x29\x9c\xd7\x2f" + - "\x32\xa4\x6c\xdb\x57\xe5\x6b\x6e\xe6\xab\x25\x75\xad\x4a\xb7\x87\xf9\x61\x89\x47\xaa\x45\xb5\x5f\xf6\xd9\x0d\xb5" + - "\xfa\x3c\xf3\x05\x52\xdf\x42\x8f\x8c\xc3\x24\xd6\x79\xd9\xd2\x2e\x4a\x58\x7c\x37\x4a\x8c\x1d\xb2\xe9\x7c\xf5\x51" + - "\xed\xc6\x85\x22\x80\x96\x59\xad\x33\x9f\xf2\x90\x1b\x07\xa6\x7f\xe1\xe2\x56\xbe\x94\x62\x7e\x93\x11\x12\xb1\x9b" + - "\x63\x5b\x72\xc5\xc1\x56\xce\x59\x66\x1c\xc5\xe4\x6c\x71\xed\x06\xde\xd7\xaa\xc9\x78\x02\xe8\x5d\x24\xf2\x40\x17" + - "\x85\x2a\xe8\x3d\x0a\xf9\xbd\xff\xe0\x52\x99\x55\xff\xcf\xb1\xed\x91\xa6\xa9\x57\x99\xfa\xe6\xdb\x7a\x6c\xca\xdc" + - "\xf9\x7e\xc5\xa3\x19\x86\xa8\x1b\xca\xf8\xc6\x79\x05\x4f\xcb\x20\x5c\x29\x8b\xdf\x13\x69\xd3\xa6\x2a\x0a\x95\x3b" + - "\xfa\x4c\x5e\x94\x48\x17\xcb\x44\xdf\x58\x88\x5f\x77\x11\x87\x57\xbb\x6c\xbd\xe7\x95\x1b\xef\x42\xf8\xa7\xad\x99" + - "\xd6\xc9\x12\x56\xdf\x1a\x10\xa0\x20\xfe\x3f\xe6\xb2\xea\x8c\x48\xdf\x74\xb3\xd2\x9d\x3f\x8c\xca\x76\x3b\x1f\xa1" + - "\xb2\xdd\x8c\x53\x99\xcd\x93\x64\x84\xcc\x6c\x66\xd0\x19\xe0\xe2\x43\x71\xc9\xb3\x5f\x5b\x86\xd3\xa6\xfa\x0a\x2d" + - "\xbf\x40\x8b\x0d\x6a\x62\xc9\x34\x1b\x16\x31\xd3\xb4\x2a\xe2\xe2\x18\xcf\x26\x91\xfa\x99\x80\xdf\xf0\xfb\x7c\xf8" + - "\x0d\x7e\x2e\x26\x5c\x2e\xec\x8f\xe5\xf0\x7d\x35\xfc\x5c\x0f\x3f\x37\xc3\xcf\x87\xe1\xe7\x56\xd1\x38\x67\x8a\x95" + - "\xfe\x67\x02\x7e\xc3\xef\xf3\xe1\x37\xf8\xb9\x80\x64\x96\xc3\xf7\xd5\xf0\x73\x3d\xfc\xdc\x0c\x3f\x1f\x86\x9f\x03" + - "\x2b\xed\x59\xb1\xd2\xff\x4c\xc0\x6f\xf8\x7d\x3e\xfc\x06\x3f\x17\x90\xcc\x72\xf8\xbe\x1a\x7e\xae\x87\x9f\x9b\xe1" + - "\xe7\xc3\xf0\x73\x60\xe5\xa5\x55\xac\xf4\x3f\x13\xf0\x1b\x7e\x9f\x0f\xbf\xc1\xcf\x05\x24\xb3\x1c\xbe\xaf\x86\x9f" + - "\xeb\xe1\xe7\x66\xf8\xf9\x30\xfc\xdc\x1a\xfb\x81\x30\x5b\x77\x3f\x54\xf0\xcd\xcc\x71\x4d\x87\x5a\xf8\x0f\xd2\x48" + - "\xb0\x16\x36\xb9\xe3\xdb\x15\x60\xf7\xdd\x04\x98\x41\x80\xed\x6c\xba\xe6\xff\xb7\xb1\x00\x13\x08\xf8\xb0\x98\x2e" + - "\xc4\xff\x99\x80\x5b\x08\x07\xf6\x57\x24\xf3\xb0\x78\xbd\x76\xd6\xb7\x81\x70\xab\x07\x67\x75\x6b\x0d\xce\x6a\xdf" + - "\x0a\x16\x2f\xdd\xcd\x5b\x42\xb8\x85\xbb\x75\x0b\x08\x37\xb7\x5a\xa7\x8b\xdb\xdd\x3a\x4d\xea\xee\xc6\x31\xc7\x5a" + - "\xf4\xa1\x54\x4c\xbb\x0f\x39\xd4\x0c\x42\x79\x3a\x92\x43\x27\x10\xda\xd3\x9b\x0c\x7a\x0b\x81\xed\x2e\x65\x30\x0f" + - "\x10\xc6\xd3\xaf\x0c\x78\x03\x81\x3d\x9d\xcb\x80\xd7\x1a\x30\xde\xfa\x15\x84\xf1\x74\x33\x03\x5e\x42\x60\x4f\x5f" + - "\x33\xe0\x05\x04\xb6\x3b\x9c\xc1\xe8\x1d\x34\xd2\x76\xad\x9f\x46\x9a\xae\xf5\x12\x9c\x3b\x15\x50\x7b\x92\xfa\x21" + - "\x2c\x14\xa6\x1e\x3d\xd0\x0c\x00\x79\xb5\xa3\x07\x4e\x00\xb0\x57\x39\xda\x93\x50\x0e\x0e\x8b\xe9\x46\x7b\x12\xba" + - "\xc1\x41\xbc\xaa\xd1\x9e\x84\x6a\x88\x00\x91\x4f\x3c\xed\x49\x68\x86\x80\xc5\xdb\xbd\x02\x20\x5e\xbd\x68\x4f\x42" + - "\x2f\x38\xac\x57\x2d\xda\x93\x50\x0b\x0e\x8b\x69\x45\x7b\x8a\xb5\x6e\x19\x69\x35\xec\x9d\x91\x46\xc3\xbe\x41\x54" + - "\x82\x9f\x5e\x93\x4a\xa1\x07\x1f\x6d\xdd\x90\xd0\x33\x1b\xda\xa3\x24\x12\x2b\xb1\xb1\x3c\xda\x22\xb0\xb6\x36\x92" + - "\xad\x36\x02\xf6\xc1\x86\xf5\xe8\x8f\x40\xda\xd8\x48\x1e\x45\x12\x48\x6b\x04\xc9\x25\xad\x95\x0d\xeb\x51\x2d\x81" + - "\xb4\xb4\x91\x3c\x3a\x26\x90\x16\x36\x92\xad\x6c\x02\x16\xeb\xf0\x51\x59\x21\xfd\x3e\x2a\x2a\xa4\xd7\x43\x43\xf9" + - "\xf7\xf1\x51\xdf\xec\xa4\x5a\x3b\x08\x32\x82\xaf\x2a\xd7\x97\x4a\x6c\xdc\xe8\x10\x33\x7d\x4d\xa6\x75\xbf\x0e\x99" + - "\x68\x90\xfa\xf8\xd0\x20\xb7\xc6\x62\xd1\x2c\x7f\xd0\xca\xf5\x71\xa0\x01\x6e\x34\x40\x5d\xf7\x35\xc0\xb5\x0e\x68" + - "\xb5\x72\xa5\x95\x2f\xdd\x8d\x5c\x6a\x80\x0b\x77\x1b\x17\x1a\xe0\xdc\x6a\xa3\x21\x78\x77\x1b\x75\xf9\xbb\x9b\x08" + - "\x3d\x28\xdd\x85\x42\xc0\x66\x1a\x98\xa7\x53\xa1\x0f\x85\x3b\x51\x36\xf8\x56\x83\xb6\xbb\x17\x78\x51\xb8\x1b\x65" + - "\x43\x6f\x34\x68\x4f\x47\x03\x3f\x4a\x73\xa4\x6c\xa0\x95\x06\xe4\xe9\x72\xe0\x49\xe1\xae\x94\x0d\xbd\xd0\xa0\xed" + - "\xce\x07\xbe\x14\xee\x4c\x21\x7d\xa0\x77\x81\xbf\x7e\xbd\xbf\xf8\xdc\x69\x40\x0d\xee\x94\xe6\x4f\x21\x50\x33\x08" + - "\xe5\x55\x95\xc1\xa1\x42\x3d\x2a\x1b\x7a\x0b\x81\x31\x45\x51\x2e\x15\xea\x53\xd9\xc0\x1b\x08\xec\x55\x13\xe5\x54" + - "\x41\xaf\xca\x86\x59\x41\x18\xaf\x92\x28\xb7\x0a\xf5\xab\x6c\xe0\x05\x04\xc6\x54\x44\x39\x56\xa8\x67\x85\x88\x5e" + - "\x93\xbc\xbf\x72\xad\x97\x10\xfd\xd0\x7d\x2b\xcc\xb9\x42\xc1\x67\x08\xb8\x47\x63\x74\xef\xca\xe7\x5e\x61\x68\x5b" + - "\x04\xcb\xd6\x21\xcd\xbf\xf2\x39\x58\x18\xd6\x06\xc1\xf2\x68\x95\xe6\x61\x21\x2e\x16\x06\xbc\x42\x80\x3d\x7a\xa6" + - "\xf9\x58\x3e\x27\x0b\xc3\x5a\x20\x58\xb6\xe6\x69\x5e\x96\xcf\xcd\x42\xfb\x12\xeb\xca\x31\xbe\xb0\xfe\x4f\xae\x0a" + - "\x1f\xdf\x23\x36\xf9\xe6\xe0\xa4\xd7\xd9\x62\x95\x7b\x9d\x2d\xc6\x6a\x90\xb3\xc5\x1a\x18\xe4\x6c\x0d\x6c\xe1\xce" + - "\x56\xdf\x82\x20\x67\xab\x6f\x75\x90\xb3\xd5\x4b\xca\xe7\x6c\xf5\x42\x0d\x72\xb6\xfa\x8e\x08\x72\xb6\xfa\xfe\xf3" + - "\x39\x5b\x7d\x57\x07\x39\x5b\xbd\x58\x43\x9c\xad\x73\x16\xe4\x6c\x29\xb0\x30\x67\x4b\x81\x87\x39\x5b\x12\xdc\xeb" + - "\x6c\x49\xa0\x30\x67\x4b\x42\x87\x39\x5b\x12\xda\xeb\x6c\x49\xa0\x30\x67\x4b\x42\x87\x39\x5b\x12\xda\xeb\x6c\x49" + - "\xa0\x30\x67\x4b\xf5\x41\x88\xb3\x25\x81\xfd\xce\x16\x83\x1a\x75\xb6\x14\x54\x90\xb3\xa5\xa0\x83\x9c\x2d\x09\xed" + - "\x73\xb6\x24\x4c\x90\xb3\x25\x81\x83\x9c\x2d\x09\xec\x73\xb6\x24\x4c\x90\xb3\x25\x81\x83\x9c\x2d\x09\xec\x73\xb6" + - "\x24\x4c\x90\xb3\xa5\x44\x1f\xe0\x6c\x49\x58\xaf\xb3\x75\xce\xae\x72\xb6\x00\xf8\x35\xce\x16\x40\xbb\xc6\xd9\x1a" + - "\xd0\x02\x9c\xad\x01\xf8\x1a\x67\x6b\xc0\xba\xc6\xd9\x1a\xb0\x02\x9c\xad\x01\xf8\x1a\x67\x6b\xc0\xba\xc6\xd9\x1a" + - "\xb0\x02\x9c\xad\x01\xf8\x1a\x67\x0b\xf4\x65\xb8\xb3\x35\x20\xdd\xe2\x6c\x19\xbb\xec\xf7\xd8\x94\x7e\xf3\xae\xb4" + - "\xd7\xdb\x62\x95\x7b\xbd\x2d\xc6\x6a\x90\xb7\xc5\x1a\x18\xe4\x6d\x0d\x6c\xe1\xde\x56\xdf\x82\x20\x6f\xab\x6f\x75" + - "\x90\xb7\xd5\x4b\xca\xe7\x6d\xf5\x42\x0d\xf2\xb6\xfa\x8e\x08\xf2\xb6\xfa\xfe\xf3\x79\x5b\x7d\x57\x07\x79\x5b\xbd" + - "\x58\x43\xbc\xad\xe2\x18\xe4\x6d\x29\xb0\x30\x6f\x4b\x81\x87\x79\x5b\x12\xdc\xeb\x6d\x49\xa0\x30\x6f\x4b\x42\x87" + - "\x79\x5b\x12\xda\xeb\x6d\x49\xa0\x30\x6f\x4b\x42\x87\x79\x5b\x12\xda\xeb\x6d\x49\xa0\x30\x6f\x4b\xf5\x41\x88\xb7" + - "\x25\x81\xfd\xde\x16\x83\x1a\xf5\xb6\x14\x54\x90\xb7\xa5\xa0\x83\xbc\x2d\x09\xed\xf3\xb6\x24\x4c\x90\xb7\x25\x81" + - "\x83\xbc\x2d\x09\xec\xf3\xb6\x24\x4c\x90\xb7\x25\x81\x83\xbc\x2d\x09\xec\xf3\xb6\x24\x4c\x90\xb7\xa5\x44\x1f\xe0" + - "\x6d\x49\x58\xaf\xb7\x55\x1c\xaf\xf2\xb6\x00\xf8\x35\xde\x16\x40\xbb\xc6\xdb\x1a\xd0\x02\xbc\xad\x01\xf8\x1a\x6f" + - "\x6b\xc0\xba\xc6\xdb\x1a\xb0\x02\xbc\xad\x01\xf8\x1a\x6f\x6b\xc0\xba\xc6\xdb\x1a\xb0\x02\xbc\xad\x01\xf8\x1a\x6f" + - "\x0b\xf4\x65\xb8\xb7\x35\x20\x8d\x79\x5b\x9d\x3a\x01\xea\x3d\x4d\x2a\x4f\x64\x13\x96\xa0\x8e\xc1\xcb\xf3\x5a\xec" + - "\x6e\xd3\x83\x7e\x86\x4b\x9e\x2d\x17\x9f\xc1\x35\x0c\xf3\xee\x02\x38\x49\xd5\x9d\x18\x5d\xe7\xdd\x60\xc5\xa9\x91" + - "\xe1\x04\x49\x7a\xe2\xbe\x65\xc5\xc9\x3c\x75\xfb\x2a\x7b\x7d\xea\x9a\xa7\x2e\x9b\x44\xd6\xb7\xd3\xf0\xed\x50\x55" + - "\x9d\x09\xa7\xbe\x9d\x78\x9a\x18\xfe\xf5\x44\x49\x66\x42\xaa\x6f\x27\x28\x32\x25\x17\xcf\x41\x66\x33\xc9\x4d\x57" + - "\xd5\x9e\x4c\x23\x59\x96\x19\xed\x33\x6a\x36\xc9\x71\xc9\x20\x97\x9b\xe6\x1e\xa2\xa2\xf7\x3f\x49\xe2\xbb\x43\xde" + - "\xc8\x1b\x40\xb0\xd9\x7e\x38\x28\xb4\xb4\x2a\x7a\x95\xab\xc7\x49\xfa\x01\xad\x8e\xd0\x8b\x9d\x64\xc7\x61\x4f\xe2" + - "\x1a\x09\x14\x7c\x82\xe8\xd2\xa7\x4e\x65\xac\x82\xa0\x1e\x71\x46\x53\xdf\xd8\x03\x89\xa6\x38\x5c\x9c\x56\x65\x46" + - "\xcb\x96\x66\x98\xf2\xa2\xa5\x40\x2a\xb0\xdc\x56\x69\xb4\xd4\x81\x6d\xab\x39\x5a\x6a\x28\xfc\xca\x18\x80\x31\x17" + - "\x92\x96\xfb\xc8\xab\xd1\x0a\x01\x6d\x3d\x52\x08\xd9\x1f\x8a\x91\xb6\x23\x85\x38\x2e\xd2\x72\xa4\xf0\x74\x43\x8b" + - "\xae\xa7\x2c\xc6\xab\xb4\x7b\x73\x53\xbc\x6d\xd7\xe4\x35\x90\xc7\xae\xec\x4e\x71\x75\x88\xbb\xd7\x9a\x7e\xa8\xb2" + - "\xec\xa3\x53\xed\xb6\xfd\x3f\x9d\x18\xbb\xac\x3c\x90\xf2\x5f\x90\x66\x97\x25\xb4\xc9\x25\xad\x8a\x1f\xd3\x82\xb4" + - "\xed\xef\x7f\xe8\xe7\x26\x7e\xc7\x12\xcb\x1e\xa4\xae\x88\x48\xb5\x2a\x2e\x67\x76\x99\x54\x2c\xb2\xc1\xad\x12\x4e" + - "\xb9\xcb\x34\xc2\x93\x48\x7c\x3e\xdd\x56\x1f\xe5\x77\x43\xec\xda\x8c\x09\x62\xca\xf3\x23\x61\x73\x87\x2a\x3a\x21" + - "\xd3\x4a\x26\x4a\xa1\xb1\x1a\xf4\x75\xaa\xb2\x2e\xe9\xd3\x0c\x56\x9b\x59\xa4\xd9\xbf\x41\xc7\x5d\x24\xb1\xda\x84" + - "\x9a\x81\xda\xec\xb9\x0d\x6b\xdd\xa0\xbb\x2e\x92\x43\x6d\xd2\x96\x8e\xa8\x0d\xaa\x76\x82\xc4\x4e\x7c\x1d\x46\x8a" + - "\x17\x0c\x8e\x64\x4c\x8d\x9f\x0c\xa6\x0d\xa0\xa1\x55\x1c\xdc\x49\x6d\x68\xe3\xc8\xd5\xfe\x87\xfe\x9f\x43\xad\x44" + - "\x26\x05\x54\xaf\x54\x19\xae\x58\xa2\xd8\xa1\x59\xb2\xd4\xd2\x1f\xac\x46\xab\xcc\xa5\x5c\x2e\xaa\x68\x8d\x52\x83" + - "\x40\x8d\x88\x7e\x61\xad\x04\x0a\xe6\xa2\x0a\x6a\x74\xab\x98\x96\xb9\x02\xd7\x1d\x2d\x95\x85\x47\xc7\x0c\xb8\x71" + - "\x25\x33\x18\x47\xb4\x4c\x23\xe9\x55\xb3\xa0\x7c\x1b\x59\x42\xb7\xe9\xda\xa1\x67\x79\x79\xa8\x50\x25\xe3\x05\xb8" + - "\x86\xf5\x65\x0e\xf5\x62\x45\x96\xfe\x58\xb5\xe8\x05\x2e\xad\x42\x89\xd9\xb5\x48\x8d\x91\xb5\x20\xca\x64\xb5\x06" + - "\x68\x12\x4a\x4c\xd6\xe2\xd1\x21\x98\x99\x04\xd7\x8d\x21\x55\x89\x47\x81\x20\xd0\xb8\xf6\x40\x66\x11\xd5\x19\x88" + - "\x79\xf5\x66\x3c\x87\x4a\xba\xa4\x8b\xc3\xc2\xa1\x34\x22\x3d\x0a\xaa\x37\xaa\x0c\x57\x1d\x51\xec\xd0\x1e\x59\x6a" + - "\xe9\x09\x56\xa3\x55\xe6\x52\x23\x17\x55\xb4\x46\xa9\x31\xa0\x46\x44\x9f\xb0\x56\x02\x95\x72\x51\x05\x35\x7a\xe6" + - "\x3f\x3d\x59\x16\xa6\x33\x5a\x7e\x1a\x8f\x6e\x19\x70\xe3\xea\x65\x30\x8e\x68\x98\x46\xd2\xab\x64\x61\x49\x74\xc8" + - "\x61\x9e\xa6\x0e\x3d\xe3\x09\x72\x50\x35\x93\x45\xb8\x96\xf1\x52\x87\x92\x89\x42\x4b\x8f\x90\xda\xcc\x22\x97\x86" + - "\x39\x48\x62\xb5\x49\x0d\x1a\x6a\x43\xd4\x0b\x69\x1d\xd0\x2e\x07\xc9\xa1\x36\x8f\x6e\xc1\x24\x44\xb8\xce\xc0\xac" + - "\x44\x1e\xd5\xd2\xc1\xc6\x35\x4b\x67\x1a\x51\x2c\x48\xd0\xab\x57\x41\x69\x93\xf6\x69\x6a\xa8\x15\xc8\xe8\xcb\xb0" + - "\xe0\x6d\xc4\x69\x32\xfb\x9d\x76\xc9\xf9\x05\xbb\x78\xcc\xdf\x6e\x8d\x48\x99\x45\x1f\x86\x40\xd3\x66\xbd\x51\xdb" + - "\x91\x68\x45\x66\x8c\xca\xca\xa3\xb4\x32\x72\xe7\xc4\xaf\x5a\xf6\x9c\xf8\xdc\xaa\xb4\x38\x32\x29\x43\xff\xad\x67" + - "\xf0\x94\xb3\x18\x1b\xbf\x90\xbd\x27\x2c\xa3\xb2\x73\xc1\xc9\x63\x82\x26\x8f\x4f\x20\xf6\x80\x64\x6d\xf1\x22\xa1" + - "\x0b\x70\x1f\xd4\x89\x6f\xb7\x3a\x01\x91\x35\xb9\x0f\x6a\x8c\x1c\xb2\x98\xf6\x41\x9d\x7a\x6a\xbc\xcb\xdc\xf9\x86" + - "\x1c\x64\xf4\x28\x06\xcc\xac\x1b\x86\x06\x45\x09\xc3\x4e\xde\x16\xa2\xc1\x8e\x5b\xb0\x07\xb9\xbf\x09\xfb\xa6\xba" + - "\x87\x4e\x7a\x13\xb6\x56\x37\xec\x04\x3d\xd2\x7d\x65\x4f\x80\x8c\x47\xd7\x77\xc4\xf5\xc8\xa0\x1f\xde\x80\x7c\x4b" + - "\xcd\xa0\x17\xde\x80\x0c\x6b\xd6\xfa\x40\xec\x91\x5e\xdf\x09\x80\xa0\x98\x2c\x6f\x45\xf6\x1b\x0b\x5b\x8e\xb7\xd5" + - "\x8c\x21\x9f\x34\x51\x18\xc6\x95\xcd\x30\x87\x9c\x16\x59\x4b\x3b\x35\x33\x89\x39\x23\x71\x67\xfc\x4e\xb0\x04\xde" + - "\x05\x3d\xd2\x92\x4b\xde\x4e\xb2\x62\xcc\x43\x18\x59\x5f\x5a\xda\xf9\x0c\xd9\xa9\xb0\xb3\x95\xe8\x39\x6e\xf4\xac" + - "\xe8\x58\xea\xc1\x55\xff\x4f\xb2\x4f\xf6\xf4\xfa\xb4\xf6\x06\xeb\x2b\x24\x7b\xee\x90\x13\x8f\x3d\xd1\xf0\x63\xf7" + - "\x5a\xd3\x1f\x5a\x4a\x9a\xf4\xc4\x63\x82\xbf\xee\x8b\x18\xa0\x52\xf6\xee\xf4\xbe\x7a\xf9\x49\xbc\x16\xc1\xbf\x36" + - "\x24\xcb\x2b\xce\x89\x4a\xde\xc8\xf2\xf7\xc0\xbe\x51\x3b\x3d\x7f\xd9\x5a\xfd\xc0\xb3\x34\xd9\xd5\x1d\x72\x99\xc9" + - "\x4e\xd7\x07\x1b\xb2\xe9\xdd\x2a\x0c\xf4\x11\x4d\x65\xc0\xdf\xb8\xf8\xf1\x7c\x29\xba\xbc\x66\xa9\xf3\xc4\x97\x5e" + - "\x59\x38\x19\xe4\xa9\x03\x93\x33\xf9\x2c\x05\x26\x20\xa4\x8c\x8b\x89\x17\x08\x27\xf7\x57\x7f\x85\xa2\xba\x74\xf5" + - "\xa5\x73\xc8\x45\xdb\xf8\xdc\xd8\x59\x8a\xc2\x9f\x19\x59\xad\x54\xc8\xf3\x50\x35\xe7\x38\xad\xca\xae\xa9\x5c\x99" + - "\xef\x1c\x0f\x3b\x2c\x96\xc6\x1b\x01\xeb\xfa\x85\xa5\xa8\x7e\x13\x5f\xae\x5c\x48\x56\x96\xab\xfc\x4c\x8e\x14\x66" + - "\x81\x0a\x4f\x91\x34\x96\xff\xaa\xa7\xd1\xff\x7f\x23\x9f\x55\xb2\x71\x67\xc0\x1a\x41\xc1\xde\xa1\x10\x7c\xb1\x16" + - "\xc2\x37\x24\xa2\xe9\x6c\xd5\x4e\x22\x9b\xc1\xde\xac\x9b\x70\x8f\xf6\xcb\x15\x23\x74\x07\x7a\xfa\xc3\x15\xef\xde" + - "\x49\x7a\x6f\x26\xc6\x0a\x31\x05\x03\xaf\x38\x40\xc2\x2c\xaf\x31\x39\xd0\xad\x36\x96\x9c\x89\xbf\x02\x64\x3e\x61" + - "\xa9\xbc\x58\xca\xf5\x77\xef\x58\xf9\x2c\x99\x4f\xa2\xd9\x66\x35\x89\xe6\x8b\xc5\x24\x9a\xae\x6f\xe9\xca\x10\xb2" + - "\x68\xbb\x77\xcc\xa0\xd7\x05\x49\xe9\xa9\x2a\x32\x23\x03\xf3\x76\xcb\x5b\x5e\x93\x34\xef\x5e\x77\xd1\x0c\xa5\xd1" + - "\x2f\xc3\x98\x79\xf2\xd1\x71\xd4\x2e\xa4\x78\x13\xfa\x8f\x59\xce\x9e\xe0\xc8\x7e\x9a\x44\x7a\x41\x43\x49\x56\x95" + - "\xc5\xeb\x4f\x93\x48\xfa\x14\x03\xb0\x0e\xeb\x8e\x12\x88\x14\x91\xfe\xc6\x43\x1e\xc6\xaa\xe2\x6d\x12\xa9\x54\xcb" + - "\xaa\x8b\x49\x51\x54\x5f\xa9\xdc\x04\x95\xef\x24\xd9\x38\xfe\x29\x04\x9b\xc0\x49\x5d\x53\xd2\x90\x32\xd5\xd3\xfb" + - "\x22\x4b\x78\x89\xd1\xbb\x5b\x19\x7d\xce\x53\x1a\xd7\xf9\x0b\x2d\x62\xf6\xf8\xd1\x2e\xe1\x6b\x7a\x50\x5d\x46\x3a" + - "\xaa\x4f\xdb\x5d\x7e\x36\xbe\xf4\x30\xfd\xd7\xb8\xa8\x52\x52\xe8\x65\xe7\xaa\xec\x4e\x3f\xa9\x35\xa6\x66\x7c\x17" + - "\x4b\x99\x16\xec\xdd\x94\xab\x04\x3b\xe3\x10\xb7\x67\x93\x7a\xdf\xe5\x6e\x08\xce\x11\x33\x1d\x7e\x32\x1a\x93\x1e" + - "\x58\xce\x34\xa3\x68\x32\x22\xb0\xda\xb3\x2d\x13\xbc\xc8\xa8\x77\x00\x32\xa8\xf3\x3a\x55\x71\x84\x88\x2b\xc1\xc5" + - "\x55\x1c\xc7\xc4\xa5\x43\x38\xc4\x65\x93\x71\x8b\x4b\x87\x1d\x17\x57\x71\x74\x8a\xcb\x28\xc2\xc5\x55\x1c\xbd\xe2" + - "\x2a\x8e\x88\xb8\x96\x6b\x3d\xe9\x1c\x1b\x67\x8c\x7d\xe0\x72\x6a\x01\x29\x95\x84\x42\x78\x63\x93\x68\xca\x9c\x2f" + - "\x63\x03\x1d\xa6\xf7\xc2\x9e\xbf\xba\xea\xa5\x12\x59\x57\xc4\x96\x01\xaa\xc6\x61\x51\x00\x43\x76\x72\x81\xa2\xa7" + - "\x0a\x73\xbc\xfc\x92\x58\x0b\x02\xf1\xee\x8c\xe3\x01\x21\xc5\x09\xee\xb8\xab\x72\x99\x7f\x1c\x05\xeb\x75\x93\xb7" + - "\xc0\xf2\x60\x65\xdb\x10\x7c\xb0\x12\xc0\x1f\x87\x82\x42\x5d\xaa\xc5\x80\x9e\xb7\x6f\x8e\x48\xf5\x93\xd5\x97\x9f" + - "\x40\x97\x42\xaa\x31\xd2\xff\x82\x53\x93\xf1\x00\x6d\x70\xe5\x4e\xbf\xad\xc3\xf0\x07\xdf\x02\xba\x52\x70\xfc\x69" + - "\xa4\x45\x9f\xec\xf6\xb9\xf2\xb6\xcb\x63\xba\xe0\xbd\x3a\x6b\x16\xc4\xf5\xc7\x0f\x28\x54\x44\x9f\x7b\x14\xf6\x54" + - "\xe2\xe0\x8b\x26\x38\x2b\x5b\x34\x07\x5c\x9d\x38\x2f\x05\xdc\xf8\xa7\x6b\x53\x84\x80\x25\x4d\x7a\xe0\x3b\xe6\x20" + - "\x98\x1d\xd1\xf7\x38\x02\x66\xf5\x47\x00\x63\xaa\x66\xdd\x94\x58\x9f\x7d\x6c\x09\x18\x1f\x57\xc0\x34\x79\x98\x82" + - "\x4e\x4d\xcc\x4f\x1c\x59\xd6\xcc\x58\xb8\x69\xeb\x49\xf3\x20\xed\x06\x1f\x31\x9e\xea\xc0\xf4\xe2\x29\x16\x13\xad" + - "\x91\x92\x31\x41\x92\x8e\xcb\xaa\x34\x3c\x38\x35\x3f\x1a\xe7\xfd\xd0\x0c\xbe\x73\x74\x0d\xba\xc2\xf3\x23\x6b\x51" + - "\x07\x7f\xc5\x88\xa3\x80\x46\x2c\x80\x8f\xa2\x1c\x50\x94\x30\xcc\xf7\x35\xcc\x9c\x3d\x94\xdb\x61\xfd\x2d\xa4\x70" + - "\x2d\x2f\xc1\x82\xf1\x10\x06\xb2\xf2\x40\x89\xa5\xc5\x95\x02\x84\x83\xc3\xe4\x5d\x1b\x2c\xf3\xb7\xc9\x56\x57\x5f" + - "\xe1\x30\x41\x57\xe9\xd1\x7a\x72\x41\x7b\x92\x6b\x78\x3d\x0c\xa1\x2e\x8e\xe0\x23\xfd\xb7\xc6\xb5\xd8\x51\x3f\xe2" + - "\xbf\xf9\xb4\xb8\x1f\xdb\x86\x16\x1b\x84\x1d\x9d\x50\x1c\x3d\x9a\xf3\x1b\x0a\xe3\x5a\x96\x82\xe5\xe3\x21\x8c\x2b" + - "\xb3\x09\x15\xa6\xcc\x26\x16\xa6\xcc\x92\x77\x4d\x99\x1f\xee\x22\x62\xc9\xd1\x89\xb4\xf1\x81\xd2\xac\x5f\xd5\x3b" + - "\xbc\x33\x14\xd4\x16\xb8\x31\x0f\x2c\xe7\x53\xe0\x16\x6a\x2d\x75\xd4\x07\x9d\xd6\xc1\x79\x82\xd3\xca\xcf\x71\x5e" + - "\x66\xf4\x65\x17\xcd\xf1\xf5\x83\xbc\xfe\xb9\xd4\x1f\x42\x5d\x60\xd1\x4b\xf9\xd1\x7e\xfe\x8d\x49\x97\x3b\x85\x31" + - "\x7d\xa6\x65\xd7\xea\x07\x7a\xe5\x68\xf9\xe4\x69\x95\xbc\xb1\xba\xd6\x39\x19\x53\x46\x35\x9f\x04\xd0\x96\x96\x2e" + - "\xd4\x6a\xb3\xfe\x93\x2f\x74\x41\xdf\x1e\xfd\x3e\x78\xbb\x7a\xb1\x60\x48\xf9\x3a\x7a\xf1\x89\x16\x35\xf7\xdc\x4d" + - "\x44\xe6\xff\xa0\x1f\x81\x3b\x07\x4b\xed\xd5\x1d\x56\x28\xfd\x3c\x94\x1f\xe8\x74\x19\xf8\x9a\x93\x08\xbc\x32\xec" + - "\xd1\x39\x9d\x67\x4b\xef\x8d\x28\x28\x47\xfd\x6d\xc3\xd3\xa3\x8c\xba\x83\xb6\xfc\xc1\xbc\x37\x87\x69\xd7\xf5\x4b" + - "\xf4\xdd\x7a\xb3\x9f\xad\x1f\x6e\x8e\xc9\x02\x1a\x68\x83\x60\x10\x85\x64\x99\xb8\x4a\x66\xcb\xdd\x79\x7e\xf7\xd1" + - "\xd5\x5b\xa3\xf2\xd3\x07\xa0\x1b\x59\x3e\x1c\x67\x0e\x2f\xeb\xbb\x3e\xbc\x86\x62\x74\x78\xa9\x62\x6b\x78\xa9\x12" + - "\x38\xbc\xf4\x8f\xe6\xf0\x12\xa5\xf8\xf0\x32\x0b\xf1\xe1\x25\xa1\xec\xe1\xa5\x95\xb8\x87\x97\xf6\x5e\xa2\xce\xf3" + - "\xd8\xf0\xe2\xa8\x7f\xbf\xe1\x85\x32\xea\xdb\x13\x59\xcd\xee\x35\xbc\xd2\x84\xcc\xd6\xfb\xb7\x0d\x2f\x4e\x03\x6d" + - "\x90\x7f\x78\x0d\x72\x77\x9e\x40\x45\x86\x57\x60\x47\xe3\xc3\xcb\x46\xa6\x4d\x53\x35\xd6\xe0\x32\xbe\xea\x43\x4b" + - "\x16\xa2\x03\x4b\x14\x5a\xc3\x4a\x7c\x87\x83\x0a\x7e\x32\x87\x14\x2b\xc3\x07\x94\x5e\xa4\x0f\x27\x08\x01\x87\x92" + - "\x4e\x76\x64\x28\x69\xcf\x84\x42\x4e\xc7\x06\x12\x47\xfc\xfb\x0d\x24\x84\x4d\xf7\x30\xe2\xef\x9b\xde\x69\x18\xd1" + - "\x87\xe5\xc3\xe2\x8d\xc3\x88\xd1\x40\x9a\xe3\x1f\x44\x83\xcc\x9d\x47\x6d\x91\x41\x14\xd4\xc5\xf8\x10\xb2\x51\x15" + - "\x18\x57\xa5\xff\xed\x21\xc2\x2f\xa1\xae\x74\x07\x52\xc7\x97\x8f\xfc\x8f\xd3\x51\x31\xa0\x61\xb0\x39\x8e\x2a\xc0" + - "\xf0\xe9\xca\xb9\x07\x00\x8f\x1c\x6c\x16\xfd\xbf\xc0\xe4\xd6\x8c\x4f\x31\x9c\xcc\x7d\x0d\x77\x10\x1a\x8d\x37\x3b" + - "\x82\xcb\x72\x9f\xc9\xae\x09\x0e\x47\x4f\x5d\xc2\xc1\x97\x4f\xf3\xdc\x5a\x0d\x5c\x51\xe2\xb5\xa1\x24\x80\x0a\xe3" + - "\xa8\xec\x04\xdb\xb5\x8c\x41\xaa\xc6\x9a\xda\x03\x68\x0d\x27\xbe\xf5\x16\x86\xb0\xef\x4a\xed\x3c\x35\xcc\xa7\xe1" + - "\xa2\xf0\x84\x74\x14\x92\x84\x49\x43\xd7\xe6\x16\xfc\x58\xf4\xb5\xd2\x02\x33\x9c\xf6\x7d\xd8\x7f\x19\x57\xd5\x61" + - "\x09\x7d\x37\x76\xd4\xc4\x85\x30\x05\x5a\x6f\x45\x7f\x7d\x24\x1d\x3b\x66\x48\x0d\xd6\x06\x84\xda\x19\xc7\x77\x94" + - "\xd0\xc4\x15\x06\x1b\xee\x98\x86\x6e\xc3\x94\x11\x33\xf6\x44\xc1\x4b\xb2\x56\xa7\x61\x65\xd0\x75\xb0\x80\xa4\xbf" + - "\x81\x17\x60\x6f\x17\xc3\xb0\xff\xd8\x73\xc1\xc9\x4d\x8c\x83\x1d\x3f\xb8\x99\xba\x31\x42\x3b\x10\x05\xdf\x2c\x0e" + - "\x7e\x38\x2c\xc8\x80\x6b\xec\xdb\xe3\x0f\x93\x0f\x3e\x0a\xac\xb7\x50\xbd\x5d\x1c\xaa\x2e\xe0\x79\xaa\x5b\x5b\x65" + - "\x84\x0a\xc7\x1a\x39\x5b\x4e\x17\x8b\xd1\x17\xe7\x42\x6b\x6c\xcf\xe3\x35\x1a\x47\x04\xa4\xb5\x1d\xdb\xc7\xd5\xcf" + - "\x18\x3a\xb7\x71\xf5\x73\x87\xd8\xce\xae\xe7\x2c\x22\x1e\xd3\x43\xee\x68\xf8\x77\x88\xe3\x73\x1b\x77\xd5\x25\x3d" + - "\xc5\x24\xe5\xe6\xe5\x4c\xca\xbc\xbe\xf4\x26\xa6\x2a\x79\x98\xd2\x57\x6a\xec\x30\x43\xf7\xf5\xd2\xd2\x26\xe6\xa1" + - "\xe7\xe1\xfc\x23\x3b\x60\xe6\x28\x69\xf1\x02\xf4\xe3\x35\x27\x2c\xfd\xaf\x3e\x0e\x6f\x51\xf6\xfd\x2b\x6e\xa9\x4f" + - "\xc5\x39\x5b\xf0\x69\x07\x3f\x81\xdf\x3b\x0d\xa3\xd7\xba\xe1\x23\xc4\x01\x9e\xff\xaf\x7e\x3e\xd7\xe2\x11\xfe\x1e" + - "\x2e\x89\x19\xa7\xd3\x99\x4a\x65\x34\xad\xd8\x61\xaf\x52\x8f\x08\x0f\x82\xd0\x9a\x6d\x5e\x36\x33\x3a\x23\xfc\x94" + - "\xe4\xa2\x7e\x61\xcd\x36\x16\x25\x33\xcf\x73\xae\x1e\x14\xc8\x35\xd8\x89\xdf\x77\xe5\xd8\x11\x3d\x39\xc6\xb1\xe8" + - "\xf8\x23\xbe\xa9\xcd\x46\x6f\x5e\x74\xbd\xd6\x91\xa2\x3e\x91\x0f\xe2\x94\x60\xf4\x43\xb4\xd6\x0f\xd6\x86\x3c\x0c" + - "\xab\x1d\x33\x9c\xae\x57\xa0\x2d\x71\x46\x0f\xe4\x52\x74\x58\xef\x79\x4e\x23\xeb\x6b\x2d\x70\x09\x10\x90\xd4\x3a" + - "\x57\x7d\x04\x7a\x23\xbf\xed\x40\x92\x0e\xf8\x19\x03\xe5\x17\x17\xa3\x69\x55\xd3\xf2\x69\x9a\x35\x55\x9d\x55\x5f" + - "\xfb\xf9\xfb\x78\x2c\x28\x84\x54\x8f\x51\x8f\x35\x89\xae\xfb\x7f\xd8\x0a\x32\xeb\xff\x85\x36\x6c\xa7\x3e\x86\xb2" + - "\x86\xeb\x38\x56\x9f\xae\x6f\xd6\x67\x5c\xd0\xaa\x54\x33\x23\x56\xf1\xce\x8b\x8c\xf5\xc1\x50\x38\xdc\x22\x05\xc5" + - "\xda\xa9\x59\xf4\x3b\xca\x2f\x28\x46\x19\x1e\xca\x51\x8e\x41\xf1\x18\xba\x50\x21\xc7\x50\x95\x08\xa3\x00\x20\xb5" + - "\xcc\x18\xa4\x10\xe2\x08\xd8\x2e\x98\xe0\x2e\x90\x20\x6b\xa9\xe7\x9a\xf2\x15\x83\x39\x9a\xee\x49\x76\xa4\x9a\x99" + - "\xf0\x3e\xc0\x0d\x69\xd4\x4d\x7e\x26\xcd\x6b\x30\xf2\x86\xec\x37\x08\x67\x73\xba\xce\xc8\x12\x21\xac\x2b\x94\xfc" + - "\x08\x55\x57\x7c\x33\x2d\x8d\xfc\x8c\x81\x8e\x5b\x1a\x01\x69\x58\x1a\x77\xc3\xe6\x0f\xeb\x64\x9b\x60\x0d\x4b\x96" + - "\xd9\x26\xb8\x61\x21\x96\x46\x67\x6d\xdc\xd2\xc8\xfa\x0c\x4b\x63\x7e\xc6\x05\xed\xb0\x34\x66\xf1\xce\x8b\x8c\xf5" + - "\x81\xcb\xd2\x88\x62\xcb\xd2\x58\xdf\x51\x7e\x9d\x96\xc6\x2a\x47\x39\x76\x5a\x1a\xbb\x7c\xc4\xd2\x08\x84\x51\x80" + - "\x00\x4b\x63\xe8\xfc\x08\x58\x80\xa5\x31\x46\xc6\x18\xd8\x88\xa5\xb9\x7e\x48\x63\xf6\x06\x50\xf1\x66\xef\xeb\xc9" + - "\xc8\x0d\xc9\xb0\x91\xb9\x4a\xf7\x0f\xab\x14\xe1\x6f\x99\x12\xba\x4c\x11\xc2\xba\x66\xc9\x8f\x50\x87\x65\xd6\x20" + - "\xc3\xe4\xc8\xcf\x18\xe8\xb8\xc9\xd1\x73\x2e\x8d\x37\x6c\xb9\xdc\x66\xcb\x25\xb6\x85\xbb\x7d\x58\x2e\xb6\xa1\x0d" + - "\x0b\x31\x39\xce\x74\x50\x0e\x93\x23\xeb\x33\x4c\x8e\xf9\x19\x17\xb4\xc3\xe4\x98\xc5\x3b\x2f\x32\xd6\x07\x2e\x93" + - "\x23\x8a\x2d\x93\x63\x7d\x47\xf9\x75\x9a\x1c\xab\x1c\xe5\xd8\x69\x72\xec\xf2\x11\x93\xa3\xd2\x62\x8d\x00\x04\x98" + - "\x1c\x43\xe7\x47\xc0\x02\x4c\x8e\x31\x32\xc6\xc0\x46\x4c\xce\xf5\x43\x1a\x33\x39\x80\xca\xa8\xc9\xc9\xcb\x43\x15" + - "\x6a\x6f\xf6\x69\x82\xee\x5a\x2d\xd7\xfb\x87\x8c\x98\x54\x75\x9d\x62\x5f\xa0\xea\xb2\x3c\x53\x16\x88\xa1\x2a\x20" + - "\x67\x95\x6f\x14\x5f\xd1\x88\xc5\x6c\x9f\x64\x2b\xcc\xa8\xaf\xb7\x64\x9f\x8e\x37\x22\xc4\xaa\x28\x7e\xc6\x0d\x0a" + - "\xab\xc4\xb0\x26\xda\x37\x44\x8c\x0e\x3b\xa2\x95\xd9\xa2\xc5\x2d\x88\x5e\xa2\x9b\x8f\xbe\xcc\xb2\x1d\xfa\x47\x9b" + - "\x3b\xa7\xd5\xd0\x0b\x6d\xfe\x2c\x7b\x81\x16\x29\x0e\x5d\x23\x8d\x67\x41\xf3\x95\x06\x98\x09\xa8\xad\x3e\x98\x00" + - "\x03\x01\xb4\xda\x4f\x6a\xcc\x34\x5c\x37\xfa\x50\xbb\x30\x90\x18\xb5\x0b\xf2\xf0\x46\xd8\xa8\x3a\x24\x24\x5b\x62" + - "\xcc\x51\x4a\xe6\x8b\x35\x42\x58\x57\x1c\xf9\x11\x76\xbc\xcc\x11\x66\xb8\x22\xf2\x33\x06\x3a\x6e\x29\xf4\x0c\x6b" + - "\xe3\x0d\xa3\xe9\x76\x33\xc3\x16\x9c\xd9\xea\x61\x35\x9b\x87\x36\x2c\xc4\x68\x38\x93\xbf\x39\x2c\x87\xac\xcf\x30" + - "\x1e\xe6\x67\x5c\xd0\x0e\x13\x62\x16\xef\xbc\xc8\x58\x1f\xb8\x6c\x89\x28\xb6\xcc\x89\xf5\x1d\xe5\xd7\x69\x54\xac" + - "\x72\x94\x63\xa7\x2b\x62\x97\x8f\xb8\x22\x2a\x09\xde\x08\x40\x80\x8d\x31\x74\x7e\x04\x2c\xc0\xd2\x18\x23\x63\x0c" + - "\x6c\x2c\xce\x72\xf5\x90\x46\xa3\x2d\x03\x95\x51\x93\xc3\x93\xb7\x05\x5a\x9c\x6c\xbb\x5a\x2c\xd1\x81\xb9\x5c\x1c" + - "\x16\xc4\xa6\x6b\xc4\xef\xf8\x37\x2d\x50\xc8\x73\xc7\x21\x60\x66\x70\x0e\x66\xa3\xf3\x46\x4e\xaf\x69\x50\xba\x5d" + - "\x24\x73\xcc\xf5\x23\xe9\x7c\x3b\x5f\x85\x35\x28\x28\x9e\xeb\xc8\x03\xe8\x0a\xe7\xf2\xca\xcc\x68\xae\xfe\x15\x15" + - "\xae\x2b\x96\xab\x97\x62\x02\x77\x44\x72\x8d\x32\x23\x90\xcb\x4a\xed\x38\xae\xf1\x19\xe3\xd4\x1d\xc5\x35\x8a\x31" + - "\x5e\x1d\x6e\x8b\x55\x38\xea\xb8\xc8\x2c\x88\xfe\xf2\x90\x00\xae\xa6\xdb\x7e\xa8\x90\xf0\x2d\x1c\x03\x63\xe4\x46" + - "\x8c\xca\xd5\xa3\x16\xb3\x29\x80\xc8\xa8\x4d\x29\xf2\x92\x6f\xd3\xa3\x37\xbc\x5d\x81\x1e\xb9\x27\x9a\x98\xa4\x44" + - "\xe7\xf6\x3f\x75\x45\xea\xbf\xec\xac\x2f\x40\x1b\x3d\x02\x56\x3c\x7a\x9f\x56\xb9\x76\xfb\xcc\xc3\xba\xcd\xa8\xa6" + - "\xba\xec\x03\x48\xa1\xa9\xf5\x94\xfd\xd8\x4b\x10\x11\xb5\xca\x5a\xac\xe6\x9b\x14\xdd\x65\xbd\x94\x19\x6d\x8a\xdc" + - "\xda\xd7\x1e\xaf\xd8\x31\x04\x8d\xa2\x91\x99\x1d\xb4\x60\xa4\xaf\x90\x66\xc1\x17\x6b\x3c\x3b\xc7\xea\x90\xc7\x53" + - "\xff\x97\x64\xf3\x08\xcf\xf9\xfc\x2a\xf7\xe8\x40\xdd\xed\x19\xd6\xad\xdf\xeb\xbd\xef\x4d\x54\x50\xe9\x4b\x0b\x2b" + - "\x7d\x69\x8d\x06\xf3\xfd\xeb\xbb\xd5\xe9\x3b\x71\x6a\x27\x2b\x1b\x50\x3e\x19\xd8\xc6\xe9\x54\x3b\xc7\xcc\xfe\xd2" + - "\x75\x55\xf9\xd3\x80\xa6\xdf\xab\xa7\x2d\xed\x5c\x85\xed\x65\x7f\xce\x61\xa9\xb0\x99\x08\x7f\x07\x92\x71\xfb\xa7" + - "\x36\xc3\xb5\x43\x04\x30\xfd\x93\xdc\x6f\x9f\xce\x56\x6d\xd4\x0b\x8e\x67\x7d\x35\x32\x4e\x39\xa0\x46\x40\x20\x3b" + - "\xd3\xbc\xd4\x39\x52\x59\x80\xd2\xaa\x28\x48\xdd\x52\x5d\xfc\x70\x18\x48\x08\x49\x03\xcd\x3d\xd7\x35\x6e\x38\x91" + - "\x67\xb1\xfa\x2a\x61\xf7\x55\xf6\x1a\x00\xce\x75\xd1\x60\x43\x2e\x71\xf1\x63\x85\x52\xed\x98\xc0\x65\x9e\x5d\x98" + - "\x80\xd7\xee\x84\xb8\xcb\xcf\x79\x79\x8c\x0f\x97\x52\x1c\x15\xa2\xa4\xa5\x56\x2f\xb8\xc1\x82\x48\xd9\xd5\x66\x17" + - "\x69\x73\xa6\x0b\x24\xcf\x18\x52\xee\x47\xb6\x6b\xa8\x9b\xaa\xa6\x4d\xdf\xdb\x5c\x2c\x93\xe8\x39\x6f\xf3\x7d\x5e" + - "\xe4\xdd\xab\x5d\xdf\x18\x74\x20\xa8\xea\x2e\xd2\xd0\xce\x7f\xe8\x0c\xa6\xc5\xd4\x3a\x4e\x7f\x6c\x8d\x5b\x15\xf7" + - "\x49\x30\xf8\x2c\xd3\xb2\x7e\x89\x32\xd2\x9e\xf8\xd9\x16\x3d\x5d\xe9\x72\xe4\x5c\x95\x78\x47\x0e\x83\x92\x8d\x92" + - "\xde\xf9\x24\x62\x3f\xc5\x21\x4a\xf7\xad\x5c\xc3\x9b\xc7\x4e\x52\x25\x16\xec\x99\x96\x97\xb1\xdb\xb7\x32\x57\xa0" + - "\x38\x3e\xfb\x08\xef\xdf\xce\x12\xee\x2c\x69\x83\xf9\x71\x78\xff\xa6\xc7\x79\xd4\x33\x93\xce\xd6\x58\x86\x03\x2d" + - "\x43\xe9\x7c\xc8\x60\x89\x9c\x01\x34\xdf\x76\xe3\xf3\x40\xdb\xc9\x14\xd7\xc8\xe9\x37\x63\x81\xa5\x3c\x25\x00\x51" + - "\xe4\xf5\x2e\x1a\x32\x66\xbc\x98\x14\xd0\xf2\x91\x3c\x85\xb0\xc4\x3c\x7f\x25\x4f\x6c\x85\xe6\x33\x4c\xd4\x71\x49" + - "\x8b\x14\x72\x07\xc7\x0f\x8d\xaa\xc1\x94\xbd\x4c\xca\xf4\x17\x1e\x5d\x4d\x86\xae\x87\x17\xd8\x75\x0d\x9a\x66\xf9" + - "\x73\x2e\x53\xd0\xa9\xe9\x18\x9e\xec\xdc\x45\x5b\xd9\xcb\x98\xa9\xc4\x82\x6b\x30\xbf\xab\x5e\xdf\x53\x91\x3f\x11" + - "\x7f\x62\x4d\x36\xef\xab\x24\x41\x69\x41\x49\xc3\x1e\xac\x3b\xdd\x70\x8a\xd4\x38\x70\x85\xa6\xf8\x76\x71\xa9\x7c" + - "\x4e\xa4\x08\x71\x80\xd7\xfd\x3f\xa7\xb3\xe8\xd2\x6a\xed\xdd\x23\xbd\x22\xf9\xda\x12\xb1\x58\x50\x25\x0e\x16\x87" + - "\x72\xb8\x6c\x33\x46\xd2\x35\x6c\x0e\x0b\xa9\x11\x83\xf4\xa4\x56\xf1\x18\xdb\x43\x19\x88\xbc\xb8\x61\x50\x77\x7c" + - "\xb4\x5a\x97\x4c\x50\xc2\x4e\x21\x38\x8e\x41\x8e\xae\xe4\xdc\x47\x45\xe5\x09\xca\xba\xa9\x8e\x79\xb6\xfb\x2f\xff" + - "\xf3\x8f\x7d\xf9\x9f\x7b\xf4\x43\xd5\x9c\xa7\x7f\xca\xd3\xa6\x6a\xab\x43\x37\x3d\xf6\x36\x85\x96\xdd\x07\x5a\x32" + - "\x8e\x7f\x38\x90\xa2\xa5\x6a\xe8\x1b\x11\x20\x35\x0f\xa0\x0e\x17\x87\x26\x21\x93\xc9\x6d\x06\x84\xcd\x87\x10\x49" + - "\x5e\x79\x32\xf2\x06\x29\xa4\x13\x25\xd2\xdc\x04\x9a\x80\xf1\xc5\x03\x36\xe4\xc5\xd2\x2d\x64\xc8\xf7\x9d\xd6\xff" + - "\x61\x4c\xa7\x87\xfc\x85\xf7\x3a\x9e\xc9\x42\x3b\xf0\x8e\xcd\xb0\xdb\xad\x6a\xfd\x60\xa0\xb1\x9e\x1b\x17\xf7\xa5" + - "\x8e\xb8\xab\x34\x89\xa6\x25\x79\xde\x93\x26\x66\xdc\x89\x53\xf7\x83\xb2\x47\xc0\xa3\x4a\xab\xb2\xa3\x65\xb7\x8b" + - "\xde\xbf\x37\x1d\x20\x2c\x41\xb7\x72\x69\xcc\x8a\x35\x86\xc7\x19\xb0\xdb\xc7\xaa\x94\x7a\x31\xdc\x00\xc4\xdf\x6a" + - "\x0d\xbe\x6e\x21\xd8\xe0\x5a\x8b\xd4\xaa\x89\x15\x79\x8f\xd9\x83\x3f\x28\xb5\xa9\xd5\xef\xec\x27\x74\x87\xf5\xb0" + - "\x58\x07\xf3\xb5\xb1\xf4\x44\x6f\xc9\x97\xe7\xba\xd7\x65\xae\xbf\x25\x1c\x5c\x85\x8b\x3b\x70\xc3\x39\x6f\xac\x66" + - "\xe0\xe3\x8d\x50\xd5\xc3\x61\x08\x80\xb9\x8f\x87\x81\xc0\xe8\x0d\x56\xae\x47\x7c\x87\x16\x20\x95\x6b\x75\x5a\xdf" + - "\xf5\x30\x2f\x28\x18\x4c\xfe\x90\x80\xc6\x6a\x39\x23\xf7\xc9\x94\xe5\xf0\xd5\xee\x65\xf0\x93\xe3\x69\x55\x9b\xa5" + - "\xf6\x8d\x2a\x79\x75\x4a\x0f\x74\x74\x55\x55\xec\x49\x83\x00\xae\x70\x40\x8b\x39\x55\x60\xde\x04\x75\x74\xbc\x80" + - "\x87\x7a\x04\x3f\x61\xb4\x9f\x2c\xda\xfa\xab\xdc\x48\xbc\x88\x77\x45\x59\x75\xd1\x07\xed\xe1\x8e\x8f\xe2\x1b\x78" + - "\x47\x42\x7c\x32\x97\x46\xdf\x7e\xf3\xee\xe3\x2f\x23\xf1\x5c\xa8\x0e\xc6\xeb\x20\xe6\x6d\xc2\x31\xa4\x60\xbe\x22" + - "\xc8\x55\x57\xd5\xdc\xaa\x0c\xfc\x59\xe6\xd6\x04\x70\xf0\x32\xd4\x8c\x89\x4d\xd7\x7f\x73\x15\x59\x56\xdd\xb7\xdf" + - "\xbc\x33\x50\x0c\x36\x7b\x49\xf8\xb8\xd4\xcb\x71\x26\xc7\xb5\xcb\x84\x0d\x54\x81\xc1\x88\x85\x75\xb7\x20\xee\xef" + - "\x3f\x53\xae\x88\xb1\x08\xa4\x63\xaa\xc0\xaf\xa2\x01\x82\x17\xbf\x1e\xe0\xca\x7e\xbf\x6e\x8e\x2c\xdd\xb2\xed\x2f" + - "\x73\x34\x2d\x40\x87\xdf\xa9\xb7\xf1\x13\x8a\x65\xe4\x22\x7b\xc0\x52\xff\x3e\xb8\x8c\x0c\x4b\xed\x15\x40\x75\x36" + - "\xc7\xc8\xce\xe6\x08\x5d\x4f\x03\xff\x2e\xf7\xbe\x7c\x5c\xe9\xdb\x4f\x37\xee\x2e\x41\x57\xd2\x6d\x38\xd9\xc5\x56" + - "\x05\x27\xd4\x4a\xc4\x8b\x56\xa2\x21\x88\xc6\xc9\xa0\x9e\xe9\x6b\x8e\x91\x4c\x24\xd1\x2b\x9c\x21\xbd\x44\xcc\x65" + - "\x1e\x77\xc5\x74\xa1\xec\x65\x0a\x78\x22\xfa\xd1\x7e\x99\xc3\x78\xae\x66\x84\x53\xb3\x36\xe4\xf9\x69\x07\xa6\xe5" + - "\xa9\x20\xc5\xa1\xad\x1d\xa1\x65\x39\x31\x22\xa6\xa0\xa5\x90\x9e\x21\xb7\xc2\xed\x21\x6f\xb8\x7e\x61\x53\x41\xd0" + - "\x24\x60\x3a\x9d\x5e\xfb\xed\xb5\xd6\x22\x98\xe7\xb5\xd7\x57\x5b\x51\x83\x3d\xbf\x49\x0f\x35\xe0\x41\x33\x8d\x86" + - "\xbd\x1c\x1d\x3b\xd7\x4f\xd2\xf2\x60\xc0\x75\x3d\x74\x87\xf9\xfa\x26\x82\xb6\x4f\xf9\xcb\xaf\xdc\xd9\xb7\xcd\xe2" + - "\x3a\x63\xd7\xaa\x81\xcd\xd2\x5f\x2f\x6d\x97\x1f\x72\x9a\x21\x1b\x69\x88\x19\xe3\x1b\x6c\x05\x79\xad\x2e\x1d\x08" + - "\x86\x0c\xc7\x06\xd8\xbe\xdc\x2e\x6a\x69\x4d\x1a\xd2\x21\xd6\x4a\x55\x68\x9b\x64\xbd\x08\xb8\x90\xe3\x8f\xf2\x43" + - "\x56\x11\xe3\x8a\x52\x56\xd6\xd5\x6b\x97\x71\x54\x3b\xb2\x60\xc5\x68\x7e\xcc\x48\x47\x84\x3a\x89\xdd\xe3\xf6\x27" + - "\x6e\xd2\xf1\xdc\x28\x61\x08\x43\x56\x78\x37\x3c\x9c\x3e\xae\xad\xcb\x81\xab\x32\xb3\xb8\x77\x97\xf8\x9e\x4a\x43" + - "\xd3\x6e\x70\x50\x12\xe6\xd0\x8c\x67\x5d\x1d\xfa\x7a\x24\x2a\xa2\x14\x73\x54\xe5\x00\xe1\x1f\xd3\x82\xb4\xed\xef" + - "\x7f\x48\xab\x22\xfe\xc9\x9c\x50\x1f\x6f\xc9\x75\x7e\xb4\x13\x1e\x79\xb8\xd7\xf3\xdb\x1a\x7b\x69\xfe\x47\xec\xb0" + - "\x7a\xd9\x99\x12\x23\xd7\x92\x59\x8c\x66\x58\xf2\x42\xed\xbb\x72\x70\x38\xfe\x6e\x59\xb0\x5d\x0d\x74\x00\xa1\xcd" + - "\x0c\x80\xf5\x36\xf6\xca\x94\xdb\x7e\x96\x3d\xe0\x1e\xe6\x03\xb1\x64\x33\xac\x9c\xdf\x0e\x9e\xc4\xee\x06\x0a\x68" + - "\x73\xe3\x26\x8a\xf1\xe0\x49\x8f\xad\xbf\x2a\xe4\xd5\xdd\xbe\x78\x5c\x77\x4d\x28\xb4\x3b\x7f\xbb\x07\x08\x5c\x2d" + - "\x73\x00\x85\x2a\xed\x55\xad\xbc\xf2\xb5\x03\x3f\xcb\x1e\xf0\xeb\x95\xd6\xd5\x0c\x87\x7e\x59\x3c\xb9\x94\x16\xe7" + - "\xc6\x4d\xf4\x76\xa5\xb5\x32\xdb\x21\xd5\xa2\x29\xea\x10\xc7\x65\x94\x7c\xa0\x8f\x6d\x8d\x09\xc6\xc7\xad\xc8\xf7" + - "\x59\x75\x85\x8a\x45\x79\x6a\x8e\xcd\xb8\xf1\xed\x0e\x3c\x1f\x67\xe8\x73\x97\xe3\x07\x06\x1e\xed\x97\x2f\xf1\xe4" + - "\x53\xee\x57\xf3\xae\x79\xf5\xd2\xd9\x2c\xf4\x49\x96\x51\x4b\xe6\x3e\x32\xe9\xaa\xe0\xda\x73\xa9\xee\xd3\xa7\x76" + - "\xcf\x38\x32\x01\x7a\x01\x35\x77\x53\xcb\x80\x37\x3e\x7e\xe0\xe3\xe1\x48\x35\xe6\xe3\xe2\xd6\x38\x00\xe5\x72\x8d" + - "\x32\x06\x02\x9c\xe6\x71\x92\xc6\x52\x13\x21\x0f\xde\x8c\xd6\xd7\xde\x2c\x76\x6f\xad\x84\xc7\x29\x58\xe3\xf8\xdb" + - "\x6f\xde\xfd\xda\xbb\x16\x5e\xc1\x6b\x11\x7c\xf5\x24\xf8\x58\xcf\x82\x15\x3f\xd6\xb1\x46\x40\x20\xac\xd3\x9c\xab" + - "\xee\x20\x1a\x8e\x1d\x98\x91\xee\x40\x49\xa3\x9d\x1e\xd2\xbf\xde\xd0\xc5\xed\x91\x7e\x9f\x7c\x61\xf7\xb9\xd7\x47" + - "\xf1\xc8\x7e\xf3\x60\x56\x92\x91\x53\x19\x4e\x2f\xc8\x7d\x7e\x12\x43\xf9\xa4\xf0\x9c\x5b\xad\x18\xda\xb0\xb3\x81" + - "\x96\x0e\xfb\xcb\x68\xb1\x6f\x97\xf9\x6e\xa6\x47\xb7\x94\x2a\x27\xa7\xb3\x5d\x96\x46\x06\x1a\x21\xbd\x1e\x5b\x7c" + - "\x25\x79\xd6\xb6\x54\xc0\x11\x18\x2c\x25\xa4\x79\xce\x13\x90\x79\x2a\xf2\x90\x78\x80\x76\xae\x89\xa3\x89\x93\x4d" + - "\xa1\x8f\x53\x1a\x73\xde\x4a\x6b\x8c\x7e\xe8\x4f\x7d\x08\x38\x2c\x86\x3b\x06\x3a\x69\x70\xfe\xcc\x75\xa4\xcd\x02" + - "\x34\x98\x19\x3d\x1b\xe7\x3d\xd6\x77\xcb\x89\x36\xd8\xd5\xe2\x24\x19\xe7\x46\xfe\x05\x39\x54\xdf\xc0\x15\xa3\x11" + - "\x8f\xc9\x38\x60\xa8\x55\x57\x92\xe7\xf8\x57\x3f\x9b\x2a\x7b\xf9\x29\x3f\x1f\x85\xb1\x50\x7b\x37\x86\x92\xc6\x1d" + - "\xd9\x6b\x89\xed\xd5\x41\xa6\xc1\xe9\xcb\xb2\xcc\xc4\x90\xba\x6d\x9e\xaa\xd6\x47\x88\x31\xae\x24\xa6\xd0\x15\x7d" + - "\xa8\x8f\x1f\x81\xbb\x21\x45\x28\xfb\xff\xc9\x60\xda\x35\x26\x9c\x97\xc6\xfa\xde\x14\xff\xc1\x9b\x0e\xcf\xb0\x62" + - "\x9f\xa1\xfe\xd8\x85\xd8\xe9\x55\xe1\xa1\x4b\x6d\x16\x09\xe1\x5c\xc7\x6b\x61\x4e\x39\xb3\xa7\xec\xc9\xd1\x3b\x00" + - "\x18\x7b\xec\x87\x1e\x47\x37\x62\x7a\x86\x72\x58\x02\xd5\x29\x18\xda\x81\xa9\x9c\x85\xa0\x2b\x85\xac\x68\xe5\x7a" + - "\x0a\x6b\x84\x5e\xf8\xc1\x3d\x2b\xea\x1d\x70\x40\xcf\xd3\x64\x57\xa4\x1f\xc6\xf6\xd5\x41\x3d\xaf\x24\x90\x38\xea" + - "\x70\x38\x2f\x50\x8c\xfa\xc1\x4e\xd7\x9a\xcd\x25\x43\x44\xcb\x5d\x20\xc0\x85\x18\x05\x35\x87\x9d\xc3\xd6\xdc\xdc" + - "\x0f\x52\x7e\x5e\x83\xf6\x08\x20\x50\x83\xe1\xed\xa4\xdb\x44\x73\x95\x6c\xf0\x41\xcc\x2f\x0c\xeb\x7a\x50\xe7\x45" + - "\x81\x19\x64\x0c\x46\xc8\xc6\xaf\x0b\x12\xf8\x93\xa0\x69\xde\x48\xc2\x60\x4d\x89\x58\xdf\x35\x9b\x68\x97\x7a\x8e" + - "\xf4\x3b\x4f\xee\x43\x3e\xda\x8e\xa4\x5f\x46\x2d\xcf\x00\x65\xb4\x8d\xbf\x28\xe2\xdb\xe9\xf7\x9a\x48\x14\x68\x84" + - "\x97\x3b\x19\xbf\xdf\xcc\xe6\xbd\xd1\xd4\xdd\x6a\xe1\x0c\xa1\x8f\x4d\x44\x77\x33\x86\x23\xa3\x3d\xd0\x08\xfe\x16" + - "\x06\xf0\x57\x37\x7e\x6f\x12\x45\xb0\x2c\xc2\x0c\x5e\x47\xf6\xb1\xb8\x01\xf0\xc4\xfe\xa8\x49\xe9\xb9\xbe\xab\x81" + - "\x83\xdc\xe7\xce\xd5\x17\xf7\x87\x91\x01\x84\x9d\x09\x7a\xe3\x19\x06\x7e\x54\xdf\xb3\xd4\x83\x0f\x5b\xac\xf0\xe7" + - "\xe5\xe5\x6d\x12\xaf\x73\x7c\xd5\xd5\x03\xad\x33\xb4\x01\x12\xfc\x80\x83\xb8\x83\x00\xee\xc4\xe8\xf3\x92\x36\xca" + - "\x7b\x48\xed\x1e\xb6\x79\x98\x71\x85\x1e\x66\x14\x5f\xe5\xfa\x28\x7e\xd9\xf1\x7b\xb8\x85\x76\xe5\x58\x15\xb7\x69" + - "\x53\x15\x05\x5b\x25\xb3\xa7\x11\xcc\xab\x23\xce\x45\xc5\xd8\xb3\x5e\x09\x3f\xd0\x38\x5f\xad\x26\xd1\xf0\x9f\xe9" + - "\xcc\xfb\x0a\x99\x13\xc9\x21\x17\x75\x83\x5d\x36\xe7\xf5\x5a\xf3\x6d\x49\xd9\x7a\xcb\xc9\xba\x48\xe3\x3d\x61\x89" + - "\x1c\xb1\xd4\xee\x9f\x28\xce\xf5\x4a\xf5\x71\x17\xfd\x53\x7e\xae\xab\xa6\x23\x5c\xd4\xda\x26\x96\x59\x66\xbe\x1d" + - "\xcf\x59\x1c\x96\xc7\xa2\xf3\x01\x9a\x8b\x23\x21\x4b\x4d\x98\x02\xdb\x40\xd1\xef\x02\x19\x74\xcc\x2b\x43\x5d\x55" + - "\xdb\x30\xd2\x00\xf6\x1f\xf9\xa3\x57\x28\x1c\x67\x08\x3b\xc3\x81\x3f\x59\xa4\x29\xc9\x9b\xb9\x54\x21\xb1\x17\xf0" + - "\x06\x71\x82\xdc\x58\x22\x2f\x71\x46\x9f\xf3\x94\x4a\x25\x5b\x3e\x24\xf5\xcb\x47\x52\x66\xd1\x87\xaa\xc9\x69\xd9" + - "\xf1\xe8\x4c\x41\xca\xac\x4d\x49\x4d\x75\xfd\xbb\x07\xa3\xef\x84\xe3\x30\xb0\x3a\x4f\x12\xfd\xbd\x97\xde\xde\x93" + - "\xbc\xa4\x4d\x7c\x28\x2e\x79\xf6\x84\xd4\xe4\x02\xe1\x16\x8b\xcd\xe0\x0a\xc4\x8b\xff\x84\xd8\xba\x7b\x3f\x2b\x74" + - "\x97\xf6\xbc\xa5\x41\x98\x03\x85\x3e\x61\xa5\xa9\x25\x50\xf7\x5f\xb0\x1b\xfa\xe6\x09\x68\x66\x19\xaf\x33\x68\x46" + - "\x15\xc8\xae\xae\x77\xb0\x60\x2a\xf7\x0b\x7e\x57\xd2\xbe\xcb\x68\xa6\x1d\x58\x24\xd7\xf1\x1e\xc2\x48\x78\x83\x24" + - "\x86\x75\x0d\x12\x15\x2f\x3a\x20\x7f\x31\x2f\x7f\x62\xe1\x6e\x9d\xea\xcc\x8a\xae\xf5\x54\xf7\x4d\x6f\x10\x90\xe8" + - "\xa0\xe9\xca\x0c\x71\xeb\x95\x88\x5b\x87\x1c\xc9\x9a\x27\x56\x3b\x58\x8d\x70\x81\x39\x7c\x1c\x89\x73\x63\x84\x54" + - "\xd4\x14\x75\x12\xc3\xba\xf7\x69\x18\x51\x3a\x43\x8a\xbf\x27\x73\xd0\xea\x70\xc0\xd4\xd9\x66\xc3\x52\x02\x78\x15" + - "\xc4\x77\x33\x92\xa9\xb1\x26\xfa\x2d\xd8\x87\x87\x2e\xee\x83\xf6\xc9\x70\xc5\x0c\xcd\x90\x3b\xea\xb7\xdf\x22\x7f" + - "\xc3\xeb\x4f\x9a\x04\xbc\x39\x46\x74\x59\x4d\xf3\xb4\x2a\x63\xe9\xef\x3a\x53\x2f\xcd\xe7\xfa\x5b\xf6\xf8\xf9\x04" + - "\x7b\x68\x99\xb5\x7c\xd2\xeb\x83\xa2\x5e\x5e\x6b\xf6\x40\x6f\x9b\xab\x1e\x4b\x33\xe4\x76\x96\xdc\x58\xd8\x4c\xfb" + - "\xb1\x16\x1b\x9b\x44\x02\x12\x6c\x3d\x69\x2f\xb8\xe9\xe3\xd5\x7a\xed\xd4\x35\x3c\x35\xc7\x41\x35\x67\x63\x36\x47" + - "\x6d\xb2\xa0\xd7\x9d\x07\x7d\xe6\xd6\xfe\x11\xac\x26\x94\x33\x6a\xfa\xb2\xf6\x43\x93\xa3\xca\xa9\x74\xf0\xed\xbe" + - "\xaf\xb3\x41\x66\xba\x80\xc1\x58\xb9\x50\x58\x8f\x0c\xaf\x49\x6a\xa7\x67\xe4\x3d\xa4\xb9\xb2\x09\xa3\x1c\x80\x00" + - "\x01\xd2\x69\xe1\x24\x4c\x5b\xeb\x07\x96\xb1\x3d\xde\x08\x57\x0e\xcf\x6b\x57\x97\x52\xb3\xcd\x59\x46\xa9\x7a\x62" + - "\xb7\x48\x85\xae\xac\xe5\xe8\x3b\x74\x18\x18\xe3\x40\x98\x3f\x7b\x20\xe0\x56\xf9\x50\x35\x67\xec\x50\xd2\x2a\xd0" + - "\xdc\x9a\xae\xa3\x61\x6f\xed\x99\x21\x78\x51\xeb\x8c\x0e\xdd\x6b\xf1\x3b\x91\x00\x2c\xd9\xc0\x1d\x17\xc8\x21\x84" + - "\xaf\x74\xc4\xfa\x5e\xfa\x75\xdf\x5b\xb6\x6b\xfa\x55\xde\x5b\x76\x56\x13\xfe\xde\xb2\x46\xe2\x6e\xef\x2d\x3b\xa9" + - "\x9a\xa7\x52\xdd\x80\x8e\xf7\x96\xc3\x10\x7c\xef\x2d\xbb\x28\x04\xbe\xb7\xac\xa1\xdf\xe7\xbd\x65\x9d\xe4\xf0\x02" + - "\xae\xf6\xfd\xb7\x7b\x6f\x19\x65\x47\xbd\xb7\x8c\x30\x35\xfe\xde\x32\x4e\xd2\x71\xca\x12\xa9\xe1\x4e\xef\x2d\x6b" + - "\x94\x6f\x7f\x6f\x39\xd0\xcd\xc1\xed\x8c\xbd\xe5\xe3\x1e\xcd\xe6\x75\xbb\xd1\x4d\x94\x6b\x2c\x20\x1a\x13\xd4\xa6" + - "\xbf\xc4\x13\x87\x1b\x8f\x10\xdc\xc7\xc7\xc2\x3c\xd6\x91\x60\xbd\x19\x8c\xbf\x3d\x52\x8f\x07\xb0\x46\xb9\xc0\x16" + - "\xd0\x16\x23\x4b\x6b\x47\xe1\xd7\xbb\xbb\x2b\xd7\x99\xfa\x49\x42\xc4\x0f\x01\x0e\x87\x8d\x3b\x05\x19\x79\x21\x89" + - "\x19\xbe\x51\x31\x43\x96\xed\x82\x88\xc8\xb0\xab\x11\x59\xe2\x44\x90\x85\x1f\x7d\xe9\x6c\x74\xdc\x71\xba\x22\xe8" + - "\x66\x52\x77\x78\x99\xe6\xca\x58\x57\x7a\xc3\x2f\x0c\xac\x73\xc8\xd2\x04\xea\x74\xc7\xb5\x87\xfc\x66\xda\x2a\xdf" + - "\x8c\x9f\x23\xae\x25\x4a\xe8\x7f\x23\x74\x8d\xd1\x8d\x0c\x45\xf8\xc2\x2d\x76\x62\xe9\xa1\xff\x87\x9c\x90\xa3\x9b" + - "\xfe\x9f\x83\x98\x1d\x50\xc2\x8f\x17\x3a\x71\xcc\x65\x0a\x0e\x84\x9e\xc7\x62\x07\xea\xae\x39\x49\x88\xd1\x57\xda" + - "\x13\xce\xb7\xb6\xfc\xb8\x1e\x6d\xac\xc5\xfa\xf9\xcf\xd0\xf7\x7b\xc3\x5b\xdc\xd3\x37\xf6\x88\x47\xc1\xf4\x6d\xf3" + - "\x71\x70\xfb\x90\xa8\x38\x3d\x87\x9d\x8b\x0c\xd1\x2f\x46\x5e\xcb\xf0\x18\x06\x18\xc8\xb8\xf7\x7c\xab\xbc\x50\xf3" + - "\x16\x2d\xb3\x12\xf5\xa8\xa7\x07\xb4\xd3\x8b\x6e\xdc\x31\xad\x11\x50\x63\xaf\x25\x04\xd6\x66\x84\xde\x10\x4a\x0f" + - "\x0f\x0f\x23\x94\xec\x5d\x23\x13\x42\x39\x35\xb7\x58\x1c\xd6\x6f\xf0\x64\xf0\x08\x50\xa0\x26\x58\x27\x89\xaf\x54" + - "\xe0\x40\x4f\x13\xa9\x7b\x2c\x1a\xa4\x59\x1a\x6d\x56\xb8\x8a\x98\x71\xec\xe3\x7a\x7c\x70\x1c\xc4\xb0\x4a\x63\x43" + - "\xe4\x36\xa6\x07\x5b\x75\x13\xcf\xae\xf3\x2e\x37\x12\x41\x5a\x2f\x34\xc3\xa7\x1a\x37\xb6\x1c\x18\xbc\xdb\xd8\xc6" + - "\x0c\xe1\xdb\xc8\x20\xed\x17\xf6\x31\xa4\xf7\xbd\x23\x5a\xa5\x8d\x0a\x9f\x53\x1d\x8f\x67\x80\x77\xb7\x4d\x44\x2d" + - "\x3f\x55\x40\x45\xd6\x53\x24\x4e\x80\x9b\xd8\x40\x1e\x1a\x09\x00\xf5\xbe\xfc\x33\xd6\x82\xab\x70\x30\x1f\x04\xbc" + - "\x8c\x2e\xf0\xf2\xf2\x99\x36\xe2\x88\x04\xf6\xe0\xf7\x7c\x8e\xf8\x95\xc9\x43\xff\xcf\x41\xc9\xed\x57\x6e\xb3\xfe" + - "\x5f\x08\x9a\x29\x51\x1c\xe8\xaa\x53\xad\xee\x19\xdf\x24\x6e\xf9\x95\x41\x7c\xa3\xae\xe5\x55\x98\x63\x8d\xf6\x7a" + - "\x97\x77\x68\xb7\xc3\xbb\xf4\x82\xd9\x53\xb3\x1f\xdc\x1e\x69\xee\x63\xc8\x41\x5a\xe6\xf4\x2e\x47\x00\x03\x19\xf7" + - "\x7a\x97\x4b\xf1\x2e\xf5\x5b\x74\xcd\xe9\x5d\xda\x16\x08\xc7\x1d\xd3\x9a\x30\xef\x32\xb4\xb6\x71\xef\x12\xbc\xb9" + - "\xe5\xa0\x64\x7b\x97\x26\x84\xcb\xbb\x9c\x25\xfd\xbf\x10\x8d\x30\xbd\x4b\x0f\x50\xa0\x26\x38\xbd\xcb\x40\x05\x0e" + - "\xf4\x2e\x91\xba\x5d\x33\x3b\x92\x1c\xdd\x65\xa8\x35\x27\x26\xb4\x0a\xfd\x99\x07\x5f\x03\x6f\x22\x8f\xf8\xc7\xd2" + - "\x5c\xde\x4e\x0f\xf1\x95\xae\xc3\x47\x9c\x24\xd1\xc1\x57\xb9\xc8\xe1\xdd\x88\xba\xc8\xd7\xa3\xbf\xa5\xe1\x5e\x17" + - "\xd9\xdd\xfa\x37\x76\xbf\xcb\x45\xbe\x85\xc0\x9b\x5a\xef\x77\x91\x85\x91\xbf\xda\x45\x36\xeb\xb7\x3c\xd7\x20\xdf" + - "\xc0\xe1\x9e\x7a\x8c\x2c\xea\x25\xfb\xeb\x72\x39\xca\x36\xc0\x4d\x9c\xb8\x1d\x65\x1f\x68\x88\xa3\xec\x6c\xc1\x55" + - "\x38\x98\x3b\xb5\x5c\x2e\x65\xb3\xf6\x0d\x25\x59\xda\x5c\xce\x7b\xfd\xb4\xc1\x83\x7d\xd8\xc0\xbc\x36\x10\xfa\x4c" + - "\x11\x7b\xd0\xc5\x7f\x10\x6b\xe0\x42\x9e\xb2\x70\xec\x34\x23\xe0\x9f\x8a\x7c\xb7\xa7\x87\xaa\xa1\x7a\x0b\x12\x79" + - "\x07\xca\x58\x0e\x0e\x6f\x40\x7c\xfe\x4b\x92\x90\xe4\x3d\x42\x15\x5e\xf7\x40\xd6\x62\x35\x39\xe6\x25\x3b\x09\xe8" + - "\xe6\xd5\xbe\x76\xa0\xbf\x0a\x95\x18\x59\x80\x11\xa9\x0c\xd5\x38\xa4\x82\x02\x32\xc7\x40\xff\xd2\xd6\x24\xf0\xe9" + - "\x83\x47\x57\x1e\x21\x2b\xe7\x81\x75\x78\xcb\xf5\xcc\x90\x7c\x27\xe7\xaa\x47\x80\x7c\xb7\x94\xd1\x56\x6b\x99\x21" + - "\x2c\x09\x68\xa5\x4a\x1a\xf6\x26\x63\xd8\x0e\xdb\x48\x0e\x59\xbd\x66\x90\x48\xc2\x66\x0b\x14\x2a\xae\xde\xb2\x8d" + - "\xe7\xe2\x02\x2c\xbf\xcc\xef\xf2\x6d\x67\x5b\x63\x80\xeb\x88\x14\xfa\x1e\x3c\x0d\x4e\x72\x80\xf7\x26\x5c\xa6\x61" + - "\x9f\xb1\xb6\x18\xb3\xbc\xc9\xb5\x2c\xee\x59\xc7\x11\x41\x8b\xdd\xe5\xd0\x98\xea\x69\x2d\x0d\xcd\x0d\xbb\x8c\x6f" + - "\xbd\xc6\x8b\xdf\x51\x85\xdc\x68\x8b\x41\xbc\x00\x6d\x85\xe9\x06\x58\x02\x52\x00\x88\x88\xb4\x32\x5c\x2d\x0c\x18" + - "\x67\x32\x8e\xe0\x9c\x1b\xba\x0d\xf0\x6b\x4c\x5c\x1c\x6d\xc3\x27\x3e\x0e\xb6\x2f\x24\xbb\x97\x8b\xb6\xc7\xbc\x20" + - "\x00\xd8\x58\xd6\xac\xc5\x7a\xd4\x9e\xac\x3d\xbc\x38\x4d\x8a\x5d\x3e\x6e\x55\x50\x56\x2c\x10\x84\x97\xf6\x8c\xc8" + - "\x9c\x7f\xb4\x65\xee\x49\xd9\xe6\x22\xed\x13\xb9\x0d\x30\x2a\xf2\xc5\xa8\xc8\x17\x1e\x5e\xdc\x22\xb7\xca\xc7\x45" + - "\x8e\xb2\x62\x81\x00\x5e\xc4\x50\x0a\x72\x27\xf0\x44\x7d\xae\x54\x43\x9c\xf8\xa8\x77\xc1\x60\x64\xcb\xf9\x1f\xaa" + - "\x99\x63\xde\x8f\xe8\xfc\xa5\xeb\xa0\x7f\x70\x4a\x12\x75\x60\x7e\x65\x0a\xc7\x9c\xe0\xe4\xa7\x37\x27\x2a\xe2\xb4" + - "\xa6\x25\x7d\xe9\x40\xeb\xf9\xdf\x4a\x00\xf0\xe4\x84\x81\x58\x37\xf4\x39\xaf\x2e\x2d\x44\x56\xdf\x4c\x02\x30\xef" + - "\x82\x80\x35\xad\xbd\xfe\xcd\x68\xb2\xd3\xc6\x6b\x65\xaa\xd6\xb7\x18\x66\xc9\xe6\x70\x5c\xcf\xd0\x02\xad\xff\xa7" + - "\x73\x7a\x8e\xa6\xeb\xfe\x3f\x0b\x7a\x36\x4c\xc0\x66\xf5\xbb\x47\x33\x29\xe5\x66\x2c\x29\x25\x7c\xb0\xd1\xd2\xf5" + - "\xc0\x94\x9a\x7b\xd2\x52\xf5\x06\xbb\xae\x61\xd3\xf9\x8a\x9e\x45\x1b\x09\x6f\xa4\x94\xb5\xfc\xd3\x19\x29\x1b\xcd" + - "\x36\x25\xd2\x81\x6b\x22\xdc\xd1\x73\xdd\xbd\xea\x82\xb4\xde\x1e\x19\x84\x8d\xbb\xf1\xea\x7a\xb9\x46\x7a\xec\x78" + - "\x0d\x58\xd6\x68\xf0\x3f\x9e\x1a\x7a\x18\xd6\xb4\x58\x99\x37\xab\x15\x3f\x05\xa3\x93\xae\x9b\xfc\x4c\x9a\x57\x17" + - "\x8a\xee\xf5\x68\x28\x28\x37\x7a\x99\x97\x9b\xf9\xc3\x3a\x19\xde\x1e\xe4\xe8\xed\x25\x4d\x69\xdb\x3a\x1b\x90\xee" + - "\x1f\x56\x29\x8a\x82\x72\xa3\x97\x79\xb9\x59\x2e\xb7\xd9\xb0\x04\xe7\xe8\x79\x79\xa8\x9c\xac\xec\xd3\x24\xa3\x36" + - "\x3c\xca\x07\x28\xf0\x32\xb1\x98\xed\x93\x6c\xa5\x13\xfd\x4a\x9a\x52\xbe\x13\x8e\x8d\xfc\x84\x64\x4b\x8a\xa2\xa0" + - "\xac\xe8\x65\xfe\x24\x68\xe9\x76\x33\x3b\x18\x9a\x48\xca\xa3\x1b\x23\xdb\xae\x16\x4b\x14\x03\x57\x5d\x58\xe4\x65" + - "\x25\xdd\x2e\x92\xb9\xea\xf8\x3d\xc9\x8e\xd4\x3f\xd1\xc1\xf7\xa0\xcd\xeb\x89\x8b\xfa\x25\xda\x38\x53\xd5\xfe\x9d" + - "\xad\x1e\x6a\x0d\xb0\x19\x17\x9c\xbf\x64\xf2\x08\xb2\x57\x83\xe4\x02\xed\xd5\xf0\xec\xc4\x4b\xfb\x04\x68\x88\x67" + - "\x32\x5e\x5a\x48\x73\x38\x9f\x3b\x38\xf6\xda\x3b\x48\x44\xb0\xaa\x0c\x37\xff\xf3\x7e\x86\xbb\x77\xa9\x38\xbb\x79" + - "\x47\xcf\x72\x9d\xa8\x58\x1e\x72\x15\xa9\xb5\xe9\x13\xe0\x1f\x59\x03\xfa\xa7\x5a\xbd\x3a\x48\x0a\x73\x40\x70\xf0" + - "\x4f\x00\x4b\x3f\x98\xb9\xc2\x53\x33\xe9\x3c\x6b\x01\x13\xe0\xa2\xfe\xf5\x72\xde\x57\x5d\x63\xe6\xa1\x5e\x20\x37" + - "\x96\x64\x10\x51\x26\x6e\x17\x2d\xcd\xcb\x13\x6d\x72\xd7\x3a\x19\x78\x64\x43\x55\xd3\xd3\x6c\x12\x81\xbf\x4f\x33" + - "\x28\x57\x41\xd0\x46\xab\xb1\xe3\xd5\xc8\xfd\xe1\xf9\x0c\x19\xa2\xf3\x24\xb1\x28\x3e\x9d\x1a\xd3\xdd\x57\x26\x6a" + - "\xd5\xff\xb3\x72\x0b\x00\xae\xed\xfb\xf7\x91\x21\x4d\x77\xae\x69\x20\x8a\x81\xf4\x2f\xce\xd7\xb6\xc4\x16\x5d\x9b" + - "\x36\x94\x96\x11\xcb\xbb\x30\x18\x2e\x78\x94\x58\xaf\x7f\xe8\xce\xe5\x83\xb8\x3b\xf5\xef\x5a\x66\x81\xab\x5a\x63" + - "\xe6\xa9\x90\xcf\xe7\x1b\x6b\x9b\x35\xb8\x53\x38\xda\xe3\xb0\xd7\xd6\x0b\xfd\x36\x5d\x77\xba\x9c\xf7\x25\xc9\x0d" + - "\x27\xd5\x5e\xa3\xe0\x67\xc6\xe7\xd8\x2d\x55\x23\xb3\xe4\xdb\x17\x34\xc6\x43\xf9\x6c\xe7\x45\xd8\x4b\x0e\x19\x4d" + - "\xe7\x6d\x44\x49\x4b\xe3\xbc\x8c\xab\x0b\xbf\x5e\x57\x05\x02\x8e\x43\xd9\xc2\x62\xd9\x3f\x27\xd1\xf0\x05\x64\x03" + - "\x85\x56\x43\x5e\xf6\xd0\x0c\x03\x48\x2e\x43\x06\x0a\xea\xe1\x5a\xf0\x6d\xb0\xcd\xc3\x27\x67\x62\x4d\xdd\x3b\x1c" + - "\x78\x9d\xa6\xa4\x56\xa1\x78\x78\x37\xfd\x11\x3f\xf1\x44\x0a\xda\x74\x46\x44\xc8\xbf\xd1\xf1\x86\x1b\xe6\xbc\xb2" + - "\xd3\x12\xbf\x59\x82\xdb\x2a\x8e\xc3\xff\x67\xd8\xec\x32\x5d\x05\x0d\xfa\xa9\x9e\x08\x84\xa7\x4b\x81\xde\x1f\x31" + - "\xc0\x3f\xd5\x16\x47\x2b\x83\xeb\x38\xcb\xdb\x73\xde\xb2\x65\xa3\xa4\x2e\xbf\xb1\x6c\x39\xbf\xd8\xf9\x96\x16\x3e" + - "\x22\xd1\x34\x2d\xaa\x16\xa7\xc5\x8b\x46\x9d\x05\xe1\x36\xc9\x8b\x08\xd2\x46\x7b\xe4\xa8\x79\xf9\x4a\x1b\xd2\xcd" + - "\x7a\xe1\x5a\xde\x66\x87\x43\x92\x61\xf7\x0d\xb2\x35\xdd\xa6\x6b\x9c\xba\x7b\x0e\x48\xb7\x74\xbe\x5f\xe0\x58\x66" + - "\x1f\xab\xd5\xca\x7e\xb5\x1c\x3c\x50\x0e\xa4\xd6\x07\x83\xff\xbe\x49\x1e\x5c\x87\x33\xb2\x2d\xcd\x0e\x58\x64\x79" + - "\x9f\xd2\x87\xc3\x0c\x21\xed\x6e\x01\x59\xd3\x19\xc5\xb8\x71\xb2\xbf\x5c\xcd\xd7\x5b\x1d\x01\xae\x2c\xd4\x51\x6d" + - "\xb2\xce\x16\x7b\x97\x11\x4d\x0f\x0f\x74\x81\xb4\xe0\x40\xe8\x3e\x4d\x71\xea\xee\x46\x1c\x36\x74\xb6\x5f\xe1\x58" + - "\xae\x76\xac\xd7\xab\x99\xd9\x0d\x60\x4d\xa2\xe4\xb3\x5d\x2e\x97\x73\x57\x33\xe6\x19\xcd\xb0\xad\x8f\xbe\x11\xd9" + - "\x0c\x25\xee\x6e\x05\x5d\xee\xb7\x69\x82\x22\xb9\x1a\xf1\xb0\x5c\xac\x16\x72\xad\xf9\xcf\xdf\x7e\x23\x67\x99\x2f" + - "\xf4\xf5\xd0\x90\x33\x6d\xa3\xba\xa9\x8e\x0d\x6d\xdb\x78\xcf\xd2\xe2\x34\x79\x4d\xf9\x70\x39\x34\xd5\x39\xfa\x05" + - "\x34\x6a\x18\x9a\xcb\x84\xfb\x02\x8c\x6a\x67\x2d\x5c\x07\xc0\x21\xc5\xcb\xbf\xf3\xea\xab\xbf\x57\xcd\x7f\x8f\x6a" + - "\xa7\xb2\x2a\x06\x0f\x33\x26\x78\xa6\x9b\xc0\xb4\xdd\xbe\x7d\xf5\xc7\x80\xfb\xf7\x73\xe4\x3d\x5d\xef\xbd\x7a\x14" + - "\x41\x05\x2c\x81\x4c\xcd\xa0\xe6\xe3\x90\x12\x85\x4d\x7b\xca\x91\x12\x09\xa2\xc7\x5e\xa3\x9a\xeb\x6b\x05\xff\x3a" + - "\xd8\xbb\xcd\xe6\x93\x49\x0c\x72\x07\x80\x16\xba\x1f\x25\xf6\x22\x60\xce\x1c\x3f\x17\x37\x5d\x73\xe7\x0b\x71\xe2" + - "\x6c\x00\x77\x29\x26\x78\xa1\xcc\xd9\x24\x1a\x3e\x8b\x4f\x91\xdd\x43\x76\x32\x0d\xc9\x74\x2f\x7d\xd2\xc4\xc7\x5e" + - "\xa3\x68\xd9\x7d\x58\xae\x32\x7a\x9c\x38\xd2\x2a\xac\x3e\xf6\x3e\xf8\x7c\xf5\xbb\x09\x74\x8b\x22\xeb\xc3\x2a\xf9" + - "\x9d\x9b\x04\x2b\x75\xa7\x65\x58\x7d\x8c\x36\x26\x3d\xf3\xc3\xc7\x47\xbc\x4d\xd5\xb5\xcd\x61\xac\xb3\xdb\xda\xff" + - "\x80\xcd\xf9\xbf\xb7\x2d\x6a\xec\x0d\x6d\xe2\x63\x9e\x99\xd6\x65\x62\xed\x0f\x19\xa5\x98\xc2\xab\x45\x85\xfa\x2a" + - "\x4f\xee\xd8\xea\x2e\xeb\x27\x65\x7e\x16\x11\x1e\x74\x22\x98\xb7\x42\xc8\x51\x5e\x1e\xf2\x32\xef\xe4\x48\xbd\x0d" + - "\xf1\x7a\x2c\x7c\x64\x5f\x13\xac\xf6\x0f\x7e\x17\xad\xff\x34\x02\xff\x98\x03\xe7\x3f\x8a\x11\x40\xf5\x3a\x7c\xdb" + - "\x63\x44\xa9\x31\x42\xff\xa9\xd1\xff\x78\x5a\xf0\x1f\x5e\xa3\xaf\xda\x43\x1b\x51\x6a\x07\xad\xff\xd4\xeb\x7f\x3c" + - "\x5d\xf8\x0f\xaf\xd7\xd7\xec\xc6\x8e\xa8\x35\x4e\xea\x3f\xb5\xfa\x1f\x4f\x13\xfe\x23\x6a\x35\xdf\x07\x33\xc3\xdf" + - "\xf0\x54\x19\x83\xb0\x1e\xec\x44\x1f\x62\x65\xa0\x93\x88\xff\x6f\xbc\xaf\x32\xbe\x2b\x8e\xc5\x70\x7e\xae\xd8\x56" + - "\xa3\x86\x39\x60\x0c\x1b\x76\x49\x62\x70\x12\x57\xfb\xbf\xd2\xb4\x43\xb6\xb0\x74\x30\x16\x16\x97\xbc\x3c\x4d\xeb" + - "\x4b\x51\x80\x4c\x3c\xc6\x1b\x08\x56\x25\xfd\x77\x03\x59\x65\x13\x32\x9f\x55\xb0\x90\xfb\x66\x28\x29\x40\x4a\x80" + - "\x01\xc7\x93\x2f\xe6\x09\x85\xae\xaa\x75\xda\x3c\xa5\x1c\x23\xe1\x7f\x16\x59\xb2\xa2\x52\x52\x5b\x87\x1f\x58\x91" + - "\x0e\x7e\xa2\x24\x93\x53\xac\xb5\x41\x83\x65\x58\xd3\x64\x96\xb7\x98\x70\xbd\xaf\x3b\x0e\x3b\xf3\xfe\x43\x9d\x5a" + - "\x5c\xd0\xb1\xad\xef\xd9\x30\x09\x79\xea\x11\xa9\x4c\x3d\x4f\x72\xe3\xa5\x0c\x83\x41\xd7\xab\xb7\xb7\xe4\x30\x73" + - "\x55\x61\x24\xb5\xf3\x64\x4e\x73\xdd\x99\x18\x39\x18\xbc\x04\x67\x4a\xb0\x0e\x00\xf9\x36\x9c\x70\xe6\x07\x4d\xef" + - "\xec\x5d\x4a\x8b\x00\x38\x7f\x68\x14\x38\x33\xc2\x5c\x75\xe1\x86\x05\x93\x5d\x47\x5b\xe4\xe1\xd1\x89\xd5\x0c\x55" + - "\x04\x6e\x05\x38\x41\xee\x70\x29\x00\x9c\x04\x71\x55\xe3\x14\xf5\x28\xf7\x6e\xcc\x80\x66\x85\x74\xb0\xb1\x41\x19" + - "\xde\x82\xbe\x2b\x6f\x60\x9f\xa1\xdd\xc2\xbb\x2f\xf9\x18\x7e\xee\x09\xe1\x8e\x17\x0c\xc7\xf0\xf0\xe2\xe0\x2b\x35" + - "\xb7\xdf\x9f\xc1\x6b\xbe\x46\x4f\x46\x30\x9e\xa6\xed\x99\x14\x05\x2a\xea\x31\xd4\x31\xcc\x5b\x54\x33\x08\x73\x9c" + - "\xe9\x31\x02\xa3\xf8\xfe\x91\x71\x3b\x66\x00\xeb\x23\x04\x18\xfe\x15\x43\xd3\xd5\x8b\x8e\x81\xe9\x97\x9f\x73\x58" + - "\xfa\x79\xb7\x06\x65\xba\xc9\x32\xea\x3a\x20\x78\xeb\xc1\x07\xd7\x04\xe4\xa1\x37\x8a\x72\xbd\x6d\x74\xd2\x72\xce" + - "\x83\x0a\x00\x49\x77\xe4\x6d\x75\x02\x4e\x75\x38\xa9\x82\xd3\x4b\x7e\x88\x61\x1e\x1c\x85\xbc\x26\xd9\x06\x68\x82" + - "\x61\xe9\x60\x0f\x58\x35\xde\x72\x68\xc4\x29\x0a\x07\x31\x3f\xfc\x3d\xba\xbe\x27\xe4\xee\x77\x56\x8a\x74\xba\xaf" + - "\xa5\xe9\x92\x2e\x0e\x4e\x5f\x8b\x91\xf4\xf4\x38\x28\xf6\xb3\x85\xcd\x71\x01\x7d\x3d\x70\x6e\xf4\x35\x94\xb7\x55" + - "\xe1\x8d\x27\x6c\x9c\x42\x70\xd3\x1b\x45\xb9\x47\xa7\x0b\x5a\x6e\x01\x4b\x00\xbb\xeb\xfd\xad\x26\x87\xb9\x3a\x3e" + - "\xe4\xa4\xea\xe9\x7d\x1d\xc2\x37\xde\x0d\xc8\x6b\xc6\x3b\x68\x82\xae\x03\x5a\x0f\x58\x35\xde\x76\x3a\xc9\x29\x0c" + - "\x27\xb9\x31\x8c\x7b\x28\x00\x27\xe5\xee\x7f\x51\x6e\x4b\xd5\xdb\x62\xba\x4f\x53\x4f\xf7\x73\xa2\x9e\xde\xd7\x00" + - "\x7c\x9d\xaf\x03\x5e\xd3\xf7\x80\x7f\xbd\xef\x35\xd9\x7b\x45\x7c\x45\x20\xc3\xe9\x65\x60\xeb\x68\xe3\x1c\xf4\x62" + - "\xb8\xae\x58\x52\xf4\xdc\xe9\xdc\xde\xd6\x1f\x0d\x27\x8c\x1e\xae\x75\x9d\xe4\xe1\xc7\x94\x66\xf6\x31\xa5\xc4\x3e" + - "\xc4\xe3\x83\xd5\x5a\x35\x44\xe8\xb4\xe3\xc2\x3a\x0c\x94\x3d\x1e\x66\x09\x7d\x35\x25\xec\xfa\x32\x7a\xa7\x18\x65" + - "\x09\x7d\xd9\x19\xe4\x65\xc3\xdd\x5f\x4e\xa2\xcb\xbb\x82\x06\xe9\x53\x62\x1e\xe3\x5a\xfb\x0e\xe6\x02\xea\xd2\x93" + - "\x8f\x90\x8f\xe2\xd2\xeb\xf0\xd9\xfc\x7b\x58\x04\x58\x5f\xf5\x4c\x85\x68\xfd\x87\xaa\xea\xf4\x8b\xd5\x66\x97\x05" + - "\x9c\xb9\x33\x9e\xca\x31\x0e\xf8\xbb\xae\x76\x8f\xc4\x9b\xcc\xbe\x7c\x02\x83\x54\x8a\xe0\x49\xb4\x42\xa6\x9b\x7b" + - "\x32\xe3\x8a\xae\x03\xe0\x16\x45\xcb\x58\x07\x55\x61\x22\xc9\xe4\x7b\xf6\x1b\x7f\xc8\x18\x76\x33\xa3\xc5\x0b\x7d" + - "\xc1\xc4\x10\x26\x83\x89\xe9\xcc\x8f\xbf\xfc\x70\xed\x60\xd4\x98\x02\xe1\x4a\x4f\x28\x33\xa8\x7d\x61\xa4\xf4\xd6" + - "\x05\xc7\x45\xaf\xd7\x53\x69\x73\x3e\xf9\x14\xc5\x17\x11\x96\x87\x44\xed\xb9\xe9\x93\x3d\x68\x3d\x78\x0e\xc9\x75" + - "\xe2\x2a\x83\x28\xc6\xfe\x8c\x1b\xda\xd6\x55\xd9\xb2\x9b\x7c\xec\x8b\x7a\xe0\xd6\x3b\x9c\xd0\xaa\x22\x71\x33\xc5" + - "\xa8\xc3\xf1\xd9\xae\x5a\x02\x0a\x16\x82\xdf\xb6\x36\x78\x33\xa9\x6b\x79\x33\x78\x29\x3e\xb2\xac\x22\x6b\x9c\xbc" + - "\x75\x58\x5c\xc9\xda\x53\xd7\x4f\xc6\xfa\x97\x46\xe3\x5d\x4d\x06\x37\xd0\xee\xb5\xf7\x1a\xda\xd7\x71\xe6\x96\xea" + - "\x68\xcd\xff\xf0\x62\x8f\xba\xec\x6e\xbd\x30\x5a\xd5\xe9\xb7\xea\xf0\x7b\xb6\x6a\xb4\x2a\x7f\xab\xee\xda\x1b\x77" + - "\x95\xf7\x5d\x25\xfa\x16\x99\x8d\x0f\x92\xdf\x60\x10\x80\xf9\xfb\x57\x1e\x03\x77\xaa\x29\xa0\xc3\x7e\xab\x9a\xbc" + - "\x6d\xba\x67\x4f\xdc\x53\xd6\xf7\x94\xe6\x1b\xe4\x65\x2b\xff\xd5\x53\x00\xc8\x60\x25\xd8\xc1\x9c\x51\xb3\x04\xf3" + - "\x2d\xef\xb0\xde\xb9\x8a\x3b\xd1\x87\xf0\x43\x13\xaa\xb5\x7e\xba\xbd\xb7\x19\x4e\xf7\x0a\x96\x9c\xf2\x1c\xa9\xf3" + - "\xff\x02\x71\x5f\x33\x6b\xbe\xa9\x9a\x70\x3f\xe0\x0d\x9d\x7c\xbf\xd6\x8c\x54\x33\x32\xcb\xde\x4d\xfc\xf7\x93\xf0" + - "\xfd\x84\x78\xb3\x9c\xd0\xe1\xf0\x1b\xeb\xfa\x5d\x0c\xcd\x68\x47\xfc\xfa\xe6\xec\x6e\x6d\x19\xed\xc0\xbb\x98\xd0" + - "\xb1\xb9\xf4\x5e\xd2\xbd\x9b\x00\x6f\x95\x51\x14\x60\xf0\xd1\x60\x44\xdf\xea\x4f\x66\x90\xc3\x2a\x02\xfd\x6a\xcc" + - "\x4a\x9f\x00\xb0\x4f\x1d\x3e\x99\x71\x72\x77\x68\x14\x1b\x8a\x21\xde\x9c\xc1\x59\x88\xd3\x86\x85\xf4\x50\x4b\xc0" + - "\x21\xa8\x59\x87\x1d\x8d\x51\x90\xa0\x91\x63\x44\x39\xa7\x4f\x5d\xf3\x64\x98\xc0\x68\x14\x7e\x64\x7a\x1b\x30\x7a" + - "\x5d\xba\xa6\x06\x05\x1f\x5c\x43\xef\x8a\x5e\x53\x83\x82\x0f\x9e\xa2\x83\xe5\x76\x1b\x8d\x37\xf0\xe1\x90\xee\x6d" + - "\x34\xde\xc0\x87\xa3\x0f\x6e\xa3\x71\x72\x05\x61\xd5\x23\xd7\xa1\x3a\xed\xf4\x69\xf1\x6e\xf0\x4d\x30\xa8\xcc\x43" + - "\xe8\x03\xf1\x86\xd1\x07\xb2\x0c\xa1\x0f\xc4\x16\x36\x41\xde\x28\xb1\x40\x55\xbe\x95\x87\x20\xa9\x06\xaa\xf1\xad" + - "\x3c\x04\x49\x3e\x50\x85\x5d\xab\xa2\xe1\xa5\xe1\x10\x25\xd6\x67\x91\x71\x2d\x36\x16\xe9\x01\x6a\x16\x5c\x03\x0a" + - "\x8f\xd4\x10\xa0\x27\x66\x9d\x6f\xa7\x71\x25\x1f\x8e\xb6\xbf\x9d\xc6\xc9\xf6\x87\xc2\xfb\x1a\x7a\x5c\x01\x5d\x0d" + - "\xc1\xbd\x3d\x2d\x46\x46\x28\x7d\x0c\xfc\xc6\x7e\xf6\xd6\x78\x2d\x81\x2b\x79\x08\x6a\xf5\xb5\x04\x4e\x8e\xdd\xca" + - "\x91\x55\xdc\xc8\xcd\x0f\x93\x80\x7b\x9f\x1c\x5e\xb6\x81\xa0\xfc\x8f\xb1\x0b\x26\xe8\x3b\x1c\x26\x91\x4f\x36\x2d" + - "\x33\x01\x9b\x8d\xa4\x1d\x31\xf1\x0a\x07\x45\xfb\xe4\xd9\x46\x56\xa7\x2a\xc2\x10\x07\x6f\x1f\xf1\xb1\x3d\xfe\xbe" + - "\x4e\x1e\xdd\xc8\xf5\x37\x85\xa3\x98\x0c\x45\x8e\xe5\x87\x7d\xd2\xc6\xe6\x48\x4b\x8d\xed\x79\x67\x02\xc0\x3e\x21" + - "\xdd\x01\xae\xef\x84\x9e\x1b\xb9\xb2\x1a\x5f\x2f\x38\x93\x8f\x06\xb6\x00\xc9\x49\x0b\xd8\xf5\x3e\xa6\x88\xd2\xc5" + - "\xbb\xc9\xc5\xb1\x58\xd2\x3a\x99\xd6\x52\x86\xfb\x2e\x79\x68\xe0\xbe\x5e\x7a\xf3\x75\x12\x5f\x4d\xb7\x74\xd4\x15" + - "\xed\x78\x43\xfe\x60\x94\xee\x9b\xfa\x0a\xe3\x5b\x4b\x2d\xe3\x4b\x9f\xa8\x81\x7b\x07\xd5\x1d\x72\x35\xfa\x2a\xbb" + - "\x69\x68\x85\x37\x05\xe9\x31\xc0\xb4\xeb\xa0\xbf\x97\xf4\xdb\x06\x18\xc2\xfa\x90\x3a\xc5\x97\x2b\x72\x80\xf5\x76" + - "\xd7\x1d\xb2\x52\x3a\x6b\xba\xa5\xaf\x42\x1b\x81\x75\xd4\xc0\xae\xeb\x94\xbe\x9b\xee\x9b\x7a\x09\x63\x5a\xcb\x05" + - "\xe2\x4b\x89\xa9\x81\xfb\xfa\xea\x1e\xf9\x37\x7d\x95\xdd\xd2\x5d\x57\x34\x05\x9b\xb8\x06\xa6\x5d\x67\xea\xbd\xa4" + - "\xdf\xd4\x69\x18\xeb\x30\xd3\x85\x2f\xff\x27\x84\xf6\x75\xd9\x3d\x72\x8d\x7a\xea\xba\xa5\xc7\xc2\x1b\x82\x75\xd8" + - "\xc0\xb2\xeb\x20\xbc\x8f\xf2\x9b\xfa\x4b\x67\x9c\x9e\xf7\x34\x33\x57\x14\xa1\x57\xeb\xe5\x91\x78\xfd\x3d\x82\x04" + - "\xcb\xe6\xe9\xac\xcf\xfa\x22\x0f\xe3\x5a\x90\xec\x03\x5b\xab\x59\x45\x39\x4b\x71\x8a\x21\xf1\x1c\x12\x58\xc9\x73" + - "\x9e\xd1\x4a\x9e\x31\x54\x0d\x26\xfb\xb6\x2a\x2e\xdd\x90\x7c\x59\xac\x73\xe0\x6d\x80\x21\x65\x01\x48\x37\x8f\x65" + - "\xf8\xb4\x56\x61\x56\x5b\x67\xeb\xfd\xeb\x56\x4b\x88\xa0\xee\x2a\xac\xa7\xf3\xd5\xef\x9c\x88\xcb\xfd\xeb\x02\xc5" + - "\xdb\x0c\x48\x5f\xa9\xb8\xec\x79\xce\x4b\x2b\xab\xe8\x70\xf8\x7b\xeb\xcf\x02\x3e\xee\xd6\x6b\xab\x0d\xba\xe8\xff" + - "\xdd\x9e\x9f\x35\xec\x1e\xc3\x38\x86\x26\x04\xa6\xb1\x7f\xbb\x54\x1d\xfa\x2a\xbb\x7e\x7a\x5d\x7c\xb5\xf3\x9b\x42" + - "\x8a\x71\x61\xdc\x7a\x98\xeb\xf9\x14\x90\x77\x0b\x18\x5a\x7b\xd6\xd1\xb6\x28\x16\xd8\xdb\x1a\x12\x84\xc3\xe7\x2e" + - "\x1e\x03\x1e\x6d\x18\x7d\x57\x25\x49\x86\x97\xd3\xf4\xfb\x21\x89\x5a\x2e\x1c\xf2\xa2\xeb\x3b\x98\x14\xf5\x89\x7c" + - "\xa8\x6a\x92\xe6\xdd\x6b\xf4\x43\x34\x4f\x58\x97\x88\x0f\xbb\x68\x3a\xd7\x18\x56\xb7\xdf\xf9\x5f\xf6\x35\x20\x58" + - "\x77\xc0\xe3\x23\x3e\x56\x56\x26\x2b\x32\x9f\xc3\xfe\xd2\x75\x55\x09\x24\xa8\x52\x61\xd6\x35\x25\x0d\x29\x53\xf0" + - "\x82\xaf\x6e\xbd\x90\xea\x87\x71\xc0\x92\x1d\xa3\xc3\xfb\x5c\x65\xa4\x88\xd9\x7b\xd4\x58\x36\x1c\x0d\xcc\x30\xb4" + - "\x87\xfc\x85\x67\x7f\x18\x8c\x4e\x03\x8c\xab\xcb\x00\xa9\xd4\x01\xb3\x64\x95\x3c\x9a\xef\xd2\x60\x86\x18\x8e\x41" + - "\x59\x16\xb7\x69\x53\x15\x05\x6b\x7f\x57\x5d\xd2\x13\x43\xbc\x74\xbd\xee\x98\xcd\x9b\x1e\x48\x46\x23\xd1\xd4\x2c" + - "\x27\x45\x75\xd4\x84\x0b\x53\xf7\x6a\xdf\xd8\xfb\xff\xd3\x85\x78\x82\x01\x7f\xce\x41\xfe\x89\xc2\x42\x40\x0f\x45" + - "\xb3\x4e\x01\x5c\x90\x8e\xf6\xe3\x39\x9e\xaf\x7e\xc7\x13\xb3\x9e\xdb\x00\xa0\x6a\x1c\xc6\x0b\xa0\xcb\x2e\x2f\xc7" + - "\x24\x87\xd0\x49\x46\xd9\x4d\xc6\x78\x4d\xbc\x8c\x26\x1f\x11\x05\x06\x5a\xaa\xd4\xe4\x05\x2a\x91\xfa\xfa\xaa\xbd" + - "\x7d\x61\xb7\x0f\xf7\x26\xc4\xd4\xa9\x3f\xa5\x61\xe4\x58\x62\x94\xc4\xc3\xd5\x1e\x52\xee\x5b\x76\x48\xf2\xdd\xb4" + - "\xc8\xeb\x5d\x34\xcc\x9a\xd6\x24\x87\x96\xdb\xf3\xdc\x76\xbb\xc5\x4b\x8c\x89\x63\xfe\x11\x9f\x16\xf4\x21\xe6\xbe" + - "\xdb\xb7\xa8\x5f\xfa\x59\xc2\x24\x8b\x5d\xed\x73\x82\xea\x02\xed\x1b\x9b\x35\x55\x7d\x77\x0b\xb4\x4c\x1c\xbd\x91" + - "\x24\x09\xce\x02\x37\x26\xbf\x78\xac\xbb\x61\xdc\x5d\x74\xf2\xd2\x4b\xc5\x39\x47\x08\x3a\xbd\xab\x2e\x5f\x11\x02" + - "\xbe\xd2\x6c\x3d\x5d\x2e\x4c\x77\x69\xec\x66\xe3\x77\xec\x05\x40\xbc\x02\x30\x19\xc1\x10\x78\x3c\x37\x95\xde\xbc" + - "\x83\x88\x5f\x44\x95\x0f\xf2\x18\x42\x51\x37\x37\xd1\xd1\x82\xde\xe7\xe4\x98\xe8\xdd\x40\xd1\x5e\x98\x76\x5e\xf9" + - "\x20\x8e\x18\x38\x26\x01\x41\x7b\xba\xef\xca\x4f\xec\x91\x33\xd7\x9e\x82\xf6\xa8\x8e\x8b\xc5\xe1\xd1\x34\x9c\xe2" + - "\xf0\x60\xbb\x1b\x9d\x39\x85\x9f\x86\x9f\x36\xbe\xa1\x6d\x7c\x96\xdc\x93\x26\x3e\x53\xd2\x5e\x1a\x73\xb1\x64\xad" + - "\x1d\xe2\xed\x76\x2b\x3c\x3c\x61\xee\x56\xc2\xab\x96\x7d\xb8\xb2\x1e\x3f\xe0\x95\x88\x8a\xc5\xe3\x55\x1f\x22\xf5" + - "\x64\x55\xa4\xbd\x59\x65\xd9\x5a\x59\xcf\x3a\x91\x2f\x4c\x49\xfd\x61\xaf\x92\x71\x3b\xcd\x1f\x98\xb2\xad\xab\xc3" + - "\x02\xad\xc4\xe5\x50\xdc\x04\xbd\x0b\x05\xd6\xeb\x15\x8e\xb0\xe4\x77\x91\x24\xda\x0b\x56\x58\xc3\xb7\xdb\xb9\xd1" + - "\xf0\x42\x6f\xf4\xd6\x20\x32\xed\xaa\xaa\xe8\x72\xd3\xd0\xc1\x6e\x02\xd6\x6b\x93\xe0\x8b\x5c\xe6\x54\x1f\xc8\x39" + - "\x2f\x5e\x77\xd1\xfb\x7f\xa5\xc5\x33\xed\xf2\x94\x44\xff\x46\x2f\xf4\xfd\x24\x52\x1f\x26\xd1\xbf\x34\x39\x29\x26" + - "\x51\x4b\xca\x36\x6e\x69\x93\x1f\xcc\xeb\xc1\xd8\xf3\x87\x4b\xcc\x4d\x9f\x2e\x7d\x1e\xaf\xcb\x26\x8a\xe6\x8e\x19" + - "\xc3\xad\x69\x0c\xb7\x26\x81\xae\xaa\x75\x23\xb0\x92\x37\x5a\x35\xab\x05\x96\x29\x12\xd3\xca\xbb\x28\x74\xc2\x1a" + - "\xd8\x08\x2e\xc8\x60\xe8\xaf\x18\xc1\x35\x53\x36\xba\xaa\x45\x78\x8e\xf3\x12\x79\x41\x6e\x9e\x60\x4f\x5a\x3e\x5c" + - "\xf1\x22\xc7\x35\x79\xe8\xc4\x72\xc8\xbd\x9d\x2a\x79\x25\x4d\x53\x7d\xf5\xe8\x33\xf6\xde\x48\x62\x2f\x6e\xf1\xdb" + - "\xf7\x22\x6b\x23\x33\xe2\x98\x4a\x20\x5c\x20\x5e\xc1\x8a\xc7\x3e\x74\xb1\xeb\x93\xa6\x34\x86\xfc\xe1\x4a\xeb\xd2" + - "\x31\xe2\x36\x00\x36\x78\x7a\x4e\x84\x97\xe1\x49\x47\xcb\x5f\x31\xb3\x3d\xde\x93\x1d\xae\xf2\x81\xb2\xc1\x93\x4f" + - "\xde\x8b\x1d\x27\x2b\x7c\xa3\x9d\x77\x8c\x9d\x71\x93\x8f\x66\x2f\x13\x26\x23\xfc\x2c\xae\x87\x15\x57\x27\x41\x4e" + - "\xa0\x7b\x19\xc6\x4a\x22\x99\x79\xd4\x0f\xef\xf9\x38\x11\x66\xc5\xc5\xcb\x4d\x9a\x8b\xf1\x61\x84\x59\x9d\x9c\x38" + - "\xf5\xd7\xf2\xbb\x75\x6d\xf1\x88\xe6\x4d\xec\xf8\x95\xc6\xa9\xbc\x77\x63\xa7\xae\x6a\x15\x1e\x1a\x8b\xc3\xe2\xeb" + - "\x8e\x35\x1e\xf9\x80\xd6\x7c\xb3\x36\xdd\x78\x30\x15\xdf\x67\x72\x5f\x86\x4f\xee\xe0\x1d\x4d\x38\x77\xa8\x47\xa3" + - "\xf4\x37\x8d\x9b\x33\x29\xfe\x6e\xcb\xdc\x34\x4d\xdf\xbc\xcc\xf5\xb8\x95\x89\xed\x29\xce\x91\x95\xad\x1b\xd6\xd0" + - "\x22\xe5\xba\x68\x5a\x0a\x83\x0a\x12\x70\xf0\x54\xb4\xf1\x8e\x81\x02\xc7\x44\x4b\x9d\x8d\x80\x2a\x3f\xc4\x58\x87" + - "\xd8\xa0\x60\x89\xa7\x94\xf2\xa1\x6f\xa6\xf6\x24\x2b\x92\x63\x66\xe9\x8e\xcb\x6f\xfa\x7f\x23\x8b\xd3\x7d\xff\x0f" + - "\xe9\x2b\x65\xe5\x23\x73\x64\xea\x11\x18\x10\xb9\x66\xbc\x18\xc0\x4f\x53\x66\x40\x26\x91\xf1\x61\x47\x0e\x9d\x77" + - "\x90\xdb\x8e\xf7\xdd\x7d\x19\x9d\xa3\x08\x49\xdc\x32\x73\xb5\x07\xb0\x2f\xa4\xb1\x8b\xde\xbf\xb7\x4d\x1f\xa6\x13" + - "\x5d\x55\xeb\x55\xca\x94\xd3\xc2\x06\x79\x26\x1f\x09\x82\x4c\xff\x5a\xfc\x09\x96\x98\x43\x64\xf5\xd1\x36\xc3\x56" + - "\xe6\x10\x8b\x55\xd0\x60\xa0\x45\x08\x87\xea\x91\x3a\x29\x95\xe8\xbd\x83\x63\x2d\xf3\xd5\x18\x27\x6c\x78\x42\xb1" + - "\xd9\x2e\x8c\x92\x8e\x3e\xd6\x75\x91\xe9\x8e\x8a\x2e\x34\xad\xcc\x2b\x36\xe6\x63\x84\xb0\x8a\x88\x4d\x89\x48\x18" + - "\x18\xaf\xbc\x74\x76\x75\x89\x79\x99\xe0\xb5\x59\x02\xbb\x51\xc9\xe0\xd0\xc3\x27\x70\x5d\x92\x7a\xa1\x2d\x4a\x2f" + - "\xb7\x40\x66\x32\x90\x74\x93\x9e\x8d\x33\x0d\xcf\x85\x01\x83\xed\x52\x33\xf9\xde\x6e\xb8\x9e\x21\x2c\x68\xee\xa9" + - "\x2e\x35\x58\x34\x2e\x33\xc0\x29\x90\x98\xcc\x8a\xa3\x2f\x7a\xc6\xc4\x15\xc6\x2d\x10\x57\x4a\x9a\xea\xd2\x52\x73" + - "\xd7\x4a\xc6\x15\x4d\x30\xb0\xa6\xf6\x46\xff\xe5\x46\xb9\x6b\xa7\x4c\xa7\xf7\x34\x0d\x4d\xfe\x2f\x5d\x40\x6c\x53" + - "\x4a\xbe\x24\x29\x5e\x01\x57\x5e\x97\xb1\x15\xe5\x02\x1b\x83\xf1\xb1\xfe\x24\x1f\x18\x47\x0b\xe5\x5b\xe3\xba\xb7" + - "\xa8\x07\xc4\x48\x51\xf0\x37\xec\xd5\x5e\x4e\xbc\xc8\x3e\x46\x93\xe8\x83\xbd\xd9\x16\x2f\xb2\x48\x84\xcb\x9c\x72" + - "\x0c\xdd\xb6\x5b\x5b\xef\xab\xfb\xb7\xee\x10\x78\xc7\xf6\x1d\x46\x19\xb8\xb3\x07\x92\xd2\xf8\x39\x6f\xf3\x7d\x5e" + - "\xb0\x68\xd5\xb0\x01\xf5\x6e\xac\x5c\xd2\xa9\x69\xd3\xd6\x94\x67\xa4\x64\x2f\x8d\xb0\x52\xeb\xab\x7a\xe2\x1f\x11" + - "\x96\x48\x68\x39\x95\x6f\x8d\xa0\x30\xa5\xcc\x21\x09\xd7\x29\xde\xed\xbd\x45\xf6\xa1\x1f\x02\x7c\xd8\x7f\x1c\xc4" + - "\xe4\x05\x0b\xe1\x53\xbc\x45\x82\x82\xd4\x0d\x7d\xbe\x9a\xcd\x38\x90\xcf\xf8\x3a\x46\x7d\xa2\xe4\x8d\xe8\xeb\x72" + - "\xb7\x03\xb8\xf1\xd7\xb4\x26\x09\x68\x49\xa2\xb5\x02\x1f\xd4\xce\x46\x94\x3c\x41\xba\xf9\x59\x89\x1e\x7f\xcf\x06" + - "\x27\xcf\x8d\x82\xbe\x21\x71\x6d\x7d\x63\x0b\x6b\x60\x8f\x7d\x55\x00\x56\x7c\xa0\xaa\x5a\x35\x79\xfb\xc9\xba\xd4" + - "\xd5\xe8\xe1\x11\x19\x00\xd5\x0f\xad\x1c\x8e\xea\xb1\xb6\xf5\x53\x69\x53\x99\x33\xe0\x6d\xe7\xc5\x56\xe6\x03\xd0" + - "\x57\xbd\xf5\x8c\x9c\xd8\x41\x1e\xa9\x5e\x33\xed\xbe\x7e\x47\xd4\x6c\xf0\x20\xd0\xf0\x47\xcb\x78\x7f\x5a\x5b\x40" + - "\x51\x32\x3c\x66\x05\x0e\x6b\x25\xc9\xec\x23\x93\x79\xf8\x33\x62\x77\xae\x40\x34\x63\x20\xcf\xaa\x9b\xb0\x09\x3d" + - "\xea\xaa\x7a\xc2\xb7\x3c\xf9\xcf\x43\x53\x9d\x3f\x58\x55\x7f\xe4\x4f\x7d\x55\x66\x09\xab\xfc\x63\xe0\x8b\x62\x5d" + - "\x15\x89\x19\xe6\xb6\xa6\xc9\xde\xae\x9b\xea\x98\x67\xbb\xff\xf2\x3f\xff\xd8\xd7\xf3\x67\x69\xe0\xa6\x7f\xca\xd3" + - "\xa6\x6a\xab\x43\x37\x55\x55\xb6\x1d\x69\xba\x3f\xf4\x6a\xd7\x76\xcd\x0f\xdf\x7f\xf7\x90\xf0\xff\xfb\x9e\x55\x47" + - "\xcb\x0c\x94\x25\xaa\x2c\xfa\x6f\x02\xff\xcf\xaf\x35\xfd\x61\x66\x36\xaf\xa1\x35\x65\x87\xd5\xd8\xff\xc6\x2f\x4e" + - "\xdd\x1a\x46\x1e\x0c\x06\xf3\x11\x23\x8f\x86\xbc\x51\xed\xb8\x88\x50\xe9\xad\xee\xa2\x76\xb7\x57\xf0\x66\xb5\xe3" + - "\xca\xe5\xd0\xbc\xd5\xdb\xd5\x2e\xb0\x69\x77\x50\xbb\xc4\xa3\x76\x0f\xf7\x56\xbb\xe1\x78\xa2\x59\xe0\x4c\x58\xee" + - "\xdc\xcd\x1b\xdb\x65\xd5\x8e\xf8\x20\x7b\xae\xd6\xfc\x32\x3d\x16\xaf\xf5\x29\x4f\xab\x32\x4e\x4f\xf4\xb9\xa9\xca" + - "\xd8\x9c\x1e\x3d\xa0\xbc\x1f\x35\xaf\x4b\x41\x33\x40\xd3\x53\xd0\x4b\x43\x1c\x06\xb1\x3a\x56\x01\xf8\x95\xb6\xf4" + - "\xca\x4b\xb6\x7e\xc1\xfd\x9a\x5b\xda\xa8\xf8\x12\x67\xb5\x7d\x91\x0c\x10\x7d\x0b\x17\x96\xb3\xd2\x5e\x54\xa2\x52" + - "\xb9\x23\xa3\xd5\xaa\xe2\x03\xde\x6a\xaf\x91\xba\xda\x7c\xd6\x4f\x89\xc8\xbf\xad\xa0\xb6\xb5\x85\xa1\x76\x26\xd0" + - "\x45\xa4\xaf\xfe\xdd\x9e\x1e\xaa\x86\xea\x21\xce\xef\xff\x32\x4f\x16\xdb\xef\x03\x1a\xe7\x46\x27\x36\x7a\x5e\x66" + - "\x79\x4a\xba\xaa\x69\x3d\xba\xa6\xc2\x8e\x09\x12\xc1\x1a\x76\x7f\x56\xc0\xaf\x5a\xf3\x42\xf7\xdb\x82\xf2\x10\x00" + - "\x87\xc3\xbd\x2b\xd7\x03\x86\x18\xf7\x45\xae\x7b\xf3\x50\xf9\x35\xb7\x5a\xef\xcf\x59\xa2\xc7\xf8\x67\xe0\x88\x55" + - "\xdf\xae\x5e\x76\xb1\x3a\x3a\xe4\x3d\x8c\x0c\x77\xd4\xa2\xbf\x6c\xf1\x42\xdd\x74\x27\x1f\x1d\x7b\x3d\x7a\xb8\x51" + - "\x6e\x0c\xa0\xda\x0d\x64\x00\x57\x29\xb2\xbd\x73\xa3\xbd\x73\x64\x4f\xc3\x7f\x6f\x73\x50\x35\x9e\x0c\xda\xa3\x28" + - "\x2a\x31\xf4\xef\xa0\xda\xcc\xf5\xa8\xeb\xca\x50\x1b\x78\x65\x85\x0f\x28\xe3\x62\x84\x75\x11\xe2\xae\xae\xb9\xb3" + - "\x99\xea\x20\x9b\x46\x09\xe8\xa1\x08\x04\xb5\x69\x43\x69\xc9\x63\x41\xea\x8c\x94\x76\x36\xec\xd7\x9a\x58\xde\x3a" + - "\xb3\x0c\x47\xbe\xc4\x09\x35\xa9\x25\x0b\xfd\xc8\x9a\x34\x73\x62\x1f\x19\xae\x96\x16\xea\x9c\xd7\x1b\x9b\x09\xe7" + - "\x16\x66\xe7\xcd\x09\x65\x75\x5d\x45\x61\x13\x8a\x56\x93\x9a\x44\xd0\xaa\x80\xf2\x4b\x3d\x9f\x73\xe3\x25\x14\x5b" + - "\xfe\x65\x6a\x2d\x2a\x22\xc3\xee\xbe\xd3\xb3\x3f\x0c\x61\x0e\x75\xb8\x32\x96\x4f\xc9\x3e\x0d\xdf\x78\xf0\x79\x12" + - "\x8d\x40\xf1\xf9\x80\x79\x22\xfd\xc7\xae\xaa\x8a\x3d\x69\x34\x64\xf9\x4d\x80\x46\xd3\xb4\xa0\xa4\x39\xe4\x2f\x0a" + - "\x4a\x7d\x00\xd4\x7a\x91\x92\xbc\xa4\x4d\x7c\x28\x2e\x79\x36\xc0\x1a\xdf\x07\xaa\xb2\x40\x80\x6a\x44\x06\xb0\xac" + - "\x88\x4f\x55\x93\xff\xdc\x97\x14\x51\x36\x10\xb6\x0a\x00\x33\x2c\xce\x0a\x4a\xf9\x07\x5d\x4e\x3e\x18\x40\x0a\x1e" + - "\x50\x55\xb8\xda\x47\xc5\x6a\x49\x9e\x15\x44\xff\x1b\x50\x29\xc9\xf3\x9e\x34\xea\x4e\x20\x04\xd3\xbe\x43\x5a\x7d" + - "\x01\x3f\xa0\x0c\x24\xa4\x7f\x37\xc0\x0d\xb2\x43\x71\x4d\x8e\x1a\x15\xfe\x37\x28\x96\x17\x14\x15\x05\xf0\x49\x81" + - "\xa9\x2d\x0e\xf1\x9b\x17\x08\x57\x4c\x7f\x4f\xd9\xdc\xe4\xb8\x5e\x85\x4d\xcd\x34\x94\x30\x48\xe5\xdc\xba\x32\x10" + - "\x09\x51\x15\x54\x07\x86\xde\x0e\xe8\x60\xad\x1f\xad\xee\xb2\xbb\xc7\xea\x0f\x63\xb3\xbb\x17\x06\x7b\x41\xfa\xa4" + - "\xa6\x2c\x36\xd9\x81\x23\xd3\xf6\xce\xbd\x6e\xda\xf4\x2b\x1e\xf1\xb0\xb8\x57\x3b\x5c\xfa\x8b\xdd\xf0\xa2\x5b\xf4" + - "\x4f\xf9\xb9\xae\x9a\x8e\x94\x9d\x06\xad\x62\x52\x02\x98\xfd\x6d\xc3\x9e\x72\x71\xbd\x40\xdb\x19\x42\x00\xdb\x93" + - "\xd8\xff\xd3\x1b\x83\x40\xe6\x25\xdb\x6d\x90\x2f\x73\x5b\x3b\x0f\xea\x94\x55\x3f\x7f\xab\xfa\xfb\xc9\x6b\x17\x25" + - "\x9f\x93\x88\x00\x5f\xc2\x38\xba\x60\x4d\xf9\xb8\x9b\x84\x1e\x78\x00\x71\x51\xce\x47\x50\xb3\xc9\xe1\x90\xbf\x60" + - "\xf7\x40\xa4\xb3\xf1\xed\x37\xf1\xb9\x8d\x9f\x73\xfa\xb5\xc7\x84\x3e\x5e\x46\x9f\xf3\x94\x72\xbf\x43\x92\x13\x92" + - "\x89\x8b\xe3\x24\x52\x7f\x9c\x33\xf0\x47\x7b\x06\x7f\xbc\xb4\x41\x4c\x0e\x54\xb9\xd2\x01\x0a\xc5\x31\xe6\x2e\x37" + - "\xf6\x4d\x40\xf7\x7a\x3e\xf0\x62\x91\x38\x67\x36\x09\xf5\x0d\x21\xd1\x9e\x2d\x12\xed\xd9\x26\xa1\xbe\x21\x24\x5e" + - "\x5a\x8b\xc4\x4b\x6b\x93\x50\xdf\xb0\xb1\x86\xcb\x6a\x38\x36\x2f\xcf\xbe\x45\xbb\xcd\x7a\xa3\x7c\x42\x43\xf2\x3e" + - "\x6d\x67\xae\x03\x33\xb1\x6e\x2c\x56\x2c\x41\x9b\x11\xb8\xb8\xa9\xbe\x22\x35\x64\x00\x6d\x12\x75\xa7\x31\x2a\x29" + - "\x2d\x0a\x8b\xcc\x95\x8d\x07\x02\x1d\x13\xc1\xb5\x94\x79\x8f\x19\xa4\xc5\xc7\xfb\xd0\x46\x99\xd7\x8a\x46\xea\x31" + - "\xaf\x92\xf0\x35\x84\x3a\x2c\xb9\xdd\xce\xac\xca\xe5\x6d\x8d\xeb\xf4\xc5\xc2\x72\xe8\x0b\x0e\x37\xaa\x2f\xbd\x2d" + - "\x01\xfa\xe2\xa0\x12\xa2\x2f\x37\x49\xe4\x76\x25\xba\xad\xba\x37\x68\xd6\x5b\x2a\xbc\xa3\xba\xf1\x0b\x3c\x46\xe5" + - "\xb3\xd9\x76\x6b\xd5\x7e\xce\x6e\xd1\x37\x0b\xcb\xa1\x6f\x38\xdc\xa8\xbe\xf5\x13\x19\xd0\x37\x07\x95\xeb\xf4\xed" + - "\x1a\x91\xdc\x43\xe1\xae\xaa\xef\x2e\x1a\x77\x43\x8d\x77\x54\xb9\x19\xbb\xc7\x63\x54\x24\xaf\x8d\x5d\xa7\x5d\x16" + - "\x96\x43\xbb\x70\xb8\x51\xed\xea\x7d\x26\xa0\x5d\x0e\x2a\xd7\x69\x97\xa3\xf5\xf7\x50\x24\x17\xe9\xbb\xe8\x8c\x9f" + - "\xf8\x9b\xd5\x03\x9f\x68\xb9\xdb\x6c\xbb\x1d\x96\xa7\xf5\x36\x03\x2b\xaa\xb1\x66\xab\xeb\xaa\x19\x1f\x55\xa2\x1e" + - "\xcb\x4a\x5d\x57\x8f\xd6\x13\x82\xa4\xa5\x9a\x6e\x92\xaa\xf3\xea\x26\x17\x07\xc8\xc3\x3c\xd8\x01\x1e\x21\x71\xe5" + - "\xc0\xc5\x10\x1d\x63\xd7\x09\x3a\x3a\x7c\x19\xa6\x36\x82\xdd\xb4\xdc\x83\x58\x47\xbe\xda\xef\x77\x49\xed\xda\x01" + - "\x6f\x60\x83\x31\xfd\x46\x3e\xae\xb6\x0e\x28\xfe\xfd\xe4\x72\x0f\x83\x02\x88\x8b\x01\x82\xf5\x3c\x3e\x46\xfe\x4f" + - "\x00\x00\x00\xff\xff\x47\x37\xb0\x07\xc9\x28\x02\x00") - -func gzipBindataAssetscssbootstrapmincss() (*gzipAsset, error) { - bytes := _gzipBindataAssetscssbootstrapmincss - info := gzipBindataFileInfo{ - name: "assets/css/bootstrap.min.css", - size: 141513, - md5checksum: "", - mode: os.FileMode(438), - modTime: time.Unix(1520997241, 0), - } - - a := &gzipAsset{bytes: bytes, info: info} - - return a, nil -} - -var _gzipBindataAssetsfaviconico = []byte( - "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61" + - "\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee" + - "\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28" + - "\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e" + - "\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b" + - "\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb" + - "\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c" + - "\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f" + - "\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0" + - "\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3" + - "\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd" + - "\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c" + - "\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d" + - "\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32" + - "\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd" + - "\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7" + - "\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55" + - "\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9" + - "\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89" + - "\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd" + - "\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1" + - "\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6" + - "\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26" + - "\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a" + - "\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c" + - "\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea" + - "\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04" + - "\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e" + - "\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14" + - "\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f" + - "\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b" + - "\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11" + - "\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3" + - "\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9" + - "\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67" + - "\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d" + - "\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc" + - "\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e" + - "\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde" + - "\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1" + - "\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34" + - "\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c" + - "\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc" + - "\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c" + - "\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa" + - "\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61" + - "\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d" + - "\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f" + - "\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0" + - "\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e" + - "\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13" + - "\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2" + - "\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27" + - "\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc" + - "\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a" + - "\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1" + - "\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60" + - "\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25" + - "\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36" + - "\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5" + - "\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c" + - "\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4" + - "\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61" + - "\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a" + - "\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26" + - "\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6" + - "\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65" + - "\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69" + - "\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99" + - "\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9" + - "\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70" + - "\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29" + - "\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f" + - "\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c" + - "\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6" + - "\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1" + - "\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31" + - "\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf" + - "\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65" + - "\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e" + - "\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89" + - "\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2" + - "\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4" + - "\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f" + - "\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf" + - "\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad" + - "\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79" + - "\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5" + - "\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06" + - "\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5" + - "\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd" + - "\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce" + - "\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35" + - "\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb" + - "\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54" + - "\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6" + - "\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d" + - "\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca" + - "\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21" + - "\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb" + - "\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd" + - "\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65" + - "\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d" + - "\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc" + - "\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93" + - "\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d" + - "\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d" + - "\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9" + - "\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98" + - "\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d" + - "\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed" + - "\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd" + - "\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1" + - "\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27" + - "\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa" + - "\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42" + - "\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b" + - "\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45" + - "\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09" + - "\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3" + - "\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0" + - "\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0" + - "\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05" + - "\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48" + - "\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8" + - "\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81" + - "\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38" + - "\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7" + - "\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3" + - "\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f" + - "\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17" + - "\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6" + - "\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a" + - "\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e" + - "\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f" + - "\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3" + - "\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd" + - "\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27" + - "\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7" + - "\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba" + - "\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58" + - "\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0" + - "\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff" + - "\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00") - -func gzipBindataAssetsfaviconico() (*gzipAsset, error) { - bytes := _gzipBindataAssetsfaviconico - info := gzipBindataFileInfo{ - name: "assets/favicon.ico", - size: 15086, - md5checksum: "", - mode: os.FileMode(438), - modTime: time.Unix(1520997241, 0), - } - - a := &gzipAsset{bytes: bytes, info: info} - - return a, nil -} - -var _gzipBindataAssetsjsjquery211js = []byte( - "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\xfd\x7b\x77\xdb\x46\x96\x28\x8a\xff\x2d\xaf\xe5\xef\x50\xa2\x73\x64" + - "\xd0\xe2\x43\xb2\x93\x74\x42\x99\xd6\xcf\xb1\x9d\x1e\x9d\x5f\xec\xb8\x23\x67\x32\xf7\x4a\xca\xa4\x48\x14\xc5\xb2" + - "\x41\x80\x41\x81\x92\xd8\xa1\xfa\xb3\xdf\xb5\x1f\xf5\x02\x40\xd9\xee\x4e\xcf\x39\x3d\x6b\x62\x11\x28\xd4\x63\xd7" + - "\xae\x5d\xfb\xbd\x87\x8f\x76\xef\xdf\x13\x8f\xc4\xfb\xbf\xad\x54\xb9\x16\xff\x5b\x5e\xc9\xd3\x69\xa9\x97\x95\xf8" + - "\x41\x4f\x4a\x59\xae\xc5\xd5\xe3\xc1\xe1\xe0\x10\x1b\xcd\xab\x6a\x39\x1a\x0e\xdf\xff\x0e\x6d\x07\xd3\x62\x31\x84" + - "\xc7\xf8\xea\x24\x9f\x66\xab\x54\x19\x71\xaa\xff\xfe\xf7\x4c\x0d\xde\x9b\xf0\x0b\x83\x0f\xdf\x9b\xf8\x9b\x17\xc5" + - "\x72\x5d\xea\xcb\x79\x25\x1e\x1f\x1c\x7c\xd5\x13\x8f\x0f\x0e\xbf\xb4\x13\xf9\xbe\x58\xe5\xa9\xac\x74\x91\xf7\xa0" + - "\xef\x81\x90\x79\x2a\x8a\x6a\xae\x4a\x31\x2d\xf2\xaa\xd4\x93\x55\x55\x94\x34\xc8\x4f\x2a\x53\xd2\xa8\x54\xac\xf2" + - "\x54\x95\xa2\x9a\x2b\xf1\xfa\xe4\x9d\xc8\xf4\x54\xe5\x46\xb5\xcc\xbc\x28\x2f\x87\xc1\x5b\x6c\xf1\x52\x56\x6a\x84" + - "\x53\xe8\x1f\x7c\xd5\x3f\x38\x7c\x77\xf8\x97\xd1\xe1\xe1\xff\x0b\xef\x86\xf7\xef\xdd\xbf\x97\xcc\x56\xf9\x14\xe6" + - "\x93\x88\xcb\xac\x98\xc8\xac\x27\x66\x72\x5a\x15\xe5\x5a\x74\xc5\x1f\xd0\x62\x47\xcf\x44\x22\xaa\xf5\x52\x15\x33" + - "\xb1\x28\xd2\x55\xa6\xc4\x78\x3c\x16\x9d\x62\xf2\x5e\x4d\xab\x8e\xd8\xdb\x8b\xdf\x0e\xd4\xcd\xb2\x28\x2b\x13\xb7" + - "\xc2\xde\x76\x76\x86\x43\xf1\x7d\x51\x8a\x17\xc5\x62\x51\xe4\xff\xfb\x14\xd7\x6f\x7f\xf4\x33\xfd\x41\x09\x95\x5f" + - "\xe9\xb2\xc8\x17\x2a\xaf\x8c\xb8\x9e\xab\x52\x09\x29\x96\x65\xb1\x54\xa5\xb8\xd6\x79\x5a\x5c\x0b\x6d\xc4\xb2\x54" + - "\x46\xe5\x55\x8f\xfb\x54\x37\x6a\xba\xaa\x14\x02\xc9\xce\x1f\xba\xbe\x54\x15\x83\x3e\x18\x3c\x1a\xa1\x9a\xcb\x4a" + - "\xa4\x85\xc8\x8b\x4a\xe8\x1c\x86\xcb\xab\x6c\x2d\x96\x85\x31\xca\x08\x69\x87\xbc\xd6\xd5\x5c\x48\x91\x16\xd3\x15" + - "\x7c\xc7\xbd\x25\x66\x35\x9d\x0b\x69\xc4\x9b\x22\x05\xe4\xe8\xf6\x04\x2c\xde\xc0\x94\x69\xd8\xfe\x42\x7e\xd0\xf9" + - "\xa5\x9f\x94\xa9\x41\x89\x7b\x7a\x37\xd7\x46\xc8\xe9\x54\xe5\xd5\x4a\x56\xca\xe0\x4a\x72\xa5\x52\x31\x2b\x68\xef" + - "\xa7\xa5\x42\xc4\x11\xc5\x4c\x48\x51\x2a\x99\xf1\xdc\x2c\x08\x06\x97\x03\x71\x25\x4b\x8b\x6a\x63\x51\xaa\xdf\x57" + - "\xba\x54\x49\x87\xf0\xa3\xd3\x4d\xe8\x83\xee\x11\x7f\x72\xaa\x94\xa8\xf4\xf4\x83\xaa\xc4\x83\xc3\x2f\xbf\xfa\xf2" + - "\x5b\x1c\x6c\x51\x94\x4a\xe8\x7c\x56\x40\xab\xfa\x96\x32\x96\x0c\x2c\x20\xc4\x31\xb4\xda\xe1\xe5\x79\x24\xaa\xca" + - "\x95\x12\x5d\x31\xa2\xb7\x0e\xc7\xae\x2d\x1e\xec\x10\x5a\xed\x5e\xfb\x9e\xdc\x9b\x9d\x6a\x5e\x16\xd7\x22\x57\xd7" + - "\xe2\x55\x59\x16\x65\x22\x3a\xbc\x26\x5e\xd1\xf6\x7d\xe9\x08\x5a\xdc\xce\xce\x2d\xfd\x53\xaa\x6a\x55\xe6\xc2\xcd" + - "\xef\xda\x36\xb8\x85\x7f\x6e\x85\xca\x8c\xa2\x71\x6b\x4b\xa0\x76\xb7\x70\x02\x86\x43\xf1\x56\x1a\xd8\x12\x6d\x84" + - "\x9e\x05\x58\x08\x48\x93\xaa\x99\xce\x55\x2a\xd6\xaa\xba\x7f\xef\x36\xe1\xa3\xc0\x6d\x76\xe1\x08\xc0\xf9\xc5\x36" + - "\x1d\x71\x6c\x5f\x8c\xb0\xb7\x9e\x08\x40\x83\x2f\x7a\x22\x2f\xfe\xca\x13\xa0\xf3\x37\x1c\x8a\x17\x32\x7f\x88\x48" + - "\x8a\x33\x98\xa8\xa9\x5c\x19\x25\x8c\xba\x52\xa5\xcc\x84\x5c\x2e\x8d\xd0\x48\xa8\x00\xd3\x9e\x9f\xbe\x1d\xbc\x79" + - "\xf5\x4e\x54\xa5\x9c\x2a\xfc\x1c\xb0\xc7\x54\x72\xfa\x41\x5c\x69\x29\x64\x79\x89\xa0\x32\x83\xa9\xcc\x32\x55\xd2" + - "\x3f\x0a\x8f\xcb\xf7\xba\x54\xb3\xe2\x46\xa4\x5a\xc1\x4a\xf1\xeb\x75\xb1\x12\x55\xb9\x16\x55\x41\x5d\x0a\xd8\x9d" + - "\xd5\xe5\x5c\x74\x70\x12\x55\xa9\xe1\x78\x43\x27\x62\x3a\x97\x3a\x37\x03\x91\x3c\x38\x7c\xf2\xe4\xc9\x57\x5d\xfc" + - "\xfe\x74\xb5\x04\xdc\x19\xb9\xce\x0f\xbf\xd9\x87\x17\xb0\x36\x40\x57\x59\x96\x62\x2c\xce\x2e\x8e\xec\x03\x03\x34" + - "\x4c\x8c\xe1\xc5\x00\xff\x76\x6f\xa6\x45\x3e\x95\x15\xbf\xa2\x1f\xee\xdd\x72\x65\xe6\xfc\x06\xfe\x74\xcf\x75\x9e" + - "\xaa\x9b\x1f\x67\xfc\x8a\x7f\xf9\x1e\x33\x69\xcc\x63\xd8\x33\x31\x16\x7f\xdc\xba\xe7\x55\x71\x5a\x95\x00\xcd\x71" + - "\xd0\x64\x60\x9f\xba\x66\x73\x69\x7e\xbc\xce\xe3\x46\xf4\xec\x2d\x12\xac\x6a\xed\x57\x45\x60\xf0\xc3\xf0\x8b\xfb" + - "\xf7\xe0\x24\xfe\x6c\x88\x76\x4d\x8b\xb2\x54\xd3\xca\xe1\x33\x90\x84\xa2\x84\x7d\xcd\xd6\x84\xeb\x8c\x3f\x76\x17" + - "\x45\x62\x64\x9e\x4e\x8a\x9b\xee\xfd\x7b\x3b\xee\xab\x31\x37\x73\x87\xab\x87\x94\xfc\x4a\x95\x06\x28\xc8\x58\x74" + - "\xf0\xf6\xeb\xd0\xe3\xe1\x50\xbc\x44\x04\x15\x52\x64\xc5\x54\x66\x62\x5a\x2c\xd7\x40\x67\x1c\xe9\x74\x34\xc5\xe3" + - "\xab\x51\x99\x82\x13\xd3\xc3\x9b\x4b\xdd\x54\x01\x89\x7f\x37\x57\x96\x0c\x11\xfd\x17\x48\xdd\xaa\x95\xcc\xb2\xb5" + - "\x78\xbf\x32\x15\xae\x56\xe7\xba\x82\xaf\x4d\x55\xae\xa0\x2b\xf1\x50\xe5\x73\x99\x4f\x55\xfa\x90\x3b\x7a\x03\x14" + - "\x10\x9b\x69\x3b\x1b\xe8\x0a\x51\x36\x15\x09\xf6\x24\xb3\xac\xb8\x16\x0a\x28\x05\x20\xe9\x84\x30\xf4\x3a\x87\x4f" + - "\x88\xaa\xe3\x1d\x9e\x02\x84\x2c\x3d\x00\xda\x42\xdd\x0d\x66\xf9\x00\x06\x68\x5d\x10\x92\x00\x07\x24\x87\xc9\xcf" + - "\xf3\xb4\x2c\x74\xfa\xf4\x4b\x60\x20\xe0\xcd\x6b\xf9\x41\x09\xb3\x2a\x95\xb8\x56\xa2\x2a\xf5\x42\x7c\xf7\xe3\x6b" + - "\x3c\x51\x6f\xbe\x3b\x7d\x7b\xff\xde\x4e\x89\x0f\xc7\x62\xf8\xeb\xd9\xb9\x39\x5f\x7d\xff\xea\xfb\xef\xcf\x6f\x9e" + - "\x1f\x5c\xec\x6f\x6a\xbf\xbf\x18\x5e\xba\xf1\x5e\xcb\x6a\x3a\x57\x46\xa4\xd2\xcc\x55\x8a\x47\x0d\x6e\x92\xa2\x14" + - "\x53\xb9\x50\x99\xfe\xbb\xce\x2f\xa1\xef\x85\x79\x5b\xaa\x99\xbe\xc1\xfe\xfb\x0b\xd3\x1f\xc2\xb5\x58\xc2\x67\xcf" + - "\xb3\xe5\x5c\xc2\xf3\x7e\x72\x76\x9e\xca\xfe\xdf\x2f\xba\xc3\x4b\xed\x46\xf8\x19\xd8\x8b\xc9\xda\x82\x02\xbb\x7d" + - "\x21\xe1\xfa\x22\x18\x4f\x80\x68\x54\x85\x28\xd5\x32\x93\x53\x95\x00\x08\x67\xbe\x55\x88\x0e\x32\xcb\x7a\x22\x53" + - "\x55\xa5\x4a\x8b\x08\x0c\x6b\x7a\x38\xa8\x8a\x9f\x97\x4b\x55\xc2\x87\x09\x01\x16\x8f\x81\xdb\x05\x31\xb6\xd3\x58" + - "\x96\x45\x55\xd8\x33\x49\x13\x05\x84\x9a\xae\x4a\xb8\x9c\x85\xc5\x62\x87\x9f\x62\xa2\x00\x30\x2b\xa3\x52\x40\x55" + - "\xbc\xec\x46\xb6\x19\xad\x35\x40\xb2\x11\x7f\xe5\xb7\xb5\x92\x65\xc5\x17\x49\x2e\xd4\x62\x59\xad\x1d\x2e\xdc\xbf" + - "\xb7\x63\xff\x1c\x89\x8e\x3f\x2f\x30\x9f\x54\xcd\xe4\x2a\xab\x44\xa6\xf2\xcb\x6a\x4e\xd7\x72\x03\xe9\x0f\xee\xdf" + - "\xdb\xa1\x06\x23\x71\x40\x9f\x57\xc5\xf3\xb2\x94\xeb\x91\x07\x5e\x0c\x2f\xa4\x79\x48\x95\x13\x22\xf8\x35\x34\xfc" + - "\xab\xa2\xd3\xf3\xa6\x9a\x0b\x95\x29\x3c\xf0\x3a\xc7\x47\x0b\xc4\x98\xd4\x3d\x36\xaa\x12\x3f\xfe\x14\x7f\x76\x3d" + - "\x2f\xb2\xf6\x96\x12\xee\xd5\x69\xa6\x64\x0e\xb4\x52\xc2\xb9\xbf\x54\x55\x30\x4f\x91\xaf\x16\xb5\xcd\x85\x27\xbb" + - "\x63\x91\xaf\xb2\x0c\x58\x01\xbc\x5a\x87\x43\xf1\x13\xbd\x75\x27\xbd\xc8\x95\x1b\x6a\x56\x16\x0b\xba\x93\x14\xf2" + - "\x51\x3b\xd4\xef\x53\x71\x20\x8e\x71\xc1\x67\xf8\x7b\x1f\xff\x1e\x30\x74\x2f\xf8\xc6\xa4\x77\x17\xc4\x5a\xd4\x46" + - "\x83\x2b\x08\xfa\xe5\x81\xe0\x52\x6c\x2c\x68\x67\xe7\x63\xe0\x7d\x07\x67\xd9\x7e\x01\xbb\xea\xba\x83\xf3\x8c\xd7" + - "\x8c\xae\x44\x91\xc3\x7d\x68\x2f\x56\xfa\x32\x21\x98\x00\x2e\x12\xf7\x76\xdd\x06\x66\x38\x43\xd0\xcb\x29\x7c\x18" + - "\x02\x17\xda\x18\xc7\x75\x43\x87\xdf\xad\x74\x96\x0a\x19\x50\xab\xb6\x0e\xa1\x31\xdc\x30\xa5\xaa\xfc\x19\x5a\xa8" + - "\xf2\x52\xd1\x02\x07\x01\xf2\x27\xc0\xa1\xd2\x38\x47\x6e\x98\xe7\x69\x4a\x9b\x94\xa5\x16\x73\xe3\xe5\x89\x04\x51" + - "\xa3\x54\x33\x60\x8f\xa7\xca\x52\xd2\xc1\xb2\x54\x57\x3f\xd2\x17\x63\x1c\xeb\xc8\xbe\xb1\x24\x74\xec\xa6\x00\x3f" + - "\xfd\x98\xbc\x65\x0c\xa7\x6c\xdd\x9f\x15\xe5\xa2\xb9\x2e\xc6\xb2\x52\x55\xf1\x26\xbd\x62\x7e\x5f\x7a\x32\x05\x74" + - "\x11\x38\xa2\xf5\xb6\x43\x61\x54\x35\xe0\x8d\xfa\x7f\x8a\x95\x98\xca\x5c\x18\xb8\x5e\xa0\x8d\x63\x8a\x1c\x1d\x70" + - "\xdb\x2f\xcb\x4b\xd3\x13\x93\x55\xc5\xfc\x9f\xa1\x3e\x8a\x3c\x5b\x23\xc9\x11\x3a\xaf\x54\x99\xc3\xcd\x36\x00\xc0" + - "\x28\x39\x9d\x87\xdb\x6a\x27\xd8\xc3\x9e\x6a\xc7\x87\x77\x0b\xbe\x49\x98\x23\xac\xb7\x0f\x16\xbe\x90\xcb\xb6\x9e" + - "\x6b\x7d\x22\xc0\x1d\x86\x25\x0e\x23\xe4\x32\xa9\xf3\x9c\x00\xa9\x9e\xd0\x8e\xf5\xe6\x1e\x6c\xc7\x7c\x4a\xb8\x15" + - "\x61\x0e\xf3\xcf\xb7\xdd\x70\x62\x78\xa6\xb6\x12\xb4\xfa\x84\xe8\x04\xca\xe5\x32\x5b\xdb\x45\x7b\xf8\x77\xa3\x15" + - "\xcf\x74\x69\xaa\xbb\x3b\x56\xbf\x27\xe2\x20\xfa\x28\x93\x9f\xf2\x4d\xff\x30\xfa\x48\xfd\x1e\x82\xd6\x81\x04\x0e" + - "\x56\xa6\x72\x8b\xc7\x44\x8d\x50\xea\xdc\x79\x2f\xc6\x62\x5f\x8b\x7d\x01\xcd\x89\x7a\x41\xcb\x91\x9d\xcd\xd6\xfd" + - "\x10\xcf\xc6\xe2\x00\xc4\xe6\xf7\xe2\x29\x7e\x72\x2c\xce\x88\xb8\xbd\xbf\x40\x42\x77\x76\x11\x4f\x2d\x4f\x3f\x02" + - "\x5b\x7f\x0c\x37\x9b\xe6\x99\x07\xe2\x5c\x23\x72\x20\x06\x5b\xbc\x05\x2c\x46\x74\xe6\xd3\xf1\x9d\x9a\xcb\x2b\x65" + - "\x04\x4a\xe3\x32\x17\x78\x5b\x3d\x34\x62\xa1\xaa\x79\x91\xf6\x90\xa7\xa2\x77\x8e\x28\xe1\x9b\x01\x13\xb6\x11\x12" + - "\x49\x80\x91\x41\x6e\x09\xf9\xf8\xa2\x44\x59\xdd\x2c\x09\x53\xf0\x19\xfe\x7d\xff\x5e\xc4\x07\xa8\x9b\x4a\xe5\xa9" + - "\xa7\x63\xb3\xdc\x3f\xaa\x81\x00\xb6\xa6\x58\xc2\x03\xd3\x13\xb9\x5c\xa8\x9e\x30\xe5\xb4\x87\xcc\x2b\xfd\xf7\xc4" + - "\xe0\xdc\x7b\x62\x9a\x15\xb9\xc2\x5d\xab\x64\x79\xa9\x48\x84\x60\x8c\x3b\x3b\xb8\x00\xa8\xfd\x71\x8b\xef\xb5\x18" + - "\x8b\x43\xfc\x8b\x2f\x9e\xa0\x65\xb8\xfb\xa9\x52\x4b\x98\x92\xcc\x0c\xc9\x27\x00\xb9\xff\x90\x79\x9a\x01\x5c\xf0" + - "\x2d\x32\xd1\x46\x83\x3c\xaf\x8b\xbc\xa6\x48\xb1\xf3\x00\xf9\x70\x52\x14\x70\x47\x39\x1d\x09\xf7\x4d\x4d\x3c\xc9" + - "\x34\x1f\xf4\x12\x89\x15\xb7\xc7\xfb\x08\x7e\x53\xc3\x2d\xab\x13\x5a\xf0\xfa\x10\x27\xf5\xfe\xbe\x93\x6b\x83\x29" + - "\x4f\x81\x9d\xbb\x9e\xab\xdc\x4e\x0c\xf8\x75\xcb\x71\x16\xa5\x30\x05\xec\x31\xfc\x48\x96\x85\x31\x7a\x92\x01\xf7" + - "\xee\xd7\xd9\x6d\x5f\xde\x6e\x4d\x4f\xb4\xcb\xbb\xaa\xcd\xf7\x76\x2f\xa9\x65\xd7\xae\xdd\xad\x80\xe6\xeb\xe6\xc9" + - "\x48\x60\x45\x80\xca\xa8\x6c\x06\x0c\x3e\x92\x61\xe0\x2e\x9c\x40\xa4\x8d\x58\x4a\x43\xbc\x20\x4e\x49\x23\x94\x79" + - "\x3b\xeb\xc3\xb8\x4b\x4b\xf7\xfb\x7e\x40\xb8\x4b\x12\x71\x84\xe7\x9a\x3e\x3c\x12\x7a\x7f\x3f\x90\x70\x7e\x84\x71" + - "\x53\x52\xc2\x54\x73\x91\x17\x79\x1f\x8e\xd9\xd0\xc9\xfa\xe2\x4a\x66\x2b\x85\xea\x1d\x9c\x45\xc2\xa8\xda\xd8\x9c" + - "\xae\xe3\x9f\x2c\x15\xc6\xfb\x0d\x97\x8b\xbb\x0d\x5b\x43\x30\x24\x65\x0a\xce\x0d\xf0\x1d\x76\xc0\xf6\xea\x94\x27" + - "\xa6\x9c\x3a\xdc\x39\xa3\x66\x17\xac\x12\x41\x84\x1c\xdb\x4f\x82\x97\xf4\x7a\x38\x14\x6f\x4b\x75\x05\x30\xcc\xe1" + - "\x22\xed\xab\x1c\x15\x0a\x59\x51\x2c\x03\x95\x4d\x80\xb9\xd8\xa1\x57\xdb\xc0\x25\xaf\xf3\x95\xf2\x1a\x18\xd7\xf1" + - "\x4f\x6a\xba\x2a\x8d\x42\xed\x89\x7a\x58\x2a\x01\xfc\x09\x74\xbe\xcc\x24\xac\x02\x97\x67\x00\xd3\xf0\xde\x35\xc1" + - "\x78\x88\x63\x7b\x7b\x34\xd8\xde\x9e\x70\x17\x9a\x36\x6f\xe1\x63\x22\x7c\x09\x62\x21\x20\x7a\x12\x9c\x7c\x4f\x47" + - "\x34\x3d\xa0\x66\x80\x6d\x7e\xda\x38\x4a\xf8\x91\x7f\xb5\x13\xf7\x65\x4f\x3b\xbf\x03\xa2\x22\xc6\x40\x74\x90\x98" + - "\xc7\x03\x99\x72\xda\x15\xc7\xf8\x72\x64\xb5\x1b\xf8\x59\xa8\x73\xba\xab\x9b\x70\x71\x51\x67\x7c\x92\x43\x08\x93" + - "\xa8\x7c\xa5\x4a\xb1\x28\xae\x94\x28\x4a\x7d\xa9\x81\xb2\x33\x5c\x99\x00\x02\x3a\x2d\xac\x8a\x2d\x42\x10\x0f\x27" + - "\x3a\x67\x04\x75\x4b\x37\x79\x9f\x43\x44\x79\x59\xe4\x0f\x2b\x31\x41\xf2\xa0\x73\xd1\x86\xf5\x6e\xa5\x0e\xbe\x48" + - "\x0e\x7c\xd3\x40\xdf\x57\x9f\x0c\xb4\x8e\xf4\x78\xf8\xdf\xdb\x90\x20\x04\x0c\xe4\xa2\x48\xf5\x4c\xab\xd4\x9f\x12" + - "\x7b\x39\x5a\x0a\xda\x72\xc5\x24\x2c\x59\xfe\x9c\xeb\xdf\x57\x8a\xb8\x47\x39\x9d\xd7\x54\x1f\xa2\xa0\x21\x96\xf2" + - "\x52\xc1\x4d\x7c\xb3\x94\x79\x5a\x8c\xac\x42\xb2\x83\xb7\xbf\x15\x48\xf7\x41\x62\x9f\x0f\x4a\x68\xb2\x48\xba\xa2" + - "\x3b\xb0\x72\xb3\x18\x9e\xbf\x1c\x5e\xf6\x44\xa7\x23\xba\xee\x0e\x7e\x6e\xcc\x6a\xa1\x02\xad\x46\xa9\x64\x4a\x5a" + - "\x9e\x62\x45\x62\x13\x3d\x21\x1d\x2c\x90\x33\xf3\x13\x3c\x18\xa1\x76\x95\x79\x83\xb2\x04\xd1\xd4\x73\x2e\x0b\x73" + - "\xe9\x88\x5c\x5d\x8d\x8a\xef\x02\x46\x20\x2f\x8a\x65\xcc\x59\x04\xca\x0e\xa5\x44\xa5\x4c\x35\x5c\xe5\xba\x1a\x4e" + - "\x8b\x52\x0d\xde\x1b\x04\x53\xaa\x2a\xa9\x33\x83\xda\x38\x45\xe2\x8e\xa7\xe7\xcc\x43\x9c\xea\x7c\xaa\x1c\x60\x0e" + - "\x07\x4f\x7a\xe2\xe5\x8f\xaf\x99\x51\x20\x49\xca\x0e\x6b\x19\x8d\x4c\x95\x15\x7d\x2c\x4b\x05\xd8\xc5\x1a\x33\x95" + - "\x0e\x40\xdc\x5e\x0b\xa7\xca\xcd\x90\x5f\x11\x27\xaf\x44\xf2\xe0\xf1\xb7\x5f\x7f\xd3\x1d\x20\x6c\xec\x14\x42\x68" + - "\x14\x93\xf7\xed\x1c\x37\xdc\x53\x49\x31\x79\xdf\xa5\x2b\xd8\x7e\xd1\x09\xa0\xc3\x27\x79\x44\x0c\x90\x3d\xd8\xf6" + - "\xdd\x2f\xa8\x60\xbb\x7b\x2c\x78\x62\x89\xfb\xde\x1e\xfe\x84\xd1\x8a\xc9\xfb\x01\xe9\xe7\xa2\xd1\xde\xac\x16\xaa" + - "\xd4\xd3\x2d\x5d\x0e\x87\x62\x29\x4b\xa3\xbe\xcf\x0a\x59\x89\x37\xf2\x8d\x01\x49\x18\x3e\xe8\x4f\xa5\xa9\x18\x2c" + - "\xcb\xc2\xe8\x4a\x03\xf7\x86\x5c\xdf\x06\x10\x65\x83\xaf\x36\x9d\x4e\x97\xfb\x19\x0c\x06\x20\xce\x2c\xb4\x41\x16" + - "\x70\x59\xaa\xca\x88\x4c\x49\xa0\xf6\xfd\x7c\xb5\x98\xa8\x92\xaf\x7e\xd3\x83\x41\x2b\x3d\x5d\x65\xb2\xcc\xd6\x62" + - "\xae\x6e\x44\xa6\x2b\x55\xca\xcc\x88\xa4\x73\x70\x33\x18\x0c\x5c\xb7\x66\x35\xa9\x4a\x89\x33\x07\x3c\x99\x2a\x10" + - "\xc0\x67\x3a\xd7\x95\x56\x46\x54\x05\x4c\x3a\x00\xce\x6e\x8d\x60\xf2\x62\x19\x4e\xfd\x60\xb5\xf6\x15\xb0\xcd\x11" + - "\xc4\x02\x12\xb9\x1d\x6a\x6f\x8a\x2a\xbe\x65\x46\xfc\xa2\x2f\x9e\xe7\x4e\x55\x53\x94\x44\xba\xc4\xf5\xbc\x00\x9a" + - "\x65\x79\xe3\xb3\xb3\x17\x99\x34\xe6\xe2\x82\x4d\x50\xd5\xda\xea\xfd\x3b\x67\xfc\x29\x4d\xe0\xa2\xe3\xba\x05\x4c" + - "\xcf\x8b\x54\x19\xf7\xc4\x1b\x6a\x90\x18\x86\x38\xc8\xb3\x8d\x38\xa5\xcd\x06\x71\x04\xfa\x78\xb7\x5e\x2a\xf8\xed" + - "\x80\x45\x78\x67\x3f\xab\x09\x6e\xfe\x82\xe2\xab\x01\x87\x83\xbe\x42\x2d\xeb\xde\x1e\x91\xd6\x5d\x52\x55\xb3\x94" + - "\x57\x6b\xe5\xb5\x70\x3d\xd1\xd1\xe6\xad\xfd\xf5\xe3\xac\xf3\x09\xe3\x0e\x87\xe2\x64\x46\xd6\x38\xde\x16\x31\x97" + - "\x06\x4e\x35\x7d\xa1\x52\x21\x33\xa4\x6e\x3d\x66\x08\xa6\x45\x3e\xd3\x29\x30\x1f\xd5\x5c\x5a\xfb\xda\xa6\x98\xbc" + - "\xdf\x10\x2f\x1a\x6e\x61\x8f\x8c\x61\xa4\xbb\xfc\xe3\x16\x36\xcf\xcd\x5c\xa5\xcc\x91\xa9\x6b\xde\x99\x50\x5a\x2a" + - "\x89\x3b\x71\x18\xf4\x6a\xb1\xac\xd6\x77\x62\x10\x48\x19\x70\x2f\xe1\xea\x6a\xbc\x97\x6f\xd5\x0a\x88\x6d\xc3\x02" + - "\x18\xb7\x8c\x66\xf7\x4b\x8c\x6b\x3c\x61\x40\x51\xf6\x45\xa7\xe3\x87\x68\xd1\x4b\x8b\xa7\xe2\xcb\xc1\x41\x4f\xe8" + - "\x1f\x4f\xc5\x53\xf1\xb5\x70\x36\x5e\x6d\xe6\xe2\x27\x75\xf9\xea\x66\x19\xea\xc2\x99\x65\xb7\xd4\x29\xc4\xc2\xfa" + - "\x2b\x47\x26\xd9\xec\xe7\xcd\x1e\x67\xce\x64\x42\xe8\x84\xa4\x15\x05\x0f\xd7\x1f\xd9\x02\x7d\x97\x35\x8d\x0e\x1c" + - "\x3f\xb4\x7c\x4a\x61\xc8\x54\x8f\xea\x3b\xb6\xc6\xb1\x02\xe9\xfe\xbd\x1d\x7a\x00\xcd\x23\x5d\x48\x91\xaa\x70\xcb" + - "\xa8\x0b\x12\xd4\x75\x9e\xea\x92\x74\x54\xea\x4a\x66\xcc\xc7\xe0\x17\x8e\xef\xa9\x4a\xbd\xb0\xbd\x1c\x05\x67\x27" + - "\xec\x37\xc0\x6a\x7c\xac\xad\x73\x80\x04\xda\xa1\xd3\x1e\xd0\x88\xac\xb8\x5c\x59\x3a\x8c\x52\x1f\xd1\x46\x34\x93" + - "\xc1\x4d\xae\xc4\xb2\x94\x97\x0b\xd9\x73\x36\x6b\xec\x6b\xb2\x16\x3a\x07\x38\xc1\x75\x2a\xdd\x67\x04\x88\x4a\x02" + - "\x97\xc5\x1a\x39\x6b\xd2\x19\xd0\xda\xec\x24\xad\x69\x2b\x09\xcd\x72\x74\xbb\x1d\x06\xd2\x01\x75\x38\xf6\xbd\xd0" + - "\x49\x7a\x45\x2a\xb3\xa4\x43\x0d\x3a\xd6\x8a\x4a\x3f\x07\xac\xca\x83\x71\xf8\x85\xfb\x7e\xae\x64\x3a\x90\xcb\xa5" + - "\xca\xd3\x17\x73\x9d\xa5\x89\x9d\x74\x77\xb0\x84\x8b\xbc\x42\xd3\x78\xa9\x80\x31\xad\x35\x60\x43\x6c\xc8\x0f\x83" + - "\x64\x55\xcd\x55\x79\xad\x8d\xea\x09\x79\x05\xd8\x0c\x8b\xb6\x24\xd5\x59\xc1\x7b\x42\xe7\x46\x95\x21\x8c\x81\xa9" + - "\xc0\x71\x64\x06\xe0\x5c\x19\x04\x65\x2e\xdc\xf6\x33\x2a\x01\x0e\xb0\x7c\xc1\x6f\x82\x8d\x8f\x78\x4d\x87\x9c\x2f" + - "\x8a\xfc\x4a\x95\x95\xb5\xc4\x54\x85\x70\x46\x90\x23\x52\x02\x4e\xd6\x84\x17\x86\x98\x9b\x54\x56\x92\xf9\x36\xd6" + - "\x17\xbe\xd6\xd3\xb2\x30\xc5\xac\x82\xbb\xf1\xb2\xa8\xa0\x93\xf9\x6a\x81\x12\xbd\x2e\xc5\x95\xca\xd3\xa2\x14\x4b" + - "\x32\xe4\x24\x0f\xbe\xfd\xea\x2f\x8f\xe1\x90\xba\x71\x42\x64\x67\xb9\xbc\x66\x36\xa0\xd3\xe7\x58\x4e\x67\x16\xea" + - "\x89\xce\xc2\xf4\x3b\x21\x3b\xea\x6d\x43\x3d\x11\xd8\x73\x62\xde\x30\x55\x6f\xe4\x42\xd5\x35\xd4\xa4\x6a\xa9\x8d" + - "\x0d\x2f\x06\xf6\x0b\xb8\xc2\xa3\x07\x83\xaa\xf8\xa1\xb8\xb6\xa6\x1f\x44\xc9\xbc\xf1\x38\xa6\x06\xa8\xfa\xd4\xc4" + - "\x6f\x06\x7a\x2a\x79\x49\x9a\xaa\x16\x35\x6b\x31\x79\xdf\xd4\x9d\x7a\x7a\x80\x97\x3b\x93\x03\x31\x46\x53\xcc\x4e" + - "\xa0\xe3\x81\xcb\x2f\xd4\xed\x69\x27\xf3\xf1\x5f\xc0\xa3\x32\xa5\x0e\xc9\x43\x38\x0c\x6b\x1b\xea\x42\xe4\x47\x74" + - "\x09\x3b\x30\x3f\x60\x3c\xc6\x5e\xed\xca\xaa\xd1\x62\xf2\x1e\x35\x04\x81\x26\x38\x14\x59\xf9\xb3\x31\xcb\xa5\xa1" + - "\xd8\x3a\x29\x95\xfc\x10\x48\x89\x81\x20\x15\x49\x9f\x34\x37\x5d\xbf\xcc\xfe\x87\xa7\xe4\x0d\x11\xc2\x2c\xd5\x54" + - "\x93\x13\x92\x81\x6b\x1e\xb0\xd2\x3a\xc0\x2c\x0a\x53\x89\x29\xfa\x0a\x91\xca\x72\x86\x12\x1b\x9e\xd6\x70\x55\x7f" + - "\xda\x36\x38\xbe\x88\x97\xac\x7b\xee\xc7\xff\xd9\xcd\xf8\xf7\x4f\x2c\x60\xe5\x3c\xe7\xf1\x49\xd6\x70\xb8\x48\xc3" + - "\x73\x19\x7a\x06\x58\x86\x03\x6f\x13\x6f\x34\xdc\xd9\xd9\xe9\x58\xf6\x80\x3f\xd8\x47\x51\x39\x20\x58\xd0\x2d\xc9" + - "\xcf\xf1\x2c\x4a\x65\x56\x59\xf5\x11\x5a\xb1\x90\x1f\x54\xdd\xe6\x2a\x64\x59\xf6\xdc\xe7\x01\xa5\x20\x33\x9a\x7d" + - "\xb1\xd9\x78\xe5\x0d\x9f\xf8\xb2\xa1\xb0\x0b\x31\x8e\x08\x05\xeb\x6d\x64\x59\x46\xba\xa6\xd8\x38\x57\x2a\x66\x50" + - "\x1c\x57\x84\xbe\x30\xc0\x68\x11\x31\xb7\x6c\xd6\xce\xce\x19\xbe\xba\x10\xa8\x39\xa7\x67\x6d\xd7\x27\xea\xdf\x19" + - "\x3d\xa0\x77\xfc\xaa\x76\xad\xdd\xdf\x66\x56\xd3\x79\x03\x46\x44\xf0\x11\x52\xba\xb6\x89\x34\x55\xde\x43\xd1\x3f" + - "\x14\x23\xeb\x6a\xc3\xe3\xe3\x57\xce\xc0\x14\x5a\xb1\x60\xf5\xe1\x28\x68\xe4\xe9\x09\xa3\xa6\x45\x9e\x36\x0d\x2f" + - "\xfb\xf4\xa2\x61\x7b\x39\xf0\xe4\x1c\x7b\xe0\x06\xbc\x59\xf6\xbc\xb3\x8d\xe5\x48\xbc\x0f\x0e\x3b\xb6\x3f\xc3\xf3" + - "\x7f\x21\xc6\x3c\xf2\x99\x78\xcf\xaa\x52\x86\x52\xd8\x2b\xdc\x04\x47\x11\xf0\xf0\x6d\xb0\xac\xcb\x52\x2d\x1b\xe6" + - "\xdc\xf0\x4a\xd2\xc4\x43\x04\xeb\xb3\xef\x4e\xe0\x8d\xe1\xeb\x69\xc1\x5e\x1f\x63\x71\x76\xb1\xfd\xc2\xc2\xde\x23" + - "\x90\xd8\xce\x5e\xdd\x2c\x89\xd7\xdd\xa5\x01\xbd\x01\xe1\xaf\x85\xf3\xdd\x22\x9b\x27\xda\x46\x50\x83\x6e\xe4\x95" + - "\x35\x5b\xeb\x4a\x2d\xac\xe4\x8a\xce\x91\x4b\xf2\x7d\x53\xc4\xe4\x4a\x90\x20\xed\x2a\x43\x40\x6f\x23\xac\xb5\x45" + - "\xc2\xc4\xec\x23\x06\x92\xa5\x62\x16\x53\x89\xa7\xad\x7d\x06\x02\x72\x6d\x89\xee\x58\x31\xc8\xd0\xc8\x16\xf6\x79" + - "\x07\xea\xf3\x27\x0d\xae\xe3\x63\x84\xe4\xee\x2d\x86\x0e\x3e\x9d\xe9\x68\xee\xe1\x16\xb6\x83\x2d\xf6\x3d\x2b\x09" + - "\x7a\x7f\xb9\x3b\xf6\xb5\x2a\x65\x6e\x32\x89\x02\x05\x6a\x36\x8b\x99\xdf\x5f\x41\xc2\x84\x2e\x51\x4e\xae\x99\x2a" + - "\xea\x77\xe7\x47\xaf\xce\xfa\x05\x55\xdb\x57\x86\x8b\xbb\x98\x82\x7b\xa9\x4e\x49\xd9\xad\x00\xf7\x91\x5a\x74\xeb" + - "\x7a\xe0\xe6\xa2\xc9\xea\xff\x41\x39\x6d\x2d\x6b\x09\x1a\x9c\x41\x70\xc3\x06\xce\x16\xff\xe3\x2b\x08\x97\xf1\x7d" + - "\x26\xab\x4a\xe5\x42\xe6\x6b\x91\x2b\x53\xa9\x34\xb0\x80\x58\x73\x3c\x7a\x3a\x5a\x16\xec\xec\xa2\x87\x77\x54\xed" + - "\x22\x7c\x6e\xc5\x9b\xbf\xfe\x7c\xf2\x52\x4c\x8b\x15\x20\x30\xa2\x32\xab\xbd\x80\x44\xad\x74\x3a\x42\xf3\x26\x5b" + - "\x7a\x75\x9e\x0a\xe9\x55\x34\x55\x21\xa4\x95\xb4\x7b\x6c\x27\x42\x8f\x3d\x54\x02\xe2\x5f\x38\x09\x12\xac\xd6\xee" + - "\xd0\xb0\x79\xf4\xfe\xbd\x9d\x65\x59\xdc\x44\x37\xc8\x2c\x6f\xf8\x07\xa2\x7f\xe5\x62\xd9\x63\xcf\x0a\xfc\x24\xbc" + - "\x61\xf9\x2e\x74\x1e\x24\xe1\x7d\x68\xa1\x5c\x2d\xd0\xfa\x9a\x9f\xb9\x66\x6c\xe4\xf2\x7e\x27\xb3\x9c\x9e\xa0\x67" + - "\x59\xb5\x58\xd6\xd4\x53\x7f\x5b\xe9\xe9\x07\x31\x9d\x2b\xf2\x70\x4b\x55\xa5\xca\x85\xce\xd1\x5c\xe1\x6d\xa0\x80" + - "\x0f\x72\x92\xa9\x9e\x75\x26\x01\x06\xd5\x11\x47\x6d\xc8\xd5\xd0\x08\x29\xde\xad\x97\x0a\xd5\xec\xe4\x2b\x72\xad" + - "\xc4\xb5\xce\x32\xf2\x80\xe2\x7d\x74\xa6\x8f\x81\x5b\x6b\x8b\x41\x54\xcc\xf2\xa6\x82\xcd\x7d\x5a\x5b\xc5\xa9\x5e" + - "\xac\x32\xd2\x84\xe9\x3c\x85\x87\xc8\x97\x8f\x23\x27\x32\xb7\x43\x3d\xf1\x98\xb1\x11\x81\xde\x34\xa9\xfb\xcb\x2d" + - "\xb7\xe8\x66\x01\xca\x8e\x05\xb4\x6b\xec\x7c\x9b\xb4\x0f\x83\xd3\x67\x37\x11\x4f\xa5\x4e\xd9\xff\x0c\x90\x10\x68" + - "\xd1\x8a\x0c\x2f\x73\x34\x40\x97\xc2\xfa\x1b\x81\x00\x59\xcc\xbc\x09\x8b\xdf\xf7\x84\x29\x84\xae\xd0\x6b\x67\xa2" + - "\x48\xce\x47\x13\x2f\x2d\x65\x80\xbd\xc2\xa6\xd7\xff\xf2\xba\x53\xf8\x89\xd6\xef\xe0\x68\x59\xe4\xf3\x52\xef\xf5" + - "\x08\x63\x26\x06\x79\x71\xed\xce\x09\x77\x60\x5d\x78\x59\x01\xcc\xce\x3f\xe2\x45\x51\x2a\xdc\x73\x8a\xe3\x58\x96" + - "\x05\x19\x33\x65\x55\x01\xd9\x45\x32\x4b\xfd\xb0\x0a\x99\xd5\xe1\xba\xe2\x35\xe5\x4a\xa5\xf8\x44\xdd\x68\x83\x7a" + - "\x1d\x63\x79\x6b\xfe\xe3\xfe\xbd\x5b\x22\x3e\xc3\xa1\x78\x5b\x2c\x71\xcb\x49\xdf\xe0\xfd\x97\x17\x72\xe9\x4d\x5c" + - "\x72\x3a\x4f\x3a\xdf\xb1\x9f\xc0\x1b\x52\xe9\xb3\x47\xb3\x45\x34\x32\x6b\xe0\x62\x59\x29\xc8\x5c\x2b\x59\x8b\x3a" + - "\xe8\x9f\x51\x25\x1d\xd1\xe9\x06\x2e\x43\x9a\xe4\x7f\x42\x97\x50\xfd\xe7\xd4\xe1\x1d\xb1\x4f\x2a\x82\x7d\xd1\xb9" + - "\xe8\x20\x7f\xd5\x2a\xed\xf3\x8a\x1c\xf1\x69\x0a\xda\xce\xcb\x63\x9b\x98\xce\x3e\xa2\x4d\x75\xfa\x51\x1c\xb8\x52" + - "\x57\x5e\x7e\x54\x9f\x5e\xd7\xe6\xde\xfa\xfe\x22\xc5\x3c\x69\xd7\xf6\xf6\x6a\xde\x05\x75\xb5\x2f\x7e\x1d\x68\x5b" + - "\x69\x3e\x48\xe7\x71\x32\x76\x7d\xe3\xb1\x38\x10\x9b\x8d\x5d\x5a\x31\x0b\xdf\x74\xc8\x32\xd3\x09\x86\x7b\x46\x6e" + - "\x44\x89\xfd\xdd\x47\x55\x9f\xb6\xc2\xda\x2d\x79\x9e\x53\xe8\x92\x18\xdf\xbf\x67\xa3\xa2\xf8\xc9\x8b\xd3\x53\x71" + - "\xca\xde\xad\xe2\x55\x7e\x09\xd4\xef\xea\x70\x70\x78\x30\x38\xfc\xf6\xf3\xc2\x9c\x0e\x9f\xfc\x5f\x11\xe0\xf4\x65" + - "\xff\xf0\x1b\x8e\x6c\x4a\xea\x81\x15\xd6\xb1\x12\x63\x02\x7a\xfe\x8c\xc1\x9f\xaf\x6e\x96\x65\x8f\xbc\x5d\xdf\xc1" + - "\xd5\x87\xa6\x81\xff\x7a\xfd\x43\x0f\xbd\x75\x3f\xa8\x5c\xff\x1d\xd9\xb8\x69\xb1\x58\xea\x0c\xff\x24\xaf\x60\xf8" + - "\xab\x58\xc1\xcd\x51\x98\xea\x05\x5f\x9c\xec\xf8\x74\x92\x2f\x57\xf8\x63\x2e\xcd\xcb\xd5\x32\xd3\x53\x59\x29\x47" + - "\x52\x7e\x40\x3f\x7b\xe7\xb0\x7f\x25\x01\x26\x3b\x46\x55\x2f\xbd\xc7\xfe\x4e\x1a\xff\xfd\x0a\x84\xa9\xe0\xf1\x89" + - "\xf9\x8f\x77\x34\xc9\x72\xb2\xba\xbc\x5c\xff\xed\xf4\xb9\xff\xc1\xce\xe3\x3d\xe4\x5a\xdd\x9f\xb0\x07\x52\xe7\xc6" + - "\xcd\xe3\x24\x37\x95\xcc\xa7\xaa\x8f\x9a\x97\x99\x9e\xa2\xea\xd2\x9b\xba\x05\x5c\xbe\xb8\xff\x70\xae\xfb\x09\xb0" + - "\x8b\x00\xf2\xa4\x8b\xec\xe8\x12\x7d\x42\x4b\x95\xbe\x2c\xa6\xad\x51\x07\x3b\xa9\x2e\xcb\x15\xba\xbd\x1c\xd0\xdc" + - "\xd1\xd9\x01\xff\x46\xf2\xf1\x42\x4e\xe7\xc8\x79\xa1\x1e\x1a\x7f\x25\x5d\x07\xf8\xad\x6f\x79\x2b\xca\xad\x0d\x60" + - "\x0b\x7e\x2c\x01\xaf\x22\x2f\xf5\x9e\x98\x44\xb6\x16\x89\x67\xcb\x3d\x8b\x36\x0b\xf8\x06\x3e\xc2\x91\x39\xe7\xa0" + - "\xee\x8f\x9d\xab\x52\x66\xfd\xe5\xaa\xc4\xd0\x2f\x34\x45\xc9\x1c\x39\x2e\x53\x95\xde\xe1\x61\x6c\x59\x1b\xf7\x08" + - "\x26\xfa\xfa\xf9\x7f\xfd\xf7\x9b\x57\x7f\x7d\xfe\xee\xe4\x3f\x5f\x09\x20\x27\x4f\x9f\x8a\x27\x87\x8d\x0d\xb2\xb6" + - "\x73\x42\x28\x8a\x3a\x49\xfe\xb8\xed\xd6\xe2\x4d\xa0\x47\x1b\x51\x83\x1b\x54\x2c\x6d\x54\x4c\xb1\xec\xb1\x87\xde" + - "\x7f\xe7\xb2\xd2\x57\x2a\x08\x97\xb1\x6f\x6a\x8f\x1a\xa1\x38\x3d\x1f\xae\x42\xee\x61\xcb\xa5\x4a\xfb\x29\x46\x5b" + - "\x70\xa0\x0d\xba\xf8\xc0\x3d\xfd\x10\xaf\x48\x21\x05\x8f\x56\xe4\xe8\xc3\xd0\x16\x8f\x03\x44\x30\x16\xab\x42\x66" + - "\x31\x96\x9d\x62\x57\xcc\xa3\x16\x11\x34\x96\x4e\xe8\x16\x98\x6b\x73\xa6\x2f\x70\xb3\xc3\xee\xdd\x9e\xea\x9a\xee" + - "\xdf\x3e\xef\x1f\x06\x9b\xcd\x8e\x77\x80\xcc\x1d\xe4\x1c\x55\xba\x21\x42\xa0\xd2\x8d\x34\xeb\x7c\xba\x91\xab\xaa" + - "\x98\x15\xd3\x95\xc1\xbf\x96\x99\x5c\x6f\x90\xee\x15\x99\xd9\xa4\x70\x56\x36\xa9\x36\xc0\x51\xa6\x9b\xb9\x4e\x53" + - "\x95\x6f\xb4\x59\xc8\xe5\x26\x2b\x8a\xe5\x66\xb1\xca\x2a\xbd\xcc\xd4\xa6\x58\xaa\x7c\x53\x2a\x99\x82\xdc\xb9\xe1" + - "\xa8\xb7\x74\x63\xa6\xc5\x52\xa5\x3e\x0a\xe1\x27\x75\xb9\xca\x64\x29\xd4\xcd\xb2\x54\xc6\xe8\x22\x37\xf6\xd5\x2f" + - "\x73\x5d\x29\xb3\x94\x53\x25\xa6\x73\x59\xca\x69\xa5\x4a\x63\xc9\xe9\xf5\xf5\xf5\xe0\xfa\x09\x92\xd3\x77\x3f\x0d" + - "\xa7\xc6\x3c\xe9\xdb\x28\x07\x33\x7c\x70\xed\x3e\xbd\x7f\x6f\xc7\xff\x80\x45\x9f\x9d\x9f\xdf\x3c\x3e\x38\x3f\xaf" + - "\xce\xcf\xcb\xf3\xf3\xfc\xfc\x7c\x76\xd1\x61\x94\xb8\xa3\xeb\x75\x5e\xc9\x9b\xe1\x03\x3f\x0f\x38\xbf\xf6\xc7\xab" + - "\x7c\x5a\xa4\x14\x69\xd5\x49\x8e\x47\xe7\xe7\xe7\xe7\x83\xcd\xd9\xf9\xf9\x75\xff\x62\x73\xf6\xeb\xf9\xf9\xcd\xc1" + - "\x41\xff\xfc\xfc\x46\x1e\x5c\x74\xf7\x3b\x01\xf9\x2c\x8c\xca\xd0\x35\x46\x65\x2a\x05\xc1\x0f\x6e\x33\x34\x20\xeb" + - "\x99\x86\xdb\x26\x1c\x0d\xe4\x23\x60\xa2\x7f\x5f\x15\x95\x75\x52\x12\x66\x5e\xac\xb2\x14\xb8\x49\x59\xff\xf8\x93" + - "\xe0\x24\x2b\xba\xce\x94\x7f\x48\x43\xd1\x59\x14\xb4\xee\x51\x7b\x67\x2f\x4e\x4f\x1f\x1f\x0e\xcd\x1a\x2e\x4b\x39" + - "\x98\x57\x8b\xec\x01\xce\xaa\x9f\xaa\x59\xdf\xcf\x04\x0e\x8c\x9f\xd6\x58\x34\xc0\xe6\x55\xa4\x9d\xeb\x4e\x4f\x74" + - "\xae\x1f\x44\x2e\x46\x76\x8a\x2e\xa0\xc5\x6c\x99\xcf\x47\xd7\xe5\x9e\x22\xf6\x9f\x9f\x9f\xc1\x7d\x10\x60\xc7\xbe" + - "\xe8\x3c\x4a\xe0\x59\x73\x67\xf7\x45\xa7\x9b\x1c\x8f\xea\x1f\xb0\x5c\xf0\xe3\x52\x95\xa8\x54\x4a\xa6\x72\x59\xad" + - "\x4a\x25\xd0\xf0\xb5\xd3\x79\x94\x9c\x3d\xfa\xf5\x8b\xcd\xee\x3f\x2e\x8e\xc7\xdd\x2d\x1f\x77\xfc\x0a\x49\x89\x21" + - "\x16\x20\x70\x4d\x54\x6d\x47\x8d\x38\xb3\xbd\x7f\x75\x81\x0e\xad\xe4\xdf\xe2\x1f\x3f\x41\x2f\x02\xfe\xf1\x25\x79" + - "\x73\x74\x1e\x25\xc7\xa3\x87\x89\x47\xcb\x5f\xe1\xdf\x87\x17\xdd\x47\xdd\x87\x9b\xf3\x4e\xfd\xc5\x79\x07\xde\x9c" + - "\x77\x36\x08\x87\x60\xdf\x00\x00\xdd\x4d\xeb\x1a\x3a\x8f\xce\xcf\x2f\x18\xaf\x97\x46\xad\xd2\x02\xe1\x3b\xba\x1b" + - "\x94\xe7\xe7\x09\x34\x60\x20\xbc\x2b\x44\xa9\xd2\xd5\x94\x44\x02\x76\xe0\x29\x66\x7e\xcf\x51\xc2\x40\xfd\x1e\x33" + - "\x33\x56\x9a\x5d\x96\xea\x7b\x9d\x55\x20\x5e\xd1\x4d\xee\x85\x38\xeb\x25\x73\x38\x10\x7c\x6a\xdc\xfe\x3c\x39\xf2" + - "\x80\x0a\xa1\xf6\x15\xed\x5b\xf2\xf9\x10\xeb\x6e\xfc\x6a\x1e\x0f\x84\xd1\x8b\x65\xa6\xfc\x80\x5f\x73\xc7\xb5\xaf" + - "\x93\xee\xd9\xf9\xf9\xc5\x05\x7c\x2b\x02\xf4\x04\x18\x3d\x0a\x7b\x7c\x02\x5c\xe8\x9a\xdc\x97\x51\x1b\x54\xc7\xb4" + - "\xc1\x23\x6e\xdc\xe9\x9e\x9f\xc3\x46\x79\x3a\x43\x5e\x51\xc8\xc5\xe6\x45\xde\x57\x66\x2a\x97\x2a\x15\x55\x29\x75" + - "\x06\x2f\xfc\x7e\xf6\x18\x0e\xf0\xd4\x14\x0b\x85\xed\xaf\x5b\xc9\xf0\xb2\x54\x53\xde\x90\xb9\x12\xa8\x01\x2a\x83" + - "\x20\x41\xe0\xb1\x48\x22\x4b\x44\xe7\xd7\xe6\x39\xdb\xdf\x00\x24\x7e\x65\x28\x5c\x74\x2d\x58\xba\x8f\x1a\x28\x26" + - "\x3a\xfb\x5f\x00\x59\xb8\x74\x54\xa1\x9c\x16\x8b\x85\xfc\x84\x51\x1e\xf5\x5a\x9e\x51\x37\xd8\xc9\x44\xe7\x12\x91" + - "\xeb\x13\xba\x4a\xce\x9e\xed\xff\x83\x36\x2a\x7e\xd3\x32\xe1\x47\x7e\xaa\x6e\x53\xff\x06\x18\xd8\x18\x69\xdc\x3a" + - "\xd2\xaf\xe7\xe7\x17\x0f\xcf\x3b\x17\x8f\x8e\xdb\x3a\xc7\xd3\x16\xc1\x83\x4e\x5d\xad\x6f\x7b\x14\x69\xb5\x11\x09" + - "\x6e\x2e\x36\x3e\xe9\x5f\xb8\xae\x91\xef\x06\xd9\x82\xe3\x18\x77\x3a\x27\x2f\x3b\xa3\x5a\x07\x0f\xee\x38\xe9\x0c" + - "\xed\x9d\xce\x8b\x1f\x9e\x9f\x9e\x36\x3e\x3d\x3f\x1f\x7c\xca\xc7\xef\x9e\xff\xb5\xf1\x69\xfb\x77\x8d\xcb\x04\xf6" + - "\x22\xee\xec\xf9\xbb\x77\x3f\x35\x7a\xab\x1d\x40\x6e\xfa\xf6\xf4\xd5\xcf\x2f\x7f\x6c\x6d\x1c\x81\x77\xa7\xf3\xe2" + - "\x3f\x4e\x7e\x68\x42\x66\x94\x20\xf7\x83\x76\x96\x4d\x26\x4d\xb5\xc9\xab\x39\xfc\x7f\x1f\x7e\x74\xfb\xc9\x74\xae" + - "\xb3\x74\x53\xcc\xfa\xc0\x56\x33\x59\x6c\xa3\xb1\x40\xc7\xd5\x95\xca\x37\x45\x9a\x6e\x92\xe4\x6c\xbf\x7f\xb1\xe9" + - "\x26\xe7\xe7\xe9\xa3\x6e\xde\xa4\xca\x02\xa9\x3e\xb7\xda\xd6\xdd\xf9\x79\xba\xdf\xdd\x74\xdb\x31\x0c\x29\x88\xe8" + - "\x68\x07\x34\xe0\x1b\x9b\x5b\x40\x37\xa2\xe3\x29\x01\xcc\x5f\x44\xdf\x71\x9c\xce\x0a\xfd\x11\x45\x86\x89\x4b\x30" + - "\x30\x1f\xa8\x23\x10\x69\xd8\xea\x81\x36\x89\xf5\xc0\xfc\x45\x61\x63\x54\x4c\x02\x4f\xfc\xf6\xc7\x53\x32\x74\xb0" + - "\x9b\xf6\x6f\x74\x23\xfc\x86\x93\x42\xad\x13\xcb\xac\xad\x9b\x54\x5b\x17\x1d\xe1\x91\x87\xa4\xfa\x7d\x73\x59\x6d" + - "\x32\xda\x16\xbf\x4b\x7e\x23\x10\x58\x75\xd0\x26\xc7\xa3\xfe\xf9\x79\xda\x3d\x46\xf8\x6f\x83\x5f\x72\x3c\x3e\xfb" + - "\xb5\x7f\xb1\xf9\xc2\x41\xd2\x73\xe1\xa5\x06\xc9\xda\x60\xb4\x73\x72\x3c\xc2\x5f\xcc\x86\x6f\x60\x31\xb2\x54\x72" + - "\x33\x59\x55\x55\x91\x77\xbf\x18\xa2\xac\x5f\xce\x95\x24\x51\x70\xf8\xeb\xfc\x3c\xa5\xa7\xf0\xdc\x09\x42\xc3\x5f" + - "\xcf\x7e\xfd\xe3\x62\xff\xfc\x8f\x73\xf3\xe8\xfc\x8c\x1f\x9f\x5f\x0f\xbd\x7f\x9a\x34\x3a\x5b\xf7\xd1\x2b\x15\xf8" + - "\xf7\x61\xa9\xaa\x52\xab\x2b\xf8\x5b\x9c\xbc\x84\x7b\xf0\xdd\xf3\xbf\xc2\x3f\x78\x58\x45\xc8\x3b\x95\xbf\xaf\x34" + - "\x5a\xad\x4a\x3b\xe9\x07\xc9\x19\x70\xb8\xfb\xdd\x4d\x72\x7e\xbd\xdf\xdd\x9c\x0f\xec\x83\xee\x17\x3c\x66\x69\xf4" + - "\x24\x23\xc6\x78\x78\xb6\xff\x8f\x0b\x0a\xea\xa6\x0b\x08\x9e\x3d\xdc\x9c\x9f\x07\xc1\xe2\xc0\xef\xd0\xcb\x2d\x6c" + - "\x7e\x0b\xc7\xc9\xb7\x59\x3f\xe2\x95\xcb\x55\xee\x06\x89\x90\x02\xaf\xdc\xb3\xf3\xf3\x54\xf6\x67\x17\x7f\x1c\xf6" + - "\xbe\xbe\x6d\xee\xde\xf1\xa6\x71\x02\x45\xa7\xbb\x19\xd0\x36\x32\xd5\xdd\x99\x05\x43\x78\xb1\xef\xbf\x7b\xbc\x80" + - "\xd4\xfd\x11\x48\x31\x81\x3c\x38\xd7\x97\x20\xa8\x76\x0e\x6e\x60\x2c\x7b\x25\xf7\xc5\xc1\xcd\xe1\xc1\xc1\xc1\x81" + - "\xcd\x6e\xf2\x46\xbe\x11\x0b\x3c\x5a\x70\x13\x4f\x8b\x54\x2d\x0b\xed\x52\xb7\xd4\xd3\x52\x3c\x7d\xfc\xa5\x3d\x45" + - "\x45\xf9\x41\x96\xc5\x2a\x4f\x31\xa9\x40\xae\x8a\x95\xf3\xb5\x16\xce\x63\xda\xe5\x62\xd9\x87\x79\x04\x12\x23\xce" + - "\x6e\x77\x3c\xa6\x3f\x36\x9b\x96\xb5\x90\x55\xdf\x4e\x9c\x1c\x1f\xb0\x35\x46\x11\xde\xb7\x41\x16\xdf\xbd\x7e\x2b" + - "\xa2\x69\xef\xec\xb0\x8b\xe5\xac\x2c\x16\x2f\xe6\xb2\x7c\x51\xa4\x2a\xa1\x81\xf6\xed\xf2\x5d\xd6\x15\xbb\x4a\xa2" + - "\x15\x32\x13\x6f\x33\x99\x2b\xdf\xa3\x48\xcc\xaa\x2c\x8b\x4b\x59\x29\xb1\x94\xba\xec\x7e\x6c\x88\x67\xcf\xc4\xe1" + - "\x81\xd8\x88\x83\x9b\x97\xdf\x1c\x1c\xf4\xe8\xe1\x9e\x38\xb8\x79\xf2\xfd\xf7\xf4\xf8\xc5\x81\x8d\xc4\xb4\xda\xea" + - "\x1f\x97\x95\x5e\x00\xc7\x09\xf4\x08\xbd\x13\xd8\xae\xf0\xdf\x3d\x4c\x9a\xf3\x83\x36\x15\x1c\xee\xaa\x5c\xe3\x06" + - "\x07\x4d\x60\x3a\x09\xe9\x32\x42\x33\x43\xa8\x72\x1a\xe0\x15\x00\xfd\x18\x41\x0a\xa9\x9d\x2d\xaf\xef\xdf\x23\x87" + - "\x89\x76\xc7\x95\x03\x9b\x05\xa3\x52\xd3\x4a\x18\x9d\x51\x12\xa0\x19\x33\x79\x7e\x52\xa4\x5d\x39\xdb\x36\x09\x17" + - "\xad\xee\x54\xc4\x47\xf7\xef\xdd\x8a\x29\xd0\x60\x91\x08\x8b\xc5\xac\x69\xf9\x83\xac\x69\x14\x0d\xc9\x5f\x1e\x3b" + - "\x7b\xc9\x0f\x98\xde\xe5\x52\x71\x3e\x14\x3d\x13\x36\xf2\x0e\x55\x1e\xde\xc1\x06\x8d\x55\x3d\xe0\x6c\x9d\x56\x23" + - "\x50\xf2\xb8\x38\x5b\x6e\x16\x80\x52\x65\xc6\xd9\x69\x6c\x38\x7d\x08\x9f\x93\x57\x4f\xbf\xb5\x42\x9a\x75\xca\x14" + - "\xe4\xea\x29\xc8\x71\x12\x01\xf2\x91\xb9\x60\x4a\x22\x17\x92\x16\x99\xbb\xc9\x2a\x4e\x9a\x17\x97\xe6\xa6\x2a\x41" + - "\x82\xb3\xb8\xc1\xed\xed\x55\x02\x52\x81\xe0\x98\xc1\xb3\xf7\xfb\xfb\x17\x68\x46\x37\x67\x7a\x7f\xff\x02\xb5\xf7" + - "\x64\x64\x8d\xc6\x12\x63\xf1\x5e\xf4\xc5\xa1\xd3\xe3\xdd\x92\x6e\x3c\xb0\x3d\x90\x42\xbc\x25\x05\x88\xf3\x10\xea" + - "\x51\xac\xb8\xb7\x49\xe0\xbd\x6a\x1d\x5c\x16\x3d\x61\x37\xdc\xde\xdc\x7f\x3b\x7d\x6e\xb5\xba\x3b\xba\x27\x2e\xcb" + - "\x62\xb5\x34\x3d\x51\x64\x69\x4f\xe4\x1a\xfe\xa3\xae\xad\xc6\x18\xfe\xb6\x8a\xf8\xc0\x74\xe1\x8d\x6f\xc7\xf6\xaf" + - "\x41\x71\x9d\xab\xd2\xea\x88\x81\xba\xd8\x26\xa3\x08\x27\x39\xa2\xa0\x9e\x5b\x29\xd0\x2f\x27\xb5\x2c\x27\x36\x4d" + - "\x86\x73\xf5\x75\x66\x3f\xdb\xc9\x11\xdd\x3f\xe8\x16\xd5\xea\x20\x45\x16\x4d\x0b\xc3\xc0\x7f\xdc\x3d\xda\x6d\xb1" + - "\xe5\x3a\x5f\x24\xec\xaf\x66\x6d\x49\xbc\xa9\xc5\x81\xc0\x3e\xa2\x25\xa2\xf9\xc5\xb5\x82\x27\xdf\xd6\x7a\xc6\xe9" + - "\x85\x9d\xc6\xfa\x73\x8c\x4b\xf5\x9b\x6b\x0f\xc1\xbc\x28\xab\xe9\xaa\x0a\x02\x38\x71\xc7\x61\xe5\xee\x36\x1f\xa8" + - "\x1b\x35\xf5\x58\x23\xba\xdd\xd0\x55\xfc\x74\xa9\x54\xda\x5f\x2d\x47\x16\xbd\x3a\x0f\x4e\x5e\x52\xb4\x8c\xed\x51" + - "\x8c\x09\x8f\xce\x0e\x2f\xba\xb5\xcc\x58\x91\x8d\xe9\xdb\xc0\xbd\x00\xd5\x97\x1e\x1a\x97\xaa\x62\xe7\xed\xef\xd6" + - "\x27\x69\x22\x16\xce\xdf\x00\x8f\x14\xda\xb7\xbd\x23\x36\xb9\x2e\xc3\x3a\x30\xd8\xf7\xbb\x4c\x4e\x3f\x4c\x54\x59" + - "\xae\xc5\x97\x83\xaf\xd9\x4e\x6d\xfc\xe7\x18\xc5\x42\x5e\x40\xb2\x04\x89\x56\x64\x45\x7e\xa9\x4a\xab\x3f\x70\xf8" + - "\x95\xb0\xf9\xe7\xc1\xd7\xdf\x7e\xfd\x84\x2f\x12\x5a\x07\x4e\xd7\x7a\x04\x07\x13\x09\xfc\x10\x7d\x18\x32\x9a\x34" + - "\x39\x14\xb9\x54\xe2\xe4\x55\x8f\xd4\x43\x3d\x14\xc0\x7f\x51\x93\x0f\xda\x59\xd3\x9d\x9f\x12\x77\x31\x59\xdb\xc0" + - "\x0c\x53\x29\x89\x26\xe6\x93\x97\xf6\xbd\x9b\xca\x40\xa7\x08\xd1\x45\x38\x01\x8b\xd6\x81\x03\x91\x87\x62\x1b\x86" + - "\x86\x1e\x93\x8d\x80\xce\xf6\xe6\xd6\xbf\x32\x6e\x4c\xbe\xe5\x78\xd2\xd8\xaa\x1c\xe7\x98\xf3\x1e\xfe\x6d\xc7\x7f" + - "\x6f\x4f\x24\x35\x74\x88\x1a\xb4\x21\x47\xd7\x85\xff\xec\x38\x6b\x50\xe2\xc9\x1d\x2b\xc7\xed\x86\xb5\x41\xeb\x4e" + - "\x60\xdd\xbd\x78\x9f\xb2\xa5\x79\x38\x40\x4c\x25\xcc\x09\xe3\x46\xe9\x78\x3c\xbe\xf0\x13\x08\x99\x08\x47\x9c\x9b" + - "\xa7\xc1\x7c\xb7\x7e\x27\x2f\xdf\xc8\x85\x0a\x0f\xa8\x9b\x69\x63\x9e\xdb\x27\x36\x20\xe9\xbb\x39\xb7\xe0\xfc\x3e" + - "\xb9\x40\x98\xb1\x4d\x31\x9e\x06\x06\x90\x59\xc7\xf8\xd6\x89\xfa\x16\xff\xc4\x2a\xdd\xc7\xb8\xbd\xdb\x17\xd8\xf4" + - "\x3d\x82\x2b\x6a\x29\xe9\x72\xc5\x05\xd9\xe9\xff\x6e\x24\xe2\xd6\xae\xb3\x2b\x02\x31\xf7\xbf\x06\x95\x32\x55\x3b" + - "\xdd\xcb\xd1\xf9\xa2\xc8\xe0\xbf\x6c\x42\xa4\xb1\xfd\x75\xe7\xb1\xd5\xbd\x71\x56\xe8\x71\x9d\xee\x01\x50\xa3\x9b" + - "\x11\x67\xfe\xfb\xe9\x73\x71\x5d\x94\x1f\x8c\x30\x55\x29\xf3\x4b\x85\x49\x00\x04\x03\xa5\x5f\x16\xa8\xb0\xfc\x7d" + - "\xa5\x40\x5e\xb6\x1f\xfd\x82\x56\x29\xfc\x4e\x30\x7f\x4f\xf9\xf4\xd6\xe4\x76\x3e\x63\xbf\x26\xa1\x6e\xaa\x52\xa2" + - "\x4c\x47\x54\x0e\xba\xb3\x9d\x00\x1d\x82\x1e\x30\xe1\xd4\xd2\xe5\x32\x2a\x95\x48\xde\xcd\x65\xfe\x01\xfd\x38\x80" + - "\xb1\x54\xd7\xe2\xe5\x6a\x59\xe4\x95\xf3\x5f\xaf\xd4\x74\x8e\x3e\x2f\x5d\xdb\xd9\xc9\x2b\xf1\x8d\x48\x0b\x85\x81" + - "\x71\x38\xaf\xc2\x86\xb8\xb9\xac\x43\xfe\xba\x68\x7a\x1d\x84\x37\x62\x4b\xa0\xc5\x6e\x4b\xfe\xcd\x9d\x1d\xe2\x44" + - "\x80\x21\x63\x65\x70\xb8\x91\xb1\x87\x5b\x42\xfb\x18\xa0\x9d\x53\xb7\x27\x1d\x9d\x76\xba\x61\x18\xbd\xdb\xf9\xc0" + - "\x6b\x9b\x44\x9c\x1e\xc8\x8e\x5f\xec\x05\xb9\x19\x63\x22\x68\xfb\x37\x61\xff\x02\x06\x40\x56\xa9\x9e\xd2\x91\x06" + - "\xea\x9c\xe9\x74\xfc\x10\x9d\x4d\x74\x0a\x52\xe6\xc3\x0b\xd1\xf1\xd3\x17\x63\x66\xb9\x42\x3b\xa1\x67\x21\x75\xbf" + - "\x1f\x4c\x9d\x5a\xa2\x7d\x90\x7b\xab\x0a\x8b\x92\x89\xf0\x6f\xeb\x13\x09\x51\xda\x8a\xeb\x8d\xb3\x81\xf9\x51\x95" + - "\x73\x0f\xf0\xb4\x3c\xba\x0c\x3d\x27\x77\xe4\x3a\x0f\x4e\x05\xaf\xe5\x7d\xa1\xf3\xa4\xd3\xeb\x78\xbf\xd6\x00\x3d" + - "\x82\x0f\xdc\xd2\xac\x58\xb5\x8d\xa4\x58\xb2\xed\x97\x32\x40\x57\x0b\xdb\xd3\x73\x90\xb8\xa2\x9e\xf9\x0b\x47\xf1" + - "\x5b\x09\x3e\x8b\x3c\xc9\xef\x46\xa2\x33\x91\x9b\xcf\xad\x98\x69\x72\x29\x8c\xb2\x2f\xec\x02\xa2\x45\x69\x17\x68" + - "\x2e\xe4\xe6\x55\x43\xba\x3b\x23\x16\x7c\x82\x80\xe7\x59\x46\x8e\x27\xc6\x3b\xdf\xd0\xae\xf8\xdd\x69\x06\x18\x7c" + - "\x71\xd8\x11\xdd\xed\xec\xbf\x95\x1c\x86\x8f\xd8\x09\x06\xdd\x0e\xc4\x07\xb5\xee\x93\x51\x71\x2a\xd1\x79\xbb\x98" + - "\x89\x4c\x2f\x34\x50\x21\xa3\xff\x4e\xbe\x2c\xff\x3f\x66\xaf\xc4\x1f\xce\xd7\x8f\x58\xe1\x1e\x3b\x5e\x75\x6f\x39" + - "\xab\x01\xb9\x5b\xb3\x37\x16\x86\x92\xc9\x59\x85\x41\xd9\x05\x65\x5c\xa8\x80\x50\x70\x12\x94\x6b\x0d\x14\x5c\x3c" + - "\xda\x71\x01\xca\xc8\x06\x41\x0f\x09\xaa\x1b\xfa\x66\x35\x9b\xe9\x1b\x95\x76\x6d\xe0\x18\x10\xb1\x44\x73\x24\x23" + - "\x3a\x50\x68\x23\x32\x90\x99\x80\x52\xc9\x5c\x20\x73\x8b\x6f\x7e\xc0\xd3\xd3\xc5\x01\x52\x95\xa9\xca\x5a\x2d\x8a" + - "\x2c\x55\xa6\x12\x2a\xaf\xca\x35\xfb\xdc\x38\x71\x2a\x72\xc6\x70\x12\xd3\x07\xb5\x36\x81\xe7\xb2\x6f\x8d\xed\xe0" + - "\x75\xcf\x7a\xcc\xba\xe0\xed\x9f\x8d\x12\xc9\x07\xb5\x86\x03\x2e\x3a\x5d\xf4\x50\xc5\xa0\xc0\x69\x91\x65\x1a\x93" + - "\x0b\x50\xb4\x2f\x29\xec\x7c\xe6\xc0\xc0\xd5\x2e\x31\x4a\x89\x13\x63\x56\x4a\x3c\x38\xfc\xea\x2f\x5d\x77\xdd\xc1" + - "\x84\x98\x8b\x71\x43\x88\xae\x78\xd6\x58\x7e\xc8\xd5\x63\xe2\x97\x0f\x4a\x2d\x7d\x4c\x52\xa9\xa6\xc0\x8d\x01\x28" + - "\xec\x75\x83\xa0\x62\xe0\x9e\xd1\x40\x66\xae\x67\x55\xd2\xf5\x21\x06\xee\xec\x24\xbe\x19\x4f\x02\x08\x11\x82\xc2" + - "\xca\x66\x3e\x33\xd7\x74\xae\xea\x48\xf8\x5a\xc2\x8d\xe6\xdd\x78\xe1\xc2\xe1\x40\x2a\xd4\x07\x4f\xd6\xcc\xcb\x10" + - "\x1a\x2e\x65\x29\x17\x1e\x09\x6f\xc5\x2c\xc7\x7c\x86\xa1\x1b\xf0\x42\x96\x1f\xea\xbb\x0a\xcf\x6a\x5e\xaa\x00\x95" + - "\x59\x7e\x66\x6f\x7a\x9c\xb7\x75\x99\x71\x9e\xa4\xf5\xe9\xb2\x7e\x01\x89\x22\xe5\x6d\xb4\xf7\x2e\x5d\x79\xdb\x67" + - "\xf9\x16\xf3\xfa\xf8\x6c\xc8\x2a\x15\xa9\xbe\x42\x74\x56\x18\x12\x60\x84\x74\xd9\x91\xe8\xe4\xd6\x17\x01\x3d\x94" + - "\x55\x30\x7d\xc0\x4c\xe8\x64\x7b\x48\x6c\xaa\xaf\x3a\x7c\x31\x3a\x72\x6a\x73\x18\xec\xce\xf2\x04\x3f\xa7\x8d\xb2" + - "\x9a\x1e\xb5\xcd\x8f\x30\x26\x7f\xe8\xc2\x81\x19\x5b\x90\x8f\xd0\x95\x61\x51\x0d\xb6\x8c\xd3\x4b\x3a\x6c\x4d\xf5" + - "\x55\x9b\xfc\x14\x3f\x8e\x03\x6d\xdd\xc4\x5c\xa8\x78\x49\x2e\x77\x62\xa1\x16\x45\xb9\x06\x31\xee\xe4\x15\xbc\x22" + - "\x08\xe4\xab\x2c\x63\x84\x8b\x76\xec\x79\x9a\x1a\xef\x9d\x6b\x3d\x76\x01\xcd\x24\x10\xd9\x99\xf3\x8c\xa6\x34\x2c" + - "\xb2\xaa\xd8\xc3\xcf\xee\x22\xe9\x14\x6f\xe9\x8d\x78\xab\x97\xaa\x6f\x14\xbc\x83\x2d\xcc\xb4\xa9\x30\xd1\x9e\xb3" + - "\x20\x6d\xc1\x00\x3b\x30\x20\x2b\x79\x43\x91\x68\x8a\x8e\xd6\x13\x54\x4d\x65\x5a\xa5\x8d\x2d\x4f\x53\x12\x2f\x13" + - "\x1a\xbf\xe7\x3a\xf2\x18\x40\x6a\x46\x7c\x6d\xfd\x5e\x37\x9d\xae\xcb\x08\x46\x2f\xc2\xf8\xa2\x16\x46\x02\xa9\x06" + - "\xb4\xa4\xd1\x30\x64\x0b\xb8\x06\x38\x14\x3c\x62\x1b\x70\x51\x44\x37\x5e\x94\x2e\xd0\x69\x0d\x80\x7a\x5d\x08\x66" + - "\x2a\x62\x88\x30\x66\xde\x0a\xd9\xfe\x78\x52\xbb\x6e\xc8\xff\xd7\x5f\x2e\x99\xc2\x80\x1e\x99\x8b\x03\x10\x64\x24" + - "\xdb\xa3\x95\x11\x93\x9e\xb8\x44\xe4\x2f\xa3\xf7\xb3\x22\xcb\x8a\x6b\x43\x1d\x87\xa0\xe5\xe9\xe1\x12\x22\xe7\x3a" + - "\x8c\x6e\x5a\x01\x4c\x27\xc0\xff\x48\xca\x99\xa6\x67\x33\x60\x27\x57\x25\x3e\x6b\x71\xa3\x9d\x34\x9f\x21\x92\x27" + - "\xe2\x1f\x93\x81\x29\x56\xe5\x54\x9d\xe4\xa9\xba\x01\x76\x29\xf2\x9b\xeb\x8a\xbe\x6d\x28\xef\x6e\xe8\x92\xb5\xc1" + - "\xd5\x72\xf2\x4a\x84\x8d\x61\xb1\x57\x52\xa3\xc7\x3f\xdc\xb0\x93\x02\x53\x7b\x91\xfa\x98\x0f\xe1\x6c\x56\x53\x2f" + - "\xc1\xa3\x28\x55\x19\xe9\x5c\xf4\x4c\x4c\x1c\xe0\xa4\xfd\x1e\xd6\xce\x9f\x3b\x6d\x26\xc1\x69\xba\x2a\x07\xb9\xba" + - "\xa9\x4e\x09\xa4\xdd\xd8\x7f\x0d\xdb\x44\x8e\x8a\xb1\x83\x5a\x83\x01\xb2\x51\x7a\xe2\x58\x1c\x8a\x11\xb5\x8a\xd0" + - "\xce\x22\x43\x1c\xfe\xc1\xb6\x46\x6b\x9f\xa5\x48\xa8\xe5\xaa\x42\x4d\x5e\xfb\x99\x86\x37\xed\x0c\x00\x7a\xc0\xbe" + - "\xc5\xae\xd8\x0f\x9b\x26\x6f\xa9\xe2\x56\x87\x3f\x64\x60\xc6\x77\x05\x91\x87\xf9\x15\xa9\x35\xc8\x3a\x38\xd5\x8e" + - "\x53\x5e\x38\x57\xeb\x8a\x14\xf1\x5e\xf1\xfb\xd9\x40\x20\x73\xe2\xe7\x02\xe0\x3b\xfc\xea\xdf\x0f\x81\xa4\x01\x82" + - "\xcd\x26\x00\x0b\x4d\xbe\xd3\xfd\x77\x00\xc6\x26\xba\x90\xd9\x36\xaa\x3d\xcb\xdb\x81\xf3\xd6\x7d\x69\x01\xe4\xee" + - "\x64\x17\xa3\x17\x30\x1c\x61\xe0\xee\x65\xa4\xd4\x76\xbf\xc7\x62\xdf\xfe\x1d\x42\x67\x4b\x37\xc0\xd0\xf7\x6c\x1c" + - "\x60\x6c\xad\x60\xb1\x08\xdf\x21\x65\x40\xdf\x13\xb8\xea\xcf\x2e\x48\x12\xb0\x66\x8c\x60\x32\x81\x49\x23\xfc\x30" + - "\x8e\x4a\x75\x69\xbd\x7d\x56\xe1\x19\x6a\x22\x64\x55\xbb\x44\x35\x7d\x1e\x19\x3e\x22\xa9\x95\x34\x36\x4a\xa5\x67" + - "\x22\x79\x5f\x1b\xf4\x4c\x5f\x74\x45\xa0\x33\xdb\xc1\x76\xef\xe1\x26\xda\x4d\x78\xc9\xf4\x93\x5f\xb4\xc5\xa8\x11" + - "\x4b\xd3\x14\x79\xe8\xbe\x92\x94\x8f\x63\x46\x89\x93\x74\xaa\xab\x35\x25\x90\xe6\xe0\x02\x97\xb0\xa5\x79\x43\x6d" + - "\x48\xb2\x19\xdf\xc6\x8d\xdc\x7d\x15\x37\xdb\x70\x18\xcb\x2d\xde\xfb\x44\x8d\x70\x68\xa0\xd6\xd3\xa9\x5a\x56\x14" + - "\xa0\x55\x78\x13\x15\x32\x5c\x6b\xe2\xa0\xeb\xc8\xd7\x26\x8a\xc7\x68\x67\x1f\xfa\xba\x26\x77\x69\x17\x51\xcb\x12" + - "\xb9\x79\x7b\xc5\x8c\x03\xdd\x10\x44\x8a\xc2\x28\x57\x05\xe0\x4a\x96\x74\x7e\xa6\x45\x7e\xa5\x72\xad\xf2\xa9\xba" + - "\x7f\xcf\xd7\x08\xe0\x72\x33\x8d\xa2\x01\x76\x13\xc8\x52\x69\xc4\x7f\xbd\xfe\xc1\x5e\x50\x5b\xe1\x7c\x4b\xd4\xe5" + - "\xb9\x63\xb0\x31\xcd\x62\xa0\x66\x8e\x80\xef\xa1\x5d\xae\x00\xc6\x94\xff\x9a\x72\x30\xe5\x45\xde\x47\x93\x89\x1d" + - "\x96\x81\x8b\xc1\x12\x7e\xd6\xf6\x67\x2b\x79\x1b\x0e\xdd\xc8\xaf\x6c\x9e\x66\x23\xae\x54\x49\x68\x4f\xd9\xed\x8d" + - "\xb2\xa5\x5f\x74\xe5\x14\x64\x6b\x55\x51\x84\x14\x27\x71\xb6\xb5\x57\xb2\x82\x7c\xf4\xf4\xac\x94\x0b\x4c\x3a\x06" + - "\xf7\x7a\x5f\x3c\xf8\xf2\x9b\x27\x68\x8b\x40\x16\xbf\x36\xe6\xd8\x19\x26\x50\x83\xde\xb4\xab\xc1\xd3\xee\xa0\xf6" + - "\x59\x20\xd7\xd4\x3b\x3c\xae\x3f\xf1\xf9\x50\x50\x0f\x07\x70\xeb\x88\x91\x93\x05\xe2\xfd\x3c\x55\x95\x67\x01\xfb" + - "\xa5\xa2\x98\xbe\x2b\x59\x6a\x40\x6e\x23\x8a\x7c\x4a\x99\x40\x53\xab\x94\xb4\xd9\xf0\xe3\x6d\xdc\x82\x00\x67\x69" + - "\x31\xbd\xa8\x61\x80\x67\x38\x49\xcf\xc0\xf4\xbd\x2a\x30\x17\x7c\x68\xdd\xa9\x61\x88\xed\x34\xd4\x55\xb4\xcd\x66" + - "\x78\xff\x5e\x60\x6f\x0c\x90\x3a\x7a\x18\x24\x97\xf7\x62\x0d\xd7\xd6\x78\x51\x2c\x40\xb4\x21\xe6\x11\x03\x4c\xb0" + - "\xcd\x31\xfe\xd3\xdc\x32\x7c\x19\xdb\x41\xc9\x25\x80\x64\x2a\x94\xf0\x06\x2c\x56\xfd\xa7\x56\xd7\x8e\x15\x3c\x99" + - "\x89\xbc\x08\x6a\x6e\xe4\x69\x1b\x8e\x3a\xd6\xb0\xc7\x26\xa8\xc0\x9e\x88\xb7\x69\x1a\xcc\x05\x86\xaa\x59\x25\x37" + - "\x1b\xb1\x8b\x33\xa8\x75\x5d\x63\x27\x03\x6b\xeb\xad\x4f\xc6\x58\x89\x62\x55\x86\xa6\xa1\xa0\xd6\x47\x5a\x4c\x8f" + - "\x7c\x84\x90\x5d\x67\x03\x73\x23\xef\x07\xa4\x83\xa6\x11\x4c\x84\x69\x03\xe0\xf8\xd2\xaa\xba\xf5\xcf\x46\xe2\xe4" + - "\xd5\xb3\x6f\x1c\xd4\xe8\xc8\xf9\x85\x03\x94\x8c\xd1\x97\x39\x25\x49\xea\xf8\xb2\x3c\x16\x95\x11\xb8\xda\x7d\x39" + - "\x97\x46\x4c\x94\x02\x69\x1d\x8e\x31\x45\xc4\x90\x66\x1c\xa5\x3a\x4a\x61\xd9\x59\xaa\x72\xa1\x31\xc0\x41\xa4\x40" + - "\x2d\xd3\x0e\xd7\xfb\x40\x2b\x26\xdc\x02\x06\x95\x08\x2d\x03\xe2\x7d\x6d\xa3\xd3\x1e\x1c\x3e\xf9\xf6\xc9\xd7\x76" + - "\x88\xaf\xfb\xdf\xd8\xca\x4f\x96\xd0\x56\xbe\xae\x03\x60\x88\x4f\xfa\x67\x0a\x2b\x9a\x5b\x69\xd3\x11\x7c\x8b\x06" + - "\xfc\x7e\x6f\xcf\xfe\x05\xdb\x4e\x7f\x0e\xaa\x62\x19\x68\xb5\x4e\x5e\x1d\x1e\x22\x59\xc3\xb1\xe7\xf2\x4a\x71\xb0" + - "\xe8\xab\x2b\x95\x57\x18\xea\x0a\x82\x35\xba\xb2\x9b\xd5\x6c\x86\xde\xc1\xe1\x20\x03\x99\xa6\xd8\xf6\x07\x6d\x2a" + - "\x95\xfb\x92\x1b\x3b\x5b\xde\x27\xa2\xb3\xca\x01\xc2\x9d\x5e\x33\xe6\x37\x72\x0b\xb0\xaa\xe5\x9e\xcd\x17\xc3\xfe" + - "\x21\xde\xec\x65\x87\xf0\x33\x6e\x8c\xee\x5f\x25\xa2\x53\xe4\x9f\x39\xb4\x57\x59\xf0\x01\x78\xe4\x03\x19\x00\x65" + - "\xfb\x7f\xca\xff\xb8\x00\x5a\xdd\xe3\x85\x91\xfb\x3f\xe1\x42\x5a\x93\x7e\x21\xb4\x7b\x60\xe1\xad\xcc\x26\x23\x35" + - "\xa1\xdb\x2b\xf9\x88\x57\x91\xea\x51\xdd\x00\x83\x02\xa8\x79\xf2\xea\x1b\xe7\xeb\xd9\xf5\xe1\x87\x83\x28\xae\x82" + - "\xb5\x53\x9e\x26\xa2\x06\x87\x60\x95\xea\xab\xc1\xd4\x19\x0a\x81\xd5\xef\x84\x5c\xee\x2e\xbc\x8f\x2d\x34\xae\x75" + - "\xc7\xb3\x72\x04\x4e\xcf\xc8\x24\xa6\xfb\xdd\xfa\xd1\xbf\x03\xa8\x4e\x0c\x6e\xb5\xc9\x76\x1e\x75\xba\x0e\x88\x98" + - "\x82\x24\x30\x78\xb5\x9a\x51\x2d\xbf\xf5\x71\x28\x45\xd9\xe8\x80\x16\xb2\x3e\xba\x58\x90\x42\xaf\xd3\x8d\x13\xf4" + - "\x5b\xd0\xb5\xcf\x32\x30\x20\xdd\x7a\x7a\xd8\xbe\x3a\x6f\xc8\xe5\x38\x75\x74\x66\x42\x12\xf1\x11\xd3\xf0\x58\xb0" + - "\x2f\x2a\xdb\x8f\x60\xda\x5b\x6d\xc4\x7b\x7b\x1f\x85\x81\xce\x73\x55\x32\x45\xef\x3c\x85\x97\x88\x0d\xe3\x87\xf2" + - "\xe1\xb3\xa7\xc3\x54\x5f\x3d\x8b\x1e\x0a\x6d\x1f\x77\x8e\x9a\x8e\x60\xa7\x72\x26\x4b\xfd\xd4\x3a\x48\xbe\x40\x01" + - "\x06\x3f\x15\xc5\x95\x2a\xfb\x53\x89\x2e\xc6\x76\x6c\xf4\x05\x46\xf0\xb7\x22\x6c\xd8\x33\x7a\x77\x3c\x3d\x3c\x88" + - "\x7a\xbe\x7c\xf5\xdd\x8b\x37\xe8\x7c\xb7\x2a\x91\x21\x99\x69\x0e\xbf\xe0\x24\xb5\x34\xb6\x32\x91\x16\xe6\x6a\x9b" + - "\x59\xbc\xa3\xdd\x26\xe2\x35\xfd\xb8\xb6\x95\xe1\xe9\x3f\x3c\xd8\xba\xbd\xdf\xad\x4f\x52\x87\xb1\x4e\x7a\x63\xaf" + - "\x13\x5f\x15\x68\x52\x16\x1f\x54\x5e\xff\xce\x26\x3e\x4e\x31\x6f\xf6\x52\x4f\x3f\x88\xd5\x12\x28\xc5\x65\x29\x17" + - "\xb2\xd2\x53\x20\x2a\x7d\x60\xbc\xa0\x37\xc3\xb7\xa0\x29\x38\x82\x12\xad\xd5\x72\x52\xac\xaa\x18\xdf\x10\xb2\x80" + - "\x30\x31\x82\xe1\x90\x1f\x39\x27\xc4\x2c\xd4\xce\x0a\xbc\x47\x9f\x8f\xc8\x76\xef\x8e\x49\x1d\x27\x71\x78\xcb\xd6" + - "\x34\xde\x24\xce\x2c\xb0\xe5\x0c\x9d\xbc\xa4\x9d\xc5\x6c\xd0\x18\x86\x64\xaf\xd2\xfa\x5a\x42\x0d\x2b\x7c\x72\xd6" + - "\x39\x79\xd9\xb9\x88\xb8\x47\x9d\x36\x12\x8d\xb4\xa5\x13\xa9\xb9\xc4\xb4\x4a\x6f\x35\x96\x28\x48\x12\x53\x8a\xbb" + - "\x5c\xaf\x02\x53\xf5\xbf\xe6\x7a\xf5\x39\x9e\x57\xe8\x71\x15\x69\x04\x51\xaa\x89\x7c\xad\x8e\xc5\x99\x58\x70\x65" + - "\x91\x50\x5b\x78\x14\x00\x15\xc0\xdf\x0a\xd6\x48\x35\x02\xb7\x15\xe2\x96\x0e\xcd\xfc\xd6\x9d\x1b\x2f\x78\xf6\xec" + - "\x66\x48\xdc\xa9\xe9\x8a\xf3\x47\x36\xdd\x0b\xf0\xb8\xd2\x90\x3c\x6d\x97\x54\x24\xf2\x21\x88\x0f\xf1\xd7\xc3\xbf" + - "\xf0\xc3\xda\x5e\xb3\x87\x55\xa9\x32\x66\x45\x51\xbf\x05\x18\x68\xd8\xdb\x0f\x4f\x06\x99\xee\x6a\xb8\xc6\x54\xb1" + - "\x0d\x58\xff\x73\xd0\x42\xcd\x20\xa5\xad\x65\xac\x6e\x00\x0e\xf7\xbb\x0d\xa9\x5b\x5b\x46\x06\x75\xab\x4e\x85\x1e" + - "\xd8\xa7\x72\xe0\xb3\x07\x6e\xdb\x06\x7b\x98\xdf\xc9\x4b\xce\xa4\xc0\x50\x7b\xf7\xfc\xaf\x08\x9e\x3b\x2f\x73\x74" + - "\x76\x0f\xfd\x87\x2f\x3f\xf7\x14\xdf\xa5\x89\xa9\xa3\xd9\xdd\x5e\x62\x95\xbc\x8c\x13\x86\x91\x1f\xfd\x47\x66\x07" + - "\x7b\xa2\x38\x31\x83\x4b\x4c\x64\x33\xb7\x85\x69\xbf\x02\xdf\xd9\x4f\x9b\x87\xd5\x17\x52\x84\xa6\x00\xe2\xef\x6a" + - "\xaf\x4c\x89\x97\x09\xbc\x83\xe0\x2b\xd4\xf6\x3e\x0a\x7c\x7d\x9c\x8d\x81\xbd\x04\x79\x0a\xde\x5d\xfa\x7e\xcd\x53" + - "\xb3\x6e\x7f\x09\x7c\x32\xaa\xc5\xb2\xd5\xe5\xaf\xe6\xdb\xe7\xf2\x9c\x70\xc6\x25\x7e\xdf\xe2\x26\x72\xeb\x99\x29" + - "\xb8\xab\x63\xec\x21\x9f\xbb\xad\xf8\x13\xf9\xd4\x05\x59\xa0\xed\xe3\xc6\x3e\x7d\x14\x89\x7c\x8f\x9f\x71\x25\xdc" + - "\x85\x57\x81\x5f\x9e\xe7\x82\xba\x91\x13\x3a\x31\xe3\x7f\x3b\x7d\x3e\x64\x9d\xec\xa9\x2f\x3b\xf8\xa7\xf3\xe3\x7f" + - "\x3b\x7d\x8e\x37\x6d\x6d\x28\x9f\x62\x88\x9a\xd5\x5e\x27\x23\x39\x05\xb6\x14\x98\x75\x2a\x01\x4c\x62\x21\xd5\x0a" + - "\x2a\x57\x4a\x24\x27\xaf\xbe\x1d\x22\x1f\x27\x0e\x0f\x07\x18\x03\x1c\x65\x20\x09\x5c\x3e\xd0\x73\x4f\x26\x23\x4c" + - "\x90\x70\x47\x8f\x2f\xe6\x65\xb1\x50\xe2\xf1\x61\x97\x93\x19\x28\x2e\xf2\x19\xd5\xbf\xc5\x82\x8b\x93\xd5\x25\x29" + - "\xfc\xbe\x19\x7e\x4b\xd7\xa5\xcd\xc8\x95\x93\x8a\x80\x7a\x80\xce\xb1\x3e\xca\x6f\xce\xca\x4f\xeb\xe2\xfd\xfa\x4d" + - "\x70\xf9\x65\xc3\x2a\x36\x99\xb3\x8a\x82\x79\xc4\xa2\x27\xae\xed\x2c\x68\xfe\x70\x9f\x73\x6a\x44\x4a\x43\x87\x00" + - "\xe6\x12\x84\x95\x5e\x28\xef\xac\x02\x4f\x4e\x5e\x85\xf3\x39\x55\xca\x46\x69\x4d\x56\x97\x66\x10\xd4\x1e\xa7\x82" + - "\xcc\xc3\xc3\x27\x4f\xfe\xf2\x4d\x98\xda\x25\x80\x23\x39\xe7\x85\xde\x9a\x6d\xe2\x43\xdd\x91\x2b\x70\xd3\x74\xb5" + - "\x05\xa1\xdf\x52\x5d\xaa\x1b\xe7\x8e\x70\xa9\x6e\xd0\xa9\xb2\x52\x97\x6b\x21\xd3\x62\x59\xa9\x94\xdc\x13\x5e\x6a" + - "\x75\x59\x88\xb7\xaa\xd4\xb9\x46\xbb\xcb\x1d\xec\x25\xad\x31\xe3\x22\x98\xa8\x50\x2c\x6c\x69\x4d\x2e\x2a\x95\x0b" + - "\x4e\x98\x62\xdb\xbf\xa3\xf2\x7a\x98\x09\x4c\x99\x4a\x9c\xbc\x7a\x68\x44\x05\xa2\x1b\xa9\x29\xa9\x9a\xab\xba\x59" + - "\x66\x7a\xaa\x39\xf4\x04\xb9\x64\x55\x51\xd6\x74\xe7\xfa\x81\xe7\x31\xaf\xbc\x70\xde\x73\x6d\xb1\x2e\x09\x3a\x5a" + - "\x60\x01\xf1\x69\x98\x06\x42\xe5\xb0\x8f\xb6\xe9\x47\xb6\xe7\xf1\x93\xaf\xbe\x75\x0e\x18\xb1\xb4\x45\xde\x65\x62" + - "\x61\x10\x5d\xa6\x99\x5e\x8e\x1f\x3e\x7c\xf6\x94\xf2\xe9\x09\x9b\x30\x04\x9f\x0d\xe9\xe1\xb3\xa7\x9c\x80\xc1\x89" + - "\x5f\x35\x9e\xe6\x1b\x76\x84\x17\x87\x87\xfd\xc3\xc7\x83\xc3\xaf\x6d\x9b\x37\x05\xc5\xb5\xfb\x55\xd8\xfe\xe9\x40" + - "\x85\x30\x37\x6c\x8f\x16\xbf\x8e\x45\x51\x8a\x2f\xf0\xbf\x8f\xc6\x1e\xfe\x24\x4b\x78\xb0\xb9\x64\x0a\xab\xfc\x43" + - "\x4e\x39\x5e\x78\x1a\x93\x55\x25\x3a\x46\xce\x54\x07\x35\xf6\xbf\xe8\xfc\xa7\x77\x35\xc0\x2d\x4c\x9a\x0f\x16\x36" + - "\xeb\x39\xc2\x4e\xe5\xfd\x95\x19\x52\x20\xeb\x7a\xa8\xd5\x70\x3e\xff\xf2\xeb\xaf\x9e\x7c\xf3\xcd\x40\x9a\xe5\x8d" + - "\x4f\x3c\xf1\xdf\x46\xb9\xf4\xa2\xde\xf9\xa5\xe1\x98\xd8\x39\x0b\x40\xfc\xeb\xf8\xe1\xc3\x0b\x2f\xe8\xf9\xab\xdf" + - "\x39\x2d\xd3\xe5\xd5\x39\x7b\xf4\xeb\x17\x17\xad\xa1\xe3\xc7\xa3\x87\x0f\x37\xe7\x9d\x73\x0c\x77\x8e\x3d\x2c\x6b" + - "\xbb\x61\x9f\xd9\x0c\x6b\x35\x2d\x50\x07\xd9\xa6\x0e\x73\xee\x15\x21\xb1\x4a\x6d\x75\x67\x46\x5d\xf2\x7c\xdc\xb2" + - "\x32\xbb\x8b\x9f\xb4\xa4\x2d\xd9\x38\x8e\x47\x38\x8f\x4d\x23\xcc\xb8\x6d\x79\x14\x5c\xc1\x84\xbc\x2f\x46\x9c\xdf" + - "\xc6\x22\x56\xe4\x40\x09\x24\x92\x90\x39\xf2\x52\xde\x96\x05\xe6\xf1\xc1\xe1\xe1\xf0\xa7\x57\x2f\xfa\x71\x06\x95" + - "\x3e\x3c\x3f\xf8\xf6\xf1\xb7\xc3\x07\x3c\xd8\x7d\xe7\x17\xfd\x8d\x25\xe3\xa4\xe6\x45\x53\x10\xba\x5e\xeb\x2c\x23" + - "\x85\xad\xc2\xc4\x09\xaa\x74\x8a\xec\xbb\x01\x6a\xd7\xf3\x71\x70\x06\x4d\x8f\x6a\xd6\xd0\x4f\xa2\x7a\x16\x4d\x28" + - "\xb1\x9c\x11\xdf\x88\x37\xe4\x9c\xf8\x7c\xb9\x34\xd1\x59\x03\x36\x0b\x95\x86\xc0\x19\x84\x28\x54\x2a\x60\x94\xb0" + - "\x84\x83\x4a\x45\x4a\x39\x25\x02\x22\x43\x3a\x76\x17\x23\x42\x65\xce\x97\x2b\x6b\xe2\xa8\xf9\xaf\x91\x4b\x80\xcd" + - "\xad\x0b\x3f\xea\x9e\xd6\x30\x93\x4e\x4f\x74\x28\x23\x91\xc3\x8e\x86\x2e\x8d\x06\xe9\xd6\x3f\x87\xf9\xc3\xe7\x2f" + - "\x3b\x11\xdf\xda\x76\x60\x5e\xe5\x58\x19\x08\x4d\x7c\x7d\xa3\x72\xac\x56\xa4\x2b\xac\xb8\x15\x83\xe1\xa3\x67\x1f" + - "\x9a\x8f\x3f\xed\x7c\xe0\x04\x5b\x22\xda\x5d\x7a\x99\xb6\x03\xf1\xfd\xf7\xe2\xc9\xe0\x2b\x38\x0a\x2a\xc7\x84\x4d" + - "\xc3\x91\x4d\xdd\x84\xbb\x46\xc0\xf2\x9a\xa0\xa4\xfe\x00\xb6\xd1\x54\x80\xb0\xdc\x41\xf7\xdf\x89\xdf\x3c\xc6\xa7" + - "\x80\xc3\xb5\xed\x89\x8e\x5b\x53\x1b\x08\xf8\xca\x39\xe8\x87\xe6\x0a\x32\xc9\xc0\xf5\x5d\x98\xaa\x4f\xd9\x44\x74" + - "\x8e\x3e\x00\xd6\x33\xc4\x61\x4f\x73\x9e\x8f\x7a\xa3\x1b\x8b\x8b\xf5\x83\xd7\x1b\x3c\x1a\x75\x6c\x79\xd9\x7a\x20" + - "\xa0\xe5\x76\xea\xec\x6b\x9d\xf3\x49\x7c\xfe\x6c\xab\xe3\xb2\x4f\x28\xb3\xa2\x7d\x7a\x8d\x04\xef\x75\xad\xbb\xb8" + - "\xcd\xa2\xf8\xfb\xdd\x0d\x8a\x8f\x7c\x6f\x6a\xef\xbb\x8e\x09\xfb\x14\x5a\xf2\xc2\x66\xa7\x05\x6c\xd0\x33\xa1\xab" + - "\x87\xc6\xcb\x80\x55\x21\xd2\xa2\xce\xaf\xdb\x4f\x81\x85\x15\xa9\x36\xd3\x22\xcf\x89\x62\xa3\x5c\x9f\x9c\xbc\x12" + - "\xdf\x12\x1e\x5a\x80\x86\x8d\x5e\x73\x88\xa3\x4d\xa8\x4d\x11\xd7\xa9\xbe\xea\x09\x74\x83\x8d\xce\x37\xf2\x6b\x7c" + - "\x3d\xcc\xa4\xce\x7c\x09\x75\x32\x7a\xf8\xca\x2c\x7f\x55\xd3\x0f\x85\xc7\x20\x45\x69\x72\xad\x2e\x95\xd8\x7f\x0e" + - "\xdb\xc3\x4f\xda\x86\x3f\x33\xbb\x70\xc3\x8f\x6e\x1c\xa2\x46\x52\x86\xc5\xed\xdd\x71\xa7\xe7\xd3\x8b\x34\x70\x29" + - "\xe4\xa6\x3d\xfa\xf1\x89\xd9\xdb\x8b\x12\x1e\xf8\xf7\x14\x76\xb1\xb1\x76\x83\xba\x78\x13\x4f\xe4\xae\xce\x6c\x9b" + - "\xb8\x43\x12\x03\x5f\x70\x30\xde\x9f\x2b\xfb\xed\x78\x33\x7a\x9b\x90\x80\x58\x3a\xa5\xf7\xd6\x0e\x67\x1d\xb3\x02" + - "\xeb\xaf\x35\x55\xdb\x80\x41\x21\x73\x74\xb7\xe1\x7c\x67\xc4\xc7\xcf\x56\x59\xb6\xf6\xbb\xec\xb2\x94\x50\x9d\x24" + - "\x03\x57\x60\xaa\xcc\x54\xe5\x29\x5d\x5c\x58\x02\x51\xe8\xbc\x17\xf8\x7e\xfb\xcf\x79\x28\x8e\x72\x08\x52\x57\xa2" + - "\x37\xad\x5b\xd3\x66\xb3\x75\x51\xdc\xbc\x5b\x57\x32\x85\x39\x20\x49\x4d\x87\xf9\x0b\xc7\x75\x8f\xd4\x6f\xc5\xb1" + - "\x90\x0d\x6b\xfd\x88\x9d\x59\x77\x76\x26\xab\xa5\xf5\x6f\x9d\x04\xda\xd6\x48\x93\xc7\xe9\x25\x57\x4b\x54\x93\xef" + - "\x26\xf8\x27\x7c\xb0\x5a\xb6\xb8\xbf\x26\xd4\x31\xce\xc7\x2f\xc0\xd6\x80\x88\x1f\x53\x57\x2e\xd7\xc3\x8e\xdc\xba" + - "\x8d\xe8\x6b\xbb\xe5\xa5\xed\x65\x4f\xb0\x48\xd1\x0d\xf2\x01\x6c\x05\x1a\x52\xe4\x49\x8b\x9a\x69\x02\x00\x09\x60" + - "\xd1\xd0\x31\x4d\x48\x97\x18\x87\x93\x46\xc9\x72\xdb\x23\x7b\x5a\xea\xab\xb9\x83\x73\x5a\x94\x15\x59\x9f\xfe\xc4" + - "\x73\xc3\x09\x21\x62\xa7\x6c\xe3\x46\x0a\xb3\x8b\x06\xd8\x78\x1c\xc4\xb5\x84\x30\xbb\xef\x92\xbd\x5f\x52\x09\x4d" + - "\x97\x62\x94\x0b\x56\xdd\xff\xdc\x7c\xa4\x51\x2e\xd2\x30\x21\x78\x51\x62\x70\x10\xfb\xc7\xa3\xbf\x14\x8a\xb9\x61" + - "\xad\x64\xe2\xe3\xe6\xd2\x88\x2d\x68\x71\xdf\x16\xa8\x70\x94\x63\x77\x3b\x7e\xf5\xc5\xee\x64\xdb\xcb\xa3\xfb\xbe" + - "\x90\x1a\x75\xd5\x50\x9d\xe1\xe3\xda\x2a\x5e\xc8\x6c\x4a\x49\xae\xad\x7f\x29\xfa\x53\x17\xd5\x5c\x70\xf2\x9f\x89" + - "\xca\x0a\x4c\x68\xe7\xe3\x12\xc2\xb8\x69\x3f\xf1\x44\xc8\xa6\xa7\x10\x20\x20\xc0\x39\x11\x93\xe6\xcb\x89\x25\x19" + - "\xdb\xcf\x14\x61\xff\x28\xe0\x94\x9c\xf3\xe1\xb5\x12\x20\x2b\xc3\xb4\xd6\xc8\x02\x86\xf7\x2b\x36\x3f\xf4\x16\xd6" + - "\x97\xf5\x0b\xda\x34\xe0\xb5\x27\x0e\x99\xa9\xd8\x49\x76\xed\x9d\x0d\xe8\xf7\x52\x55\x72\x3a\x27\xf5\xe4\x56\xf8" + - "\x27\x6e\xa9\xdc\x20\xe0\x3e\x88\xc3\x28\x0a\x43\xc1\x62\x68\xb5\x75\x74\x18\x55\x69\x58\x93\x96\x5c\xd1\xaa\x02" + - "\x1d\x90\x9c\x6f\x55\x1c\xa5\x1e\xa0\x6e\x5a\x4c\x11\xc2\x35\xb8\xc2\xab\x28\x41\x05\x7b\x49\x22\x29\x8b\x3c\xb6" + - "\x84\xec\xde\xed\xe4\x1e\x52\x12\x1e\xad\xbe\x8b\x9f\x31\xda\xa4\x39\xda\x61\x83\x11\x7e\x2d\x35\xdd\x46\xbe\xb2" + - "\x32\x1c\xfe\x10\x91\x5d\xca\x67\x4b\xaf\x93\x5a\x3d\x1c\x9f\x13\x1a\xf7\xa4\xbf\xfd\xf5\x04\x13\x91\x33\x61\x8f" + - "\x0e\x78\x7c\x68\xc4\x9e\xf8\xd2\xd6\xde\xa1\x34\xb5\xf8\x51\x3b\xd1\x46\x1f\x54\x5d\x09\x85\x85\x5c\x39\xf8\x8f" + - "\xac\x8c\xd0\x15\xe5\xb0\x9b\xfe\x59\x94\x88\xe3\x3f\x1a\xb5\x4f\x24\xde\x99\x32\xb8\x22\xe8\x39\xdf\xa5\x8d\xe7" + - "\x12\xad\x29\x42\x0a\x36\xa8\x4c\xe8\xf7\x44\x04\xe5\x4f\xde\xe2\x37\x18\xd4\xe2\xd7\xa3\x34\xe6\x1c\xb7\x58\x8a" + - "\xa5\xc5\xeb\x27\x91\xe4\x29\xc9\x97\x33\x5d\x84\x7f\x34\x6f\x6f\xc0\x31\x82\x32\xdf\xfb\xc1\x53\xf7\x10\x7a\x89" + - "\x1a\xe1\x6f\xf7\xf3\xdf\x89\x1d\xf7\xa3\x7a\xab\x1e\x04\x36\x76\xa8\xc7\xf9\x98\x41\x5a\x90\xe2\x77\x5f\xf7\xe2" + - "\x7e\xcd\xb1\x0b\x37\x87\xd9\x95\x1a\x24\xda\x02\x7d\x6a\x34\x3b\x22\x81\xb9\x52\xa9\x00\x86\x10\xa3\xbb\x0c\xc7" + - "\x88\xe9\x52\xc8\x7c\xaa\x0c\xa6\x8d\x24\xef\x67\x40\x64\x6d\xe8\xc6\xa1\x40\x18\x89\xfd\xb6\x44\xc7\xb4\xb1\x15" + - "\x72\x39\x58\xe5\x14\x59\x49\xb1\x35\x3e\xda\x8d\xc3\x8f\x3e\xa7\xb7\xc9\xb6\xde\x78\x89\xbf\xc8\xec\x83\x40\x66" + - "\x11\x75\xfc\x25\xc8\xe8\x45\x81\xb9\x00\x66\xe4\x53\xad\xcd\xb4\x54\x4b\x99\x4f\xd7\xe1\xb0\x72\x69\x73\x4f\x4f" + - "\xf0\x2f\xc7\x47\x61\x39\x8a\xfa\xe9\xd6\x8c\x23\xc8\x7f\x08\x69\x61\xcf\xb5\x4a\xa2\x93\x4b\xae\x83\xb6\x28\x9e" + - "\x85\x2d\x89\x77\xf1\x8e\xc1\xb8\x3d\x37\x7c\xeb\xcd\x45\x5d\x02\x91\x0b\x3c\x4d\x11\xf3\xe8\x6e\x60\x80\xdb\xa5" + - "\x44\xf4\x35\x40\xfd\xc9\xb6\x16\xb6\xc1\x81\x4f\x10\x16\x38\xbd\x3a\x97\x68\xf6\x12\xf6\x62\x7c\x60\x0d\xbf\x59" + - "\x72\x4d\x31\x2e\x33\x12\x78\xed\xdb\x14\x4e\xd4\x26\x5f\x65\x99\xfd\xaf\x6f\xbf\x65\x8c\x40\x97\x50\x2f\x7d\x06" + - "\xbd\x79\xc7\xf5\x53\x55\xc5\x29\xfb\x61\x37\x00\xd5\xbd\x13\x28\x9b\x51\x5b\xdd\xc9\x3f\x25\x29\x93\xb7\xad\x3a" + - "\xcb\xfa\x6b\xf9\x41\x09\x83\xae\x50\xe8\x0e\xd2\xcc\xe9\x8c\xc7\x9d\xb2\xf4\x52\xe6\xfe\x92\x3c\x78\xc2\xf8\xf6" + - "\x5a\x2e\xd5\x9e\xe8\x8c\x1f\x7e\x71\xf8\xf0\xa2\x13\x55\xcb\xd8\xa6\x65\x69\x9a\x40\x29\x32\x2f\xb1\x59\x41\x5e" + - "\x3b\x1d\x4b\xed\x09\x8b\x65\x0c\xc8\x6e\xfd\x3b\x10\xc5\xe1\x7f\x6d\xf9\x45\xdc\x37\x8e\x65\xf1\xe9\x0c\x7c\xa5" + - "\xbe\x58\x59\x10\x6e\x5b\xa0\xab\x38\x79\x25\xbe\x7d\x68\x1a\xb6\xcf\x58\x05\x51\xe4\x4d\x8d\x49\xa0\x79\x83\xe1" + - "\x36\x1b\xb1\x5d\x6f\xc2\x6c\xda\x0e\x4b\xb6\xd7\x0a\xb0\xaf\xd9\x23\x11\x67\xa9\x91\xa9\x9a\x28\x2a\x73\x5c\x4b" + - "\xfa\x33\x1c\x8a\x59\x29\x2f\x59\x7c\xc6\xe9\xf3\x1b\x44\xaf\x34\xc8\x00\x14\x3d\x88\x7d\xce\x0f\x0f\x1b\xbc\x0d" + - "\x97\xfc\x73\x2e\x0e\x94\xa7\x41\x71\xe6\xb4\x28\x76\x30\x3e\x51\xae\xa6\x03\x9f\xaa\x33\x42\xd5\x0b\xe7\xdc\x25" + - "\x9e\x21\x0b\x10\x1d\xb0\x40\x66\x0f\x4b\x35\xc7\xb9\x86\x3e\xe7\x70\x7d\x34\x0d\xda\x3f\x91\xf7\x2c\xb4\xe2\xb7" + - "\x66\x43\xaa\xaf\x0a\x8e\x52\x0b\xad\x08\xea\xe2\xfe\x9f\xa1\x15\x70\x26\xb0\xda\x55\x23\x12\xb9\x59\x80\x87\x19" + - "\x2a\xbc\x63\xf2\x87\xe8\x56\x28\x66\x45\x91\x51\x29\x63\x0a\xf1\x18\xb4\xa7\x53\xf0\xbe\xf4\xdf\x1c\x50\x36\x85" + - "\x2b\x99\x61\x7c\x1c\xa0\x63\x54\x53\xbe\x36\x91\x5e\xdb\x44\xac\xb0\x35\x8b\x00\xd9\x43\xa7\xc2\xd8\xe7\x82\xae" + - "\x8f\xb0\x14\x96\xdf\x3c\x98\x02\x00\xcc\x7b\x6d\x1c\xdb\x99\xe1\x67\x2d\xee\xd6\xec\xb8\x18\x8e\xc1\x89\x39\x1b" + - "\xde\x68\x76\x6f\xb9\x46\x29\xad\xb7\xdd\xa3\x0a\xab\x23\xa1\x8b\xee\x95\xcc\x06\x3e\x9e\x8f\xf9\x3e\x78\x48\x4e" + - "\x55\xcc\xc1\x71\xcc\x7d\x84\x60\x64\x14\x08\x31\x6c\x61\x6c\x61\x41\x52\xbf\xe7\xea\x9a\xca\x34\x25\xa2\x73\x8a" + - "\x75\x06\xac\x56\x75\x95\x97\x6a\x5a\x5c\xe6\xfa\xef\x2a\x0d\x0a\x43\x8c\xb0\x2e\x13\x76\xd3\x08\x3e\x7a\x19\xde" + - "\xf5\x36\x3f\x08\x2a\x26\xe0\x87\xd3\x55\xc4\x31\x66\x58\xac\xe9\x07\xfd\x41\xdd\x5a\xa7\x1e\x8e\xf9\xe1\x35\x50" + - "\x79\xaf\x53\x8a\x5e\xf3\x0b\x89\x0b\xae\x46\xce\x53\x7e\x20\xef\x41\xe5\xeb\x7c\xda\x54\x91\x1c\xbc\x9d\x23\xbf" + - "\x7f\xad\xc4\x23\x90\xb6\x1f\x39\x16\x97\x32\x78\xfa\xae\x7a\x42\x1a\xb3\xa2\x7c\x28\xba\x74\x56\xff\x5a\x59\x1e" + - "\x31\x16\x4e\xb6\xa6\x2e\xdc\x2b\xf4\x55\xf2\xec\x7b\xd0\x10\x1e\x9e\x62\xf0\x21\xec\xb6\xcd\x8a\x86\xf9\x35\x13" + - "\xc1\x79\x50\xdd\xd3\xa2\xac\x88\x8b\x27\xad\x51\x78\xe7\x46\x13\xa9\x07\x87\xdf\xe9\xb8\xe5\x13\xec\x01\xbb\x65" + - "\xdb\x50\xe5\x4b\x4b\xf7\x01\x82\x1e\x1c\xac\x26\xd7\x8d\x5a\xe7\x6e\xc4\xf7\x41\x8c\xa9\x9b\xfd\x92\x16\xe5\xfb" + - "\xc1\x5a\xa9\x3d\x71\x28\x1a\xb1\x1a\x43\xf1\x22\x53\xce\x20\xc9\x79\x6b\x18\xaf\xaa\xc2\x25\xa0\xf0\x45\x09\x03" + - "\x6f\x18\x33\x1a\x0e\x2f\x75\x35\x5f\xa1\x3e\x83\xab\x3e\x71\xf9\xa9\xe1\x72\x95\x65\xc3\xc7\x8f\xbf\xaa\x6d\x07" + - "\x9f\x1f\x4f\x09\xbc\x8b\x59\x8c\xe5\x3f\x57\x3a\xd3\xd5\x3a\x4e\x93\xc2\x49\x9c\x6d\x52\x1b\xbc\x17\xe8\x78\x16" + - "\x33\x21\x73\xaa\xc5\x08\x7f\xdb\x02\xf4\x2d\x87\x60\xe3\x12\x2f\xc0\x56\xf0\x29\xe0\x52\x52\x3e\xea\xcd\x3f\x68" + - "\xf5\xee\xb4\xae\x9d\x3d\x16\x04\xc4\x58\x74\x3a\x1e\xf1\xf1\xaf\x20\x17\x66\xe4\xab\x17\x66\xdf\x74\x6d\x82\x68" + - "\x23\x8c\x6e\x73\xf9\x49\xc9\x89\x4a\x1b\x4e\x99\xa2\x2c\x1b\x62\x57\x1b\xa1\x1f\x7b\x9b\xc2\x70\x35\xdc\x23\xe9" + - "\x84\xbc\x1b\x24\x95\x68\x65\xa7\xc4\x80\x6f\x82\x85\xec\x8f\x05\xaf\xdd\x86\xf8\x79\x94\x09\x84\xcf\x9a\x36\x9c" + - "\xc3\xf9\x02\x65\x7c\xfd\x89\x67\x6e\x38\x99\x03\x6c\xde\x0b\xf6\xfc\x81\xbd\x0d\x7d\x13\x86\x43\x81\xe6\x73\xdc" + - "\x02\x2a\xe9\xca\x25\x04\x6d\x14\xae\x21\x45\x29\x59\xa2\xd5\xb5\xc8\x74\x1e\x5d\x76\x87\x87\x5f\x3d\xf1\xa9\x83" + - "\x42\xf7\xdb\x70\xdc\xd6\x62\x95\xa1\x93\x73\xd0\x38\x0c\xac\x72\x30\x7d\x67\x81\xa9\x2b\x23\x30\xb1\x70\xa9\xc8" + - "\x8e\x46\x45\x8e\x98\x1e\x60\x5f\x3e\xce\xe2\x08\x1f\x1c\x45\x6f\x83\x64\x12\x11\x17\x18\x6d\x48\xe8\xca\x79\xfb" + - "\xd1\x6d\x79\xd2\xd8\x84\x2f\x6b\xd1\x8b\x0e\x2f\xff\x13\x0e\x91\x65\xb0\x3c\xae\xa0\x29\x28\xf5\xa8\x52\x60\xbd" + - "\x44\x1b\xbe\xa7\x73\x53\x95\x2b\x3a\x9d\x8c\x44\xe1\xb9\xae\xdc\x99\xe6\x54\xea\x2e\xa0\xd4\xca\x41\x63\x16\x14" + - "\x28\x99\x30\x62\x75\xfa\x1e\x23\x70\x80\xab\x81\x13\xbe\x32\xa8\xb6\x0b\x92\x3b\x8d\xc4\x57\x07\x94\x45\x9d\xf3" + - "\x12\xa0\xf1\x70\x14\xa5\x0d\x08\xea\x39\x8c\x84\x2b\xeb\x40\x4f\x3d\x7b\x33\x12\x7f\x70\x8a\xfa\x99\xce\x53\xff" + - "\x0b\x75\xa8\xfa\x0a\xde\x03\xa8\x3a\xcf\x3a\x23\xf1\x87\x48\x75\x39\x12\x1d\xaf\x86\xe8\xf4\x48\xcc\x1e\x91\x13" + - "\xe4\x2d\x95\x0e\x10\xed\x6d\xed\xeb\xfd\xf0\x75\xa9\xae\x74\xb1\x32\xbc\xe9\xed\xfd\xfd\xe3\x8e\x0f\xc4\xad\x4f" + - "\xb2\xef\x2a\xc3\xd8\x49\x73\xe1\x87\x80\x25\x41\x99\xc7\x62\x96\x4d\x63\x1b\x64\xb4\xfd\x04\x97\x77\xa7\x5f\x2d" + - "\xae\x48\x09\x7d\xa9\xaf\x54\xce\x14\xb8\x2a\x5c\x72\x4d\x71\x3d\x57\xa8\xcf\xe3\x52\x34\x45\xe9\x8a\x39\x05\xa3" + - "\x3f\xb9\x40\x7d\xbf\xfb\xb1\xd9\xf0\xdf\x5f\x06\x7f\x7f\x85\x7f\xd7\xaa\xcb\xdf\x39\xbf\x38\x0f\x29\x9e\xf0\x7f" + - "\x8c\x03\x27\xeb\x60\xf0\x0e\x71\x59\xf6\x01\x26\xf3\x8a\x95\xc9\x61\xf9\x69\xc7\x2b\xf4\xe0\x1c\x11\x39\x20\xe8" + - "\xfb\x92\x18\xdb\xe0\x3d\x7c\xe4\x52\x57\xa0\x73\xa6\x43\xca\x33\xfe\xf4\x82\x26\x77\x48\x6e\x46\x54\x4a\x23\xaf" + - "\xe6\x9b\xc1\x60\xc0\x39\xfc\x1e\x8b\xeb\xb9\xac\x44\xad\x8c\x06\xbd\x7b\xe2\x13\x5b\xf8\x82\x0f\xe7\xe9\x23\xf8" + - "\xff\x1c\x6b\x63\x9c\xa7\xfb\xdd\xe3\xa0\xb7\x2f\xc5\x4d\xde\x9f\x16\x8b\x65\x91\xb3\xb7\xe6\x4d\xbe\xbf\x0e\xba" + - "\x81\x8f\x8e\xe1\xf3\x0d\x7f\xf1\x95\x30\xfa\x32\xa7\x96\xfe\x4b\x7a\xf7\xb5\xb8\x69\x7f\xf1\x17\xf7\xd1\xba\xfe" + - "\xea\x1b\xb1\x6e\x7b\x8e\x56\xf0\x76\x04\xad\x27\x54\xa9\x6f\xf7\xe1\x45\xb0\x45\x4f\xd8\x90\xd2\xc9\xab\x79\xb0" + - "\xfb\xc3\xa1\xc8\xab\x79\xff\x91\xe0\x2a\x6d\xc6\x2d\x99\xde\xd3\xb5\xec\x50\xc2\x1b\x3e\x43\x5e\xdf\x0e\x78\x10" + - "\xe5\x98\xf4\x03\x70\xf1\x81\x1b\xe4\xcc\xb1\x1c\xb3\x5c\x28\x2c\x25\x04\xb7\x42\x10\x94\x32\xc0\xcd\x77\x1f\x96" + - "\x6a\xa1\xb0\x1a\x14\x6a\x8e\x50\xcb\x31\x44\x6a\x30\x95\x98\xb7\x0e\xc4\x13\xa0\x4c\xd9\x1a\x4e\xdb\xc1\xf0\x30" + - "\xc4\xe8\x2f\x01\x56\xfb\x89\x3f\x43\xc7\xfe\x08\xed\xb3\x9f\xcd\xd9\xd7\x78\x9c\x0e\xbb\x62\x24\x1e\x8b\x47\xe1" + - "\xe9\x43\x58\x01\xee\x74\xfc\xe1\xb3\x8f\x8b\x34\xed\x04\xb9\x6a\x5d\xb7\x38\x9e\xed\xe3\x2f\x17\xee\x2c\x7d\x73" + - "\x41\x29\x32\xdb\x7a\x09\xc8\x08\xd5\x19\xc5\x54\x45\x70\xad\xcc\xf5\x44\x57\xbe\xa2\x15\x9d\xc3\x46\x6e\xe1\x70" + - "\x53\xee\xde\x93\xb6\x33\x1c\x9f\x5a\x57\xf2\x66\xdb\xb1\x45\x81\xe7\x06\xee\x3b\x76\x22\x70\x35\xe9\xc6\x16\x49" + - "\xbe\xbe\xc0\xf8\x2d\xa6\x37\x4d\xac\x8c\x0e\x39\x6b\xca\xfc\x4c\x1b\x0a\x1f\x9b\xd3\x2d\xb2\x67\x3d\xc7\xbc\x29" + - "\x96\x9a\xfa\xc2\xcd\xd2\xf4\xb5\xa9\x9f\x82\x10\x40\x9e\x0c\xde\x41\x5a\x43\x1f\xc0\xaa\xd4\x4b\x5e\x71\x58\x01" + - "\x0b\x69\x96\x5b\xfb\xf6\x2d\x72\x4d\x40\xc2\x22\xb7\x1e\x5e\xb2\x7b\xe3\x13\x5a\xa3\xa7\x51\x65\x47\xa3\xd4\xbc" + - "\xb6\xe0\x59\x52\xaa\xe9\xaa\x34\x88\xeb\x4c\x7f\x12\x6e\x18\x66\xc2\xb5\xbd\xf6\xe8\xd2\xec\x46\x9d\xcb\xf4\x0a" + - "\x2b\x71\xb2\xd1\x19\x18\x2c\x31\xcd\x0a\x64\x5d\xe8\x6e\x9e\x2b\xc3\xf0\x0b\x7a\xb7\x7d\xda\x62\x97\x89\xe8\x74" + - "\x3b\x3d\xff\xd8\x15\xef\xe5\x2f\xba\xa2\x5f\x7f\x19\x5a\x6d\x61\x26\xdc\x92\x92\xb2\xa8\x4b\xf2\x2f\xc5\xee\xc3" + - "\x6d\x3a\xf0\xdb\x74\x10\x52\x32\x3b\xce\x51\x63\x4f\xdd\xb0\xdb\x1a\x07\x38\x44\xe9\x3f\xc8\xa9\x80\xeb\xa9\x19" + - "\x56\x70\x59\x66\x8b\x4b\x6b\x11\x69\xb2\x2e\x09\x89\xf3\x7b\xb5\xdb\xde\xbd\xeb\x66\x7c\x12\xca\x0b\x96\xbb\x72" + - "\x8c\xc9\x7d\x5f\xe0\x2a\x4e\x24\xf2\x46\x2e\x54\x23\x1d\xae\x15\xb2\x38\x20\xb9\xde\xee\x63\x0c\x41\x4b\x02\xae" + - "\x30\x68\x2e\x1a\xd2\x86\x62\xb1\xda\x27\x4c\x7c\x20\x42\x8f\x17\x71\x6b\x15\x41\xdb\x82\xfe\x1a\xac\xb5\x0d\x7b" + - "\xba\x23\x39\x18\x0e\x6f\x5f\xd9\x0b\xa5\xc6\x60\x70\x49\xb1\x96\xe0\xa9\x08\x5e\x4b\xac\x4e\x97\x8b\xb1\xf0\xe5" + - "\x7a\xcf\x82\xb6\x9c\xb0\xf4\x28\xa6\x8d\xf6\x2b\xab\x12\x4f\x7c\x37\x51\x4d\xa1\xe4\xd7\x6d\x45\xe1\xa2\x11\x5a" + - "\x8a\x0a\x6d\xbe\xe8\x76\xc2\xf3\xe9\x67\x17\x85\x81\x7d\x0c\xaa\x3c\x2f\x26\x2a\xa1\x58\x17\x84\xae\x87\x42\x9d" + - "\x05\xbc\x7f\xed\xeb\x5c\x34\x34\x82\x9f\x16\x89\xc9\x99\x1a\x3a\x5d\xcb\x99\xda\x1d\xab\xf1\x84\x0d\x16\x9c\x14" + - "\xa5\x05\x17\xd0\xec\xb1\x85\xb0\x26\x76\xde\x15\x4c\x4a\xba\x12\x2f\x49\x81\x2c\x13\xab\xb3\xe3\x84\xe0\xb6\x3d" + - "\xa9\x5d\x9a\xd0\xb4\x53\x21\x90\xed\x8e\x3b\x71\xc2\x6c\xce\xf5\x6c\x1b\x35\x3e\x0f\x7c\xc0\x82\x70\x42\x1c\x72" + - "\x7f\x1c\x5c\x2c\xed\xc3\x8d\x3b\xe2\xd8\xcf\x70\xcc\xd0\xb0\xfe\x71\x8d\xa9\xf9\xc6\xbb\x1f\x69\xfc\x2b\x36\xa6" + - "\x16\x4e\xd3\xe7\xa9\xb9\x85\x3a\x95\x6f\x6f\xef\xe2\xd1\xa7\x75\xf1\x2c\xf0\x20\xa8\xf5\xf0\x45\x6b\x0f\x4c\x27" + - "\xfb\xf8\xdc\x7b\x7e\x7f\x6c\xf9\xff\xc0\xce\x12\x96\x57\x2c\x88\x29\xff\xf1\x67\xcd\x6a\xd3\x0e\xf4\xcd\xa6\x36" + - "\xc1\x03\x46\x4e\x3b\xc5\x7d\x8c\x2d\xf5\x1f\xec\x8b\x4e\xbf\xe3\xc6\xf0\x5e\x7e\x0d\xaa\xd5\x10\x8b\x2a\xd4\x69" + - "\x81\x24\xe3\x93\xf1\xb1\xe4\xdb\x13\x19\xb0\xb9\x21\x35\xe3\xca\xa2\x14\x3f\x5d\x63\xee\x77\x2d\x73\xcf\xac\xd9" + - "\xac\x28\xaf\x65\x99\xd6\x1a\xf7\xbf\xb4\x4d\xa1\x73\xdb\xb6\x98\xb1\x62\x0e\x45\x2a\xe2\x4e\x49\xa0\xea\xd4\x28" + - "\x23\xb9\x59\x39\x97\x4f\x9c\x21\x61\xce\x71\x70\xc1\xdb\xf2\x33\xc8\xdf\x8f\x50\xc0\x48\xf2\xee\xa7\x5d\x14\xbb" + - "\xbb\xb5\x5a\x2b\x2e\x29\xbb\x35\xfb\xef\xd4\x4d\x57\xce\xe0\x75\xb3\x08\x4f\x35\x7a\xf1\x00\x49\xed\x09\xac\x72" + - "\xff\x82\xfe\x46\x3d\x25\xe6\x3d\xa5\xbf\x31\xe9\x60\x4f\x98\x4a\x52\x39\x7d\xfc\x5f\xaa\xb1\x70\x17\xc1\x1b\xe0" + - "\x65\xc1\x79\x2c\x3a\x81\x6a\xaa\x23\xda\x34\x17\xb6\x13\x97\xb9\xab\xb6\x22\x9f\xb7\x9e\x6e\x72\x06\xff\xdd\x97" + - "\xa2\xfb\x68\x65\x94\x2d\x1b\xbf\x0b\x0b\xde\xdb\x13\xbb\xd4\x83\x23\x30\x51\x46\xa7\x80\xf7\xc2\xcd\x19\x25\x41" + - "\x4d\x4a\xe0\x7f\x1a\xb5\x28\x6d\x63\xb2\xa9\x13\x0c\x02\x97\x57\xa7\x5f\x05\x20\x85\xcf\x77\x02\x7d\xeb\x91\x7f" + - "\x5a\x57\xc7\xc2\x3f\x67\xf8\x71\x14\xc5\xed\x46\x64\x70\x70\x9e\xb4\xbb\x58\x04\x00\xdf\xc8\x37\x6b\x8f\xfc\xde" + - "\x69\xf3\xbf\xe5\xff\xdd\xfa\xbf\x83\x3f\x91\x3d\x24\x3d\x26\x15\x0a\xb3\xfa\xf6\x11\x80\xab\xff\x08\xb3\xcf\x5f" + - "\x2b\xf4\x5f\xb1\xa9\xfd\xd2\x22\x57\xc2\x14\x5d\xdf\x0b\x22\x94\x18\x0b\x42\x25\x97\xb4\xb4\x03\x7d\x74\xa8\x6c" + - "\x13\xb6\xd8\xdb\x8b\x51\xca\xcf\xcf\x4f\xa9\xc5\xcb\xd8\xdf\x31\x7e\xa8\xb3\x00\x4d\x39\x99\x95\xd7\xb2\x8a\x91" + - "\x7d\x06\x3b\x4f\x8f\x2e\x8e\x22\xd4\xc8\x8b\xbc\x0f\x28\x85\x47\x16\x71\x22\x19\x0c\x06\x5d\xcc\xdc\xaf\x0c\x27" + - "\xdb\xc7\x8c\xfe\x45\x2e\x7e\xa3\xde\x7e\x8b\xb0\xc5\x8e\xbf\xb7\x27\x1c\x9e\x86\x7b\x41\xe6\x92\x0f\xe2\x37\xc0" + - "\x91\xdf\x48\xca\xc1\x0c\xce\x78\x82\xb2\x35\x26\xe3\xb1\xf9\x43\xdd\x57\xfe\xf8\x0a\x9b\x93\x2c\xcc\xda\xbe\xd9" + - "\x88\xa4\xf9\x74\x2c\xfe\xb8\x0d\xca\x20\x4d\xf9\x73\xdf\xd7\x19\x6d\xca\x85\x2b\x02\x16\x60\x31\x65\x54\x1e\x73" + - "\x0a\xfc\x03\x12\xd9\x53\x5d\x96\xab\xdc\xa0\x3b\x26\x3e\x3f\x0c\xbe\xb2\xe9\xa1\xef\xfc\xe0\x71\x6d\x18\x3e\x0d" + - "\x34\x9a\x4b\xbd\x16\x94\xe4\x3b\x0b\xde\x87\x9b\xd5\x38\x54\xfb\xfb\x51\x47\x61\x1a\x0c\x3e\x6b\xc8\xcd\x46\x48" + - "\xfe\xbd\xcc\xb2\x89\x74\x31\x3a\xe8\x09\x16\x6e\x0c\xfa\x26\x03\x6a\xf9\xaf\x12\x5e\x66\x08\xa3\x03\xe4\xfc\xb0" + - "\xe1\x60\x59\x2c\x93\x6e\x37\xa6\x39\xe4\x7c\x36\x57\x39\x25\x8b\xed\xd9\xa2\x0d\x9c\x9a\x36\x40\x25\x94\xab\x26" + - "\xa5\x92\x1f\xfc\xb7\x4e\x8f\xdf\x12\x71\xb0\xbf\x8f\xd3\xb1\xeb\x85\xe7\xb5\x4b\x25\xc6\x1e\xb7\xe3\x70\x54\x78" + - "\x73\xa2\x4b\x00\xbb\xbb\x08\x29\x04\xce\xe6\xa8\x8d\x4c\xdc\x46\x47\xe7\x67\xa3\x5a\xd0\x58\xb9\x18\x92\x7a\x82" + - "\x6e\x77\x8a\x43\x75\x81\x3d\x31\x7b\x7b\x5c\x55\x41\x8c\xc9\x86\x5a\xc7\xf6\xfa\x33\xc4\xf5\xae\x5d\x5e\xd7\x23" + - "\x5c\x0d\x11\x43\xc0\x44\x08\x7b\x58\xa3\x04\x6d\x54\xc0\xde\xe5\x40\x3e\x5a\x9e\x27\x54\xd8\xf8\xb8\xcf\xd7\x48" + - "\xe2\xb5\xab\xcd\x2a\x63\xce\xea\x65\xdd\xdf\xb3\xa2\x58\x62\x4a\x9b\x09\x2a\xd3\x09\x21\x3f\x82\x8d\xff\xe4\x19" + - "\xf8\xd7\x70\x99\x7d\x5f\xfe\x9c\x4b\xca\xe3\x70\x8c\xb2\x68\x01\x82\xfd\xaf\xec\x41\x11\x20\xa0\xc9\xe9\x5c\xa8" + - "\x7c\x5a\xac\xf2\x4a\x95\x1e\xbd\xea\x17\x68\x2b\xe5\x85\x05\x13\x24\x62\x54\xaa\x3f\x8b\x51\x29\x3e\x29\xcd\xe3" + - "\x71\x1b\x82\xc6\x9f\xd5\x6d\x47\xb1\x71\x9c\xda\x6f\xe0\xdb\x96\x3b\x6e\x38\x14\x27\xf9\xb4\x28\x97\x45\x29\x2b" + - "\x02\x4c\x31\x9b\x19\x55\xf5\xe0\xef\x9c\x39\x71\x79\x29\x75\x6e\x2a\x31\x5d\x4f\x33\xc5\xc5\x6b\x02\x74\xef\x8f" + - "\x91\x65\x75\x13\x08\x92\xe0\xe3\x94\x89\xbd\x05\xb0\xd0\xb3\xff\x15\x30\xbc\x07\xe8\x46\x08\x4f\x87\xfc\xf4\xd9" + - "\xd8\x3a\x4a\x04\x93\xbe\xfd\xa8\x4e\x95\xf4\x4a\xbd\x46\x26\x70\x58\x22\xbd\xeb\x53\x76\x3a\x4c\xa6\x86\xfe\x76" + - "\x18\x70\xac\x73\x1b\x72\xec\x92\x4e\xb4\x06\xac\x3b\x83\xe2\xf0\x41\xd8\x9d\x2f\x25\xf6\xb6\xd4\x45\xa9\x2b\xfd" + - "\x77\x2c\xae\x82\x15\x0b\xc3\x60\x66\x9d\xd3\xb3\xe9\xca\x54\xc5\xc2\x85\x23\xc2\x3c\x64\x9a\xaa\x94\x22\x25\x57" + - "\xcb\xa5\x2a\xb1\x5d\xa6\x2a\x2e\xbe\x6c\x6b\x82\x04\x5a\x7b\xa3\x2a\xb2\xc4\x19\xa1\xf3\xb9\x2a\x75\xc5\xba\xcd" + - "\x30\xd8\x96\x6a\x58\x5c\x5a\xad\xb2\xf7\x02\xe3\x46\x67\x56\x17\x87\x28\x8b\x6f\x7c\xbf\xf6\x65\xdd\x43\xcc\x9f" + - "\xf5\x58\x2f\xde\x59\xe5\xec\x03\xa3\x6c\xc8\x2f\xb9\x17\xf1\x18\x71\x90\x28\xd9\x5c\xc5\x42\xae\x31\x99\x5d\x68" + - "\x64\x05\x2a\xa5\xf3\x94\x3c\x5f\x60\xb1\xf6\xab\x40\x23\x5d\x2a\xab\x54\xac\x0a\xfe\x98\xc3\x55\x50\xa9\x68\x91" + - "\xc2\x7e\xf9\x7e\x65\x2a\xa0\x82\x9c\x85\x3c\x2d\x42\x0f\xce\xb8\x54\x4d\x5d\x53\x3e\x8b\x72\xcb\x37\xf4\x9d\xdf" + - "\xad\x2a\xb1\xb0\x71\x20\x36\x5f\x2c\xf0\xb4\x45\x96\xa2\x51\x4a\xa2\x0a\x34\x1c\xcd\x7b\x46\x06\xfc\x34\x6c\x13" + - "\x12\x05\x8b\xc5\xf6\xdf\x4e\x27\xc0\xe8\x8b\x38\x29\x57\x6d\xc7\x06\xe4\x65\xf7\x96\xb3\xd3\x26\xed\x1b\xd8\x75" + - "\xa1\x83\x9f\x95\x02\xdf\x66\x14\x48\x6f\x9c\xc4\xc4\x11\xb9\x29\x67\xc1\xa7\xef\x1a\xa9\xef\xc3\xec\xf7\x4e\x75" + - "\xed\x28\x45\x7b\xe9\xb5\x9d\x1d\x9d\xc2\xb5\x51\x0b\x77\x08\x26\x96\x86\x95\xd7\x6c\x2a\x7b\x98\x9d\xa0\x74\xf6" + - "\x76\xfe\xfe\x59\xeb\x77\xae\x5a\xa7\x0f\x99\xdc\x2a\x48\x87\x18\x41\x02\xf2\x01\x2e\xd7\x04\xb4\xaa\xd5\x24\x34" + - "\xcb\xeb\xba\x6a\x3e\x7f\x23\xe7\xa9\xf2\xb6\xa8\x54\x5e\x69\x4c\x22\x3b\x2d\x40\x32\xbc\x09\x4f\x72\x27\x2f\xaa" + - "\xce\x68\x7b\xcd\x82\x9a\x46\x1b\x3d\x46\x34\x5f\xed\xf6\xe5\x92\xcb\x24\x15\x38\x80\xce\x1c\xb1\xf3\x09\x89\xe0" + - "\x1c\x01\xb3\x6a\x13\x6a\x02\xdb\x58\x95\x54\xee\xda\xb6\x46\x55\xab\x11\x14\x25\x38\xd1\xb9\xe4\x6a\xf6\x71\xc2" + - "\x09\x97\xea\xcc\xa7\x37\x73\x8f\x68\x23\x30\xe2\x82\x26\xf2\xd1\xca\x6b\x9e\x76\x84\xe6\x00\x55\x86\xe7\xf6\xd8" + - "\x76\xfe\x71\x9c\xbe\x53\xb3\x11\x64\x6d\xdb\xd9\x59\xe5\x1e\xc5\x79\x4c\xdb\x17\xf9\x3b\xdf\x2c\xb2\x9e\x38\xbb" + - "\x08\x90\x5d\x73\xf9\x84\x5a\x85\x87\xb6\x1a\x0f\xbe\xf7\xc9\x5a\xfc\xc6\xfd\x5b\xb9\x6f\xcb\xc1\x20\x36\x89\x3d" + - "\x7a\x5c\x07\x58\xd9\x21\x3c\x3e\x78\x1c\x74\x5c\xd9\x41\x5f\xb0\x0e\xa1\x05\xfd\xf9\x8e\xed\xb6\x9b\x1d\xb6\x02" + - "\x0c\xb7\x9b\x2c\x4a\xa1\x72\xc2\x81\x4a\x53\x70\x52\x00\x2b\xe7\xe9\x79\x54\x53\x4f\xb9\xfa\xb1\xc0\x1d\xc6\xc6" + - "\x89\xae\xbd\xf4\xe7\xd2\x7c\xc6\x29\xf8\xb4\x24\x93\xcd\x22\xdf\xd4\x2c\xf6\x5f\x6f\x99\x8c\x75\x0c\xdf\x3e\xa3" + - "\x28\x23\xe0\xa7\xcd\x26\x69\x3a\x8f\xb1\xeb\xf7\xc0\x7b\xaa\x6d\x36\x75\x57\xad\x50\x3f\xcb\xa3\x3e\xf3\xe1\x91" + - "\xf1\xc4\x87\x43\xd1\xf9\x85\x1d\x67\x82\x10\x7b\x8c\xea\x24\x47\x58\x76\x8c\x92\x62\x94\xc9\xfc\x32\xe9\x3a\xd8" + - "\xf0\xe7\xda\x70\xd1\x01\x53\x64\x5c\x63\x15\x28\x0d\xf7\xf4\xd0\x08\xf8\x6c\x25\x2f\x95\xad\xb5\x41\x95\x98\x15" + - "\x90\x14\xf5\xfb\x4a\x66\xd6\x56\x4a\xe1\x85\x33\xad\x4a\xf1\xc2\x3a\x9e\x17\xa5\x98\xa8\x4b\x9d\xe7\xd0\x1a\x39" + - "\xa2\x7a\x4b\xa1\x17\x0b\x95\x6a\x59\xc1\xd8\x94\xbb\x8a\x26\xdc\xe9\x77\x06\xdc\x0b\x16\x03\x03\x2c\xc4\xa4\x62" + - "\x33\xf1\xc2\x71\xb0\x77\xcd\x14\x56\xb6\x54\xe5\xac\x28\x17\x2a\x6d\x30\x87\xd9\x3a\xec\x3d\x9a\x51\x9c\xb5\x9d" + - "\x3d\x27\xa9\x02\x8a\x1f\x02\xbd\xdc\x3b\xdc\xc5\xc7\x38\x4c\xf8\xaa\x4f\x37\x00\x62\x1b\xfc\xae\x63\x5a\x80\x4c" + - "\xf0\x3a\x24\xff\xf8\x9b\xd6\x64\xb3\x75\xd9\xf9\xf8\x89\x7b\xa6\x64\xb7\xf4\x4f\xc9\xe8\x85\x1d\xa0\xe1\xa9\xbb" + - "\xcd\x11\x22\x62\xf8\xa0\x3d\xb1\x7b\x34\x95\x30\x32\x17\x9f\x8c\xf1\xc5\xbf\x60\x4c\xbd\xcb\x62\x05\x4f\x7e\x90" + - "\xf9\x25\xd3\x8d\xb4\x88\xf3\x0b\x24\xf6\x7d\x50\xcf\x2f\xf2\xed\xb7\xee\xfd\x38\xd3\x51\xf4\x28\x36\xc9\xdd\x2c" + - "\x32\x3c\x14\x64\x95\x6b\x69\x40\x2f\x6b\xd2\x6d\x30\xbc\xfd\xb3\x6d\xa1\xb1\x55\x97\x3e\x18\x13\xdc\xec\x68\xf8" + - "\xa9\x3b\xea\xf8\x86\x8c\x24\x6c\x68\xaa\x0b\x4d\xa2\xee\x32\x5e\x53\x99\x77\x23\xed\x78\x28\x43\xc7\x9c\x66\xd3" + - "\xf6\x12\x90\x93\xd7\xda\x4c\x55\x96\xc9\x5c\x15\x2b\x62\x57\x2a\x59\x5e\xaa\x2a\x92\xce\xa2\x4d\xe3\x4a\x1e\x73" + - "\x31\x16\xd7\x98\x10\x6b\x90\x15\x53\x69\xf3\x52\xd4\x1e\x01\x5b\x3b\x8f\x50\x01\x3f\xa5\xa8\x12\xe7\x14\x60\x2d" + - "\x47\x44\x2b\xd3\x58\x5a\x2c\x8b\xe2\x8e\xd9\x04\x40\xb7\x41\xbc\xaf\xec\x6d\xe6\xba\xc0\xec\x8e\x9f\xd5\x47\x4b" + - "\x42\x49\xaa\x9f\xed\xde\xcd\xa5\xf9\x1e\x93\x46\x52\x69\x90\xf8\x61\x42\xf1\x22\xbb\xbb\x89\xaf\xce\x65\x71\x6e" + - "\x5e\xaa\x19\xfc\xf8\x07\xbd\x92\x13\xd4\xb3\xc4\x86\xe1\x20\x11\x9d\x8f\xd3\xc1\xa5\xd8\x44\x4f\x9f\xb2\x98\x81" + - "\xcb\x6e\x85\x72\xbc\x4f\xb4\x61\xe1\xe2\x32\x45\x7d\x7e\x6f\x4e\xed\xee\x3a\xb3\x39\xd6\xb6\xf6\x85\xda\x0a\xf1" + - "\xe2\xf4\xf4\x49\x6f\x5b\x32\x3a\xcc\x07\x61\x5f\x01\x07\xeb\xb2\xd3\xfd\x1b\xd2\xd2\xd5\x7c\x47\xee\xb0\x33\x45" + - "\x08\x9c\xf8\x6f\xe2\x0a\x75\x6c\xa5\xe3\x21\xba\x4e\x93\xe4\xdb\x52\x8a\xbd\xb0\xb1\x5d\x5f\xcd\x2f\xc0\x3e\xbe" + - "\x13\x98\xcf\x5d\x91\x14\xf4\xff\x77\x85\x4d\x16\xf2\x83\x32\x0e\x72\xfd\xc9\xba\x1f\x14\x1e\xc5\x6b\x1a\xa7\x81" + - "\x81\xc1\x54\x07\x80\x2a\x95\x53\x07\x61\x2a\xc3\x1a\xc1\xf1\x74\xbb\xf6\xc2\x2d\x03\x51\xb9\x55\x8e\x8a\x56\xdb" + - "\x8e\x41\xc3\xa1\x60\xbe\x89\x51\x7d\xb1\xac\xd6\x77\x42\xe0\x63\x17\x31\xf6\x10\xdc\xc4\x68\xea\xa3\xfc\x99\xda" + - "\x90\x9b\x15\x71\x1f\x96\x91\x4a\x0e\x51\x75\x6b\xb3\x8d\x52\x70\x67\x02\x5c\xd9\x48\x3c\x39\x12\xd3\x54\x56\x72" + - "\x24\xbe\x3c\x12\x70\xe1\x56\x6b\x51\xaa\xd9\x48\x7c\xd5\x75\xc9\x48\x05\xa6\xd1\x04\x66\x62\xb2\xe6\x52\xd5\x22" + - "\x61\xcf\xf8\x91\xf8\xe6\x68\x8b\x6b\xfc\x48\xfc\xe5\x48\xa8\x6a\x3a\x70\xf9\xe4\x1c\x45\x7f\x2a\xbe\xe6\xba\xf8" + - "\x36\x49\x6e\x10\xef\x96\x3c\xee\xda\x72\x37\x72\xb9\x54\xb2\x44\xd1\xee\x4f\x0f\x31\x68\xc9\x25\x0d\xd3\x6a\x98" + - "\xa9\x43\x53\x62\x4b\xa6\x9f\x26\xc9\x20\x0c\xfa\x28\xf5\xd9\x8d\xf4\x5e\x8c\x17\x17\x51\xa8\x43\x80\x43\x4c\xae" + - "\x87\x51\x95\x4b\x10\x40\x94\x4c\x55\xf9\xd1\xc1\x4a\x6a\x67\x03\x96\x23\x17\xad\xda\x29\xa5\xa3\xff\xd1\x0e\x29" + - "\xbf\xcd\xa7\x74\xc8\x65\x1d\xef\xbc\x7a\x3f\xb1\x8e\xe4\xa7\x97\xd2\xb4\xa3\xb6\x56\x98\x8c\xe7\x07\x07\xe1\xee" + - "\xd9\x01\x72\x1e\x35\xce\xfd\x1d\xa6\x00\x3f\xad\x80\xb2\xf8\xb9\xe1\x88\xf8\x92\x5e\xb7\x94\xf6\xe1\xac\xb9\xea" + - "\x5a\x00\x53\xf8\x55\x10\x4d\x8f\x3c\xb4\x11\x89\x1a\x5c\x0e\x7a\xa2\x63\x94\x2c\xa7\xf3\x4e\xd7\x9e\x15\x14\x50" + - "\xda\xc6\xa3\x4e\x13\x91\x70\x58\x70\x0b\xab\x88\x7e\x20\xdd\xae\xf3\x9b\xda\x6c\x70\xdc\xb6\x05\xd2\x12\x1a\x68" + - "\x6a\xf3\xf9\xf4\x75\xde\x9f\x16\x59\xe6\xf3\xe3\x76\xf0\x88\x76\x46\xdb\xaa\x6a\x36\x4a\x2e\x31\xa8\xcf\xc4\x81" + - "\x2d\x45\xee\x04\x5d\xf4\x68\xf9\x78\x4f\x51\xa9\xc9\x9e\xa8\xe5\x9b\x74\xfd\x3b\xbf\xd6\xc3\xc6\x40\xea\xf7\x7f" + - "\x76\x98\x16\xa5\xbf\x1b\xd0\xbd\x79\x2a\x0e\xc4\xb1\xff\xb9\x6f\xa7\x32\xaa\xeb\x57\x83\x19\x5d\xa9\xfc\x5f\x5e" + - "\x3a\xea\xc5\x84\x63\xce\x89\x9c\x1e\x09\x2d\x9e\x72\x4b\xf8\x7b\x7f\x2c\x1e\xd7\x1c\xaa\x6d\xa9\xd0\xb6\xe0\xcc" + - "\x48\x11\xc6\x0d\x6b\x73\x2f\xd2\xf4\x4f\x9b\xfa\xe1\xff\xec\xd4\xb3\x7f\x1a\xdf\x5a\x10\xc1\xae\xe1\x33\xf0\x20" + - "\x5e\x6d\xbf\xaf\xd1\x24\x75\xf4\xe7\x2e\xf2\xf2\xff\xaa\x45\xee\xef\x87\x9b\xfa\xa7\x2c\x94\xab\x9a\xbb\xd0\x3c" + - "\x7f\xfb\xe6\xd5\x1c\x8b\x38\xd4\xee\xe4\xdf\xb9\xa0\x0a\xf0\xa5\x69\xca\xd5\x95\x83\x3b\xd8\x6b\xc4\x69\xd6\x1a" + - "\xb8\xcf\x3f\x44\x29\x53\x5d\x50\x3c\x1b\xfb\x13\x4e\x8a\x1b\xfb\x7b\xa6\x33\x65\xff\x5e\x4a\x63\xae\x8b\x32\xb5" + - "\xbf\xf5\x42\x5e\x2a\x1b\x08\xc7\x6b\x8e\xcd\x63\x1a\x2d\x07\x2d\x75\xab\x09\x08\xb7\xb5\x99\x98\xd5\x64\xa1\x2b" + - "\xdb\x7d\xa9\x8c\xaa\x3e\xb9\xfb\xb8\x2a\xb4\xeb\x9f\xca\xc4\x4a\xb3\x16\xcf\xdf\x9e\x50\x54\xaa\xd5\xd2\xe7\xea" + - "\x3a\x30\x03\x86\xf5\xd7\xdd\xc3\x84\x32\x78\x04\x26\x22\x9f\xbc\x61\x1c\x46\x08\x99\xda\x6e\x1c\xf1\x96\x05\x66" + - "\xc6\x71\x6d\x40\x8e\x8d\x72\xb1\x14\xce\x5d\x38\x78\xd2\xd4\xce\xc2\x2e\x94\x46\xfd\x98\x67\xeb\x20\xc6\x99\xd5" + - "\xd8\xac\xa1\xef\x51\xe8\x85\xe9\x91\x1b\x27\x60\x93\x29\xbe\x97\x65\x4f\x5c\x96\xc5\x6a\x69\x7a\xc2\xc5\x21\x92" + - "\x69\x93\xbd\x42\x38\x64\x83\x5d\x52\x9c\x3e\x38\xf2\x45\xa7\x2c\x7a\xd4\x3e\x0e\x52\xf5\xf3\x3a\x16\x07\x62\xc4" + - "\x8d\x6a\x91\xfb\x24\x91\xe0\x6c\x50\xcf\x4f\x43\xc0\x1b\x9a\x9a\x2d\xc7\xe0\x23\x25\x3d\x64\xed\x13\x9a\x88\x55" + - "\xcc\x50\x5f\x61\x3e\xc8\x17\x98\x3c\x99\xca\x5f\x95\xa6\x12\xe5\x0a\xaf\xf4\x20\x64\x4c\xa5\x28\x18\x2e\x38\x2f" + - "\x6f\x89\xe9\x96\x07\xea\x46\x4d\x5d\x7f\xb5\x74\x00\x71\xbc\x91\x4f\xf0\x31\x2d\x72\xca\x83\xc0\x56\x1e\x0c\xc1" + - "\x95\x68\xde\x41\x6d\x21\x35\x77\xeb\x85\x7f\x2d\x44\x5c\x08\x89\xbb\x33\x36\x1b\x6a\x11\x92\x07\x02\x0b\x93\x8e" + - "\x84\xf6\x15\x81\xd4\x8d\xf3\x68\x05\xa6\x44\x96\x00\x3c\x34\x42\x2b\x13\xe9\xf3\xc2\x95\xdb\xb7\xdb\xd6\x5f\xb3" + - "\xe0\x0c\x28\x93\x17\xd3\x30\x9a\x10\x4d\xcf\xe9\x13\xb3\x95\x1a\x39\x94\x74\x00\x7b\x21\x4d\x65\x53\xd5\x4a\xcc" + - "\x7a\xeb\x86\x46\xbf\x9a\xa5\x9c\xb2\x53\x04\x60\xed\xc8\xc3\xa7\x61\xd3\x12\x1d\x41\x42\x9a\xf5\xa3\xdb\x0e\x5f" + - "\x1f\x08\x54\xcf\x3a\xe6\x8e\xbd\xa5\xe1\x78\xa8\x75\x1e\x9e\xea\x18\x07\x1c\xd4\x7c\xc0\x18\x7b\xa3\xd4\x41\x87" + - "\x5a\x2a\x8f\xc1\x81\x43\x1f\xb3\xb5\xb6\xa7\x66\x1b\x87\x6a\xc1\x0e\xdc\xbd\x05\x6d\x7b\xd0\xbe\x09\x0c\x58\x47" + - "\x14\x7c\x4e\x68\x6e\xc9\x62\xa3\xed\xf8\xd3\xc1\xea\xa2\xdc\x9b\x07\xcd\x65\x81\x73\x1e\x36\x51\x5a\x0b\x8e\x77" + - "\xaa\xe6\xca\xde\xb0\x94\xd4\xce\x25\x3f\xa7\x48\x29\x6a\x8c\xee\xad\x0f\x4b\x45\xfe\x08\x40\x70\xc8\xb0\x1a\x26" + - "\x5c\xeb\x71\x2a\x75\x5b\xa9\x46\xb8\x84\x54\x4c\x15\x7d\xec\x7b\x40\xb1\x1c\x8d\xb4\xeb\x1a\xb9\x27\xac\xe2\x8e" + - "\x75\xf7\x81\xb1\x6c\x64\xf5\x05\xde\x33\xca\x0d\xc4\x9b\xc3\x01\x34\x9e\x86\x33\xb1\xeb\xc6\xd4\x91\xae\x7a\x5f" + - "\x53\xbd\x70\xe5\x82\xb8\xc7\x80\xe2\xfb\xfc\x15\x99\xca\x2d\xe5\xb6\x69\xb2\x89\xe4\xfb\xfc\x6b\x18\xe3\x51\xe7" + - "\x3e\x8f\x84\xde\xdf\xf7\x19\x90\x2c\xb1\xb7\x5d\x9d\xe9\x0b\x4a\xa9\x53\xcb\xe7\x14\xd0\xec\xdb\x68\xba\x32\x4d" + - "\x3d\xad\xb1\x78\x52\xf6\x82\x73\xde\x43\xb3\x57\xb0\x08\x72\x41\xf6\x0d\x06\xa9\xa6\xe4\x96\xc8\x85\xbc\x29\x72" + - "\x5b\xf7\x49\x8c\xe9\x53\xf4\x74\xe2\x20\x89\x30\xc6\xff\x3e\x66\x87\xcf\xad\x1a\x11\xfe\xc4\x24\x80\x61\x1a\x2a" + - "\x37\x08\xdd\x0a\xc7\x96\x3e\xc6\xfe\x59\x59\x61\xb0\x58\x0b\x27\xfd\x1b\x2e\x4b\x35\x55\x68\xcc\x0f\x9c\xda\x3e" + - "\xc9\xba\xdb\x66\x39\x68\xba\x97\x6f\xad\x11\xb6\xd9\x88\x06\x14\x1a\xda\x1e\x67\x28\x6e\x9b\x47\x53\x0b\xe4\x62" + - "\x15\x1a\xeb\x96\x59\x76\xc7\x9a\xcd\x27\x2f\x1a\x76\xb5\xc8\xd2\x17\x8d\xf0\x06\x9a\x4b\xae\xae\xad\xbb\x74\xe8" + - "\xbe\x67\x77\xee\x22\x70\x71\xfa\x05\x53\x0f\x3d\x44\x4f\x2d\x21\xcb\x89\xae\x4a\x59\xae\x9d\x97\xb7\x2b\xd1\x8f" + - "\x75\x9d\x31\x2d\x30\x55\x01\x9d\xa8\x5c\xcd\x74\x45\xce\x5c\x00\xed\xa0\x8c\x2a\x41\x3b\x32\xc1\x7f\xda\x2e\xfd" + - "\xb3\xdb\x14\x30\x0f\xdb\x76\x29\x72\x3b\xd8\xe2\x4f\x1f\x99\xa4\x68\x3b\x23\xbf\xd5\x7f\xf3\x22\x22\x37\xf7\x4f" + - "\x76\xfb\x3d\x8a\x60\x90\x58\xac\xa8\xb9\xba\xf3\x24\xad\xea\x09\x46\xe3\x86\xa8\x4a\xa9\xbb\xab\xfb\x97\x87\xf6" + - "\xa5\x45\x9e\xd8\x1f\x16\x93\x05\x62\x52\x83\xaa\x10\x0e\xed\x4c\xe1\x1c\x28\x26\x72\xfa\xa1\xbf\x2c\x8b\xa5\xbc" + - "\x44\xe7\xb7\xc2\xb9\x49\xc7\x76\x8e\xd0\xb9\xc0\xf6\x73\x26\x1e\xe3\x2a\xfd\x6c\x1e\x8b\x8b\xc0\x2b\xa4\xc5\xa9" + - "\xf8\x27\xb5\x32\x0a\x26\x32\xfd\x57\x26\xd2\x80\x1c\x49\x15\xf8\xe4\xa8\xb6\x7a\x66\x24\x16\x58\x9f\x88\xae\x4d" + - "\x80\xd5\x91\x90\x54\x57\xc2\xbe\x70\x36\xf7\x0f\x4a\x2d\x09\x0f\xec\x71\xf1\xbb\x57\x5f\xf9\x9d\x28\x5d\x8b\x9e" + - "\x69\x43\xea\xc8\x95\xb6\x05\xbd\xef\x73\x2e\xfa\xf8\x8a\x61\x78\xbc\xb6\x83\xf3\x2c\x6a\x39\x4b\xed\xd3\xd0\x4f" + - "\xf0\xf8\xb3\x28\x98\xf7\xb7\x73\xbd\x1c\x45\x34\x3d\x72\x2a\x0a\xf9\x9d\x12\xee\xcd\x8f\x1e\xf4\xcf\xd5\xd5\x13" + - "\x8f\xe1\x46\x38\xb8\x68\x40\x66\xb1\xca\x2a\xbd\xcc\xd4\x0b\x1a\xd2\x84\xcc\x06\x4f\xc3\xf4\x5a\xd2\xc4\xd5\xd9" + - "\x08\xdb\x36\x58\xf5\x5d\x6c\x43\xd3\xf9\xc7\x76\x80\x89\x71\x23\x67\xa5\xdb\xd6\x64\x62\xd1\x2a\xa6\x45\x9e\xaa" + - "\xdc\x60\xc6\x80\x40\xa4\x5d\xf6\xd8\x2f\xb5\x75\xcb\x22\xa7\xb3\x5c\x5d\xff\x1c\xf8\x9c\xb1\xcf\x5c\x7d\x95\xae" + - "\xf7\x90\x5f\x5a\xc8\xe5\x92\x79\xec\xa5\xd8\x0d\x53\xa0\xdd\x05\x81\x4f\xf0\x27\x23\xfc\x60\x89\x62\xb3\xe1\xb5" + - "\x7c\x0c\x49\xc2\x95\xb4\x55\x08\xe5\x9b\x05\xe7\xec\x31\x6b\x21\x97\x75\x35\x53\x74\xa4\xea\xd9\x48\xc3\x51\x1a" + - "\xdb\x61\x94\x3f\x6a\x4e\x52\xe9\x05\x9b\xed\x78\xbc\x65\x61\x2a\xfb\x9a\xfe\xce\x53\xfb\x77\x2d\x5f\x00\x85\x00" + - "\xba\xf6\x68\x87\xf5\x3f\x5b\x3c\x89\x83\xb6\xe3\x78\x4a\xfe\x85\x43\xb0\xa0\x77\x98\x41\xd0\x3b\xfc\xdc\xda\x7b" + - "\x9e\x6e\xe9\xbd\x6d\x19\x35\x64\xbe\xd3\x63\x92\x31\xbd\x9d\xd6\x00\xe6\x56\x6a\xb1\xec\x09\xdd\x0b\xfc\x26\x97" + - "\xa5\x7a\x2d\xc3\x7a\xb7\x30\x7c\xed\x49\xa9\xb0\x06\x85\x46\x9f\x18\xeb\xfa\xe7\x90\xd9\xf2\x50\x7f\x55\x95\xd0" + - "\xb9\xae\xb4\xcc\xbc\xd7\x24\x32\x46\x30\x3b\x67\x65\xbd\x21\xab\x34\xb4\x30\xec\x7d\x89\xe9\x47\xb6\xd2\x14\x74" + - "\x6c\x7a\xd4\x71\xab\xf2\xfc\xc4\xb1\x38\x73\x99\x60\x2f\xc4\xc8\x2f\x9b\x7d\x3c\xed\xcc\xde\x96\x8a\x0f\x44\x55" + - "\x60\x96\x54\xeb\xd4\xca\x1e\x8f\xe8\x48\x57\x5e\x51\x01\x4a\x38\x90\x70\x06\x61\x62\x7d\x4b\x53\xcc\x3a\x9f\xce" + - "\xcb\x22\xd7\x7f\x97\xce\x53\x9d\x3b\x39\xc9\x43\xd1\x1a\xa5\x71\xb7\xa8\xdd\x40\x72\x63\xdf\x25\x4f\x75\x10\x02" + - "\x38\xf8\x6b\x20\x3a\x01\xce\xd7\xb6\x8f\x5d\x9c\xa8\x3d\xaf\x8a\x07\xff\x71\xe5\xd3\x27\x5b\xd9\x91\xf3\x05\xda" + - "\xbb\x56\x46\xc8\x55\x94\x4c\x11\x54\xca\x48\x53\x94\x18\xf1\x88\x53\x0e\x90\x1c\xb3\xba\xf9\x7d\xb7\xa8\x45\x23" + - "\x04\x78\x8c\x61\x22\xf8\xf1\x71\x00\x85\x51\xf4\xf1\x66\x13\x1d\x1f\x1f\x25\x0d\x53\x1d\x0c\x06\x3a\xaf\x54\xc9" + - "\x5e\x82\x91\xc1\xdc\x88\x5c\xc1\x0f\x59\xae\xf9\x83\xb3\x0b\x1f\x01\xcd\x5f\x17\x2e\xfb\x39\x30\x3d\x76\xc7\x28" + - "\x66\x35\x5b\xbb\x4b\x90\x1e\x8f\x42\x1d\x47\x79\x92\x1f\x05\x2a\x9a\x3c\x15\xcb\x52\x2f\x80\xf1\x67\x4d\x85\xa3" + - "\xb9\x16\xc2\xb1\x9a\xca\x33\x05\x27\xb9\xa3\x4f\x3f\x02\x46\xb5\xc8\x46\x5e\x19\xf4\x7c\xb9\xcc\xd6\x01\x44\xdc" + - "\x28\x11\x90\x68\x20\x38\xb1\x74\x53\x32\xd6\x84\xa3\xd8\xa3\xca\xb4\xd7\x7f\x9e\xf0\x49\x3f\xbb\x68\x99\x8a\x3d" + - "\x15\x3f\xe7\x7d\x62\xda\x66\xac\x4d\x74\x87\x76\xb2\x16\x9c\x38\xb6\x9a\xab\x85\xb0\xd1\x91\x6e\xad\x74\xd1\x88" + - "\x31\x8e\xf2\x89\x2c\x8b\xbd\xb5\xe0\x93\x9a\x03\xb4\x5f\xd2\x99\x5d\xd2\x99\xbe\x10\xa1\x3f\x74\x79\x92\x37\xde" + - "\x85\xce\xd1\xb7\xed\x7a\x21\xc4\xcb\xe8\x66\x8c\x31\xd7\x23\x6c\x3c\xd9\xa0\x95\x9f\x26\x93\x38\x0a\x5c\xc9\x65" + - "\x16\x6c\x05\x46\x10\xd1\x16\x39\xef\x9c\x08\xa9\x75\x0e\x9c\xb6\xef\xd5\x32\x2e\x56\x55\xa6\xb8\xe4\xb8\x65\x59" + - "\x03\x9e\xf0\xc7\x55\x55\x0b\xc3\xf8\x14\x67\xf3\x00\xa6\x75\x6f\x73\x94\x0f\x30\x98\xd9\xef\x28\x17\xd5\xc5\x8f" + - "\xb9\xc4\xfe\x1a\x24\xe1\x70\xa5\xae\x03\xdc\x75\xd6\x11\xfb\xed\xf1\x0e\xeb\x6d\x11\x1b\xfc\xaf\x07\x41\xc2\x7e" + - "\xe6\x49\x44\xc9\xce\x2e\xba\x3d\xc6\xdd\x9a\x56\xc1\x91\x36\xcc\x33\x68\x99\xae\x96\x7b\xa6\xf2\xc2\x8e\x15\x33" + - "\x10\x8b\x3d\x09\x67\x6f\xb0\x3b\x81\xdc\x0e\xe3\xbb\x40\xec\x85\xca\x84\xb7\x33\xd8\xef\xe3\xd6\xe0\x18\x76\xa6" + - "\x18\xf1\x1d\x80\xdd\x60\xa2\x8e\x48\xba\xc4\xe8\x00\xe8\x92\x0e\x84\x4d\x11\x6c\x9f\x44\x31\x02\x75\xb9\xc6\x52" + - "\x9c\x34\x00\x95\x07\x50\xcf\xd5\xbd\x0e\xa6\xaa\x67\x82\x13\xdd\xdc\xaf\xe7\x36\x8d\xb6\xca\x91\xa4\x88\xa2\xe2" + - "\x3b\x9f\xc8\x38\x88\x5e\x72\x70\xb6\x99\x88\x83\x1b\xa2\xd7\xdc\x87\xa0\x2c\x9a\x7f\x87\x0f\x6c\x15\xd4\x6d\x07" + - "\xb5\x89\x63\x6e\xb9\x21\xf1\x0c\xf0\x2b\x16\xa1\x01\xb3\x07\x12\x68\x74\xd2\xf6\x65\x33\xd5\x6a\xb7\x29\x20\x51" + - "\xeb\xef\xcb\x62\xf1\x0e\xf5\x9b\x2d\x3a\x55\x94\x7d\x5f\x58\xe2\xec\x98\xdb\xf7\x77\xaa\x59\x39\xd6\xe7\x27\xce" + - "\x46\x6a\xad\x55\x36\x3b\xe9\x99\x55\xa7\x1e\x5c\x90\x8b\x0b\x4b\x24\x0b\xaa\xb7\x1d\x7c\x56\xef\xc8\x46\x14\xba" + - "\x9e\x3a\xa2\xe3\xc5\x99\x7a\x6b\x2c\x04\x22\x0e\xbc\x6f\xcb\x3b\x20\x8a\xc5\x2a\x4f\x25\x59\xc6\xdd\x85\xa9\x72" + - "\x83\x49\xc5\x30\x0c\x52\x85\x65\x55\x4b\x25\xa7\x73\xcc\xbc\xcd\x59\xde\x96\xfd\x4c\x5d\xa9\xcc\xd2\xc6\xc4\x74" + - "\x9d\x1c\xca\x60\x12\xe3\xba\xde\xf7\x13\xfd\x7b\x43\x58\xb3\x5b\x8e\xa8\x03\xc5\xa6\x8b\xeb\xb9\x51\x9f\xe7\xeb" + - "\x7f\x72\xe0\xf8\xb0\xc7\x3b\xcd\xed\x5d\xc4\xc7\x27\x4d\x85\x2c\x93\x67\x8d\x7a\x05\xad\x4a\x05\x17\x9d\xb2\x5b" + - "\xdf\x37\x64\x4e\xa1\x69\x50\x6d\x61\x77\xcc\x3a\xb2\x45\x61\xaa\x17\xae\x04\x03\x79\xb3\xd2\x89\x48\xc2\x15\x78" + - "\xb9\xbd\x1b\x70\xe2\xe1\x51\xe5\x86\x5b\xe6\x18\x9d\x6a\x0f\xe2\x6d\x12\x2a\xeb\x24\x2e\x3e\x55\x38\xf6\xf1\x6a" + - "\xed\x27\x43\xdb\x93\x51\xb7\x39\x32\x84\xe3\x7d\xde\xae\x03\x72\x47\xb6\x6b\xfd\x90\x5a\x28\x65\x6c\xb6\x6f\xce" + - "\xc1\x92\x19\x22\x53\xfe\xad\x0b\xe7\x3c\x6a\xe4\xea\xc3\x6a\x04\x32\x13\xab\x25\xca\xcc\x8a\x84\x96\xa5\xf3\x49" + - "\xb1\xd3\xf2\x34\xb2\x25\xfc\x2e\x34\x2d\x23\xdf\xeb\x72\x21\x5a\x78\xf9\xbc\x5c\x89\x9e\x09\x99\xaf\xbb\x28\x14" + - "\x91\xc7\xb0\x98\xcb\x3c\x75\x61\x86\x98\x9e\x7e\x7f\x5f\xf3\x1d\x64\xb7\xe8\xbd\xdd\xa2\xf7\x7e\x8b\xec\x94\xda" + - "\xb7\xe6\xbd\x05\x4b\xc8\xae\x44\xb1\xf2\xd1\xf5\xe6\x6d\x44\x6e\x7f\x1c\xf7\xf4\x8c\x52\x63\xdc\xb1\x7d\xf5\xa6" + - "\x81\xfd\xcb\x0e\xed\x0b\x72\x79\x1b\x05\x4e\x55\x5c\x4b\x23\x64\xbb\x79\xb9\x27\x74\x6e\x54\x59\x09\x99\xbb\x73" + - "\x0d\xf0\xeb\x5b\x8f\xe3\xdf\x1e\xb9\x64\x31\x4c\xdf\x7d\x0a\x2b\x8d\x9e\x76\xdd\xc1\xb4\xc8\xa7\xb2\x4a\xfe\x10" + - "\x6c\x59\x65\x00\xe1\xfb\xc7\xe2\x22\x70\x5f\x14\x1d\x71\x8c\x49\x0a\x47\xa2\xd3\x11\xb7\x36\xd5\x44\x77\x4b\x6c" + - "\x66\x6c\x89\x2d\x3d\x14\x9e\x8a\xf7\x2e\x65\x69\xdb\xc5\x65\x27\xa9\x7b\xe2\x3d\x1c\x4b\xfb\x25\xef\xf2\x96\x6f" + - "\xbd\x0b\x41\xdc\xcb\x7b\x54\xdb\xb6\xf4\xd1\x66\x85\xa4\x56\x91\x1b\x93\x53\x97\x12\x17\xea\xa4\xb3\xa3\x56\xb5" + - "\xd3\x76\x2c\xb8\xeb\xe2\xfe\x6b\x59\xac\x96\xfc\x8d\x49\x6a\x9d\x98\x5e\x80\x76\xe1\xad\x3e\x59\x9f\x62\xe2\xff" + - "\xe0\x6d\x10\x9b\x88\x2b\x9e\xac\x6d\x7c\xc9\xb8\xde\x6b\xbd\xa9\x59\x2d\x55\xf9\xda\xd1\x92\xba\xbe\x27\xa4\x95" + - "\x01\x97\xe3\xa8\x79\xa4\x66\x26\xf2\xfa\xde\xb3\x1a\x21\xdf\x96\xbe\x28\x56\x38\x21\xae\xf1\x87\xb7\x7e\xe7\xa0" + - "\xe3\x32\xdc\x7a\x2d\x27\x32\xd9\x7b\x7b\x3e\x42\xd8\x2d\x35\x0d\xe3\x86\x79\x6e\xdf\xc9\xe9\x07\xac\x0b\x58\xbf" + - "\x62\xbc\xab\xc6\x2f\x1c\xf5\x26\xb3\x6b\xb9\xe6\x7a\x68\x5c\xfa\x0f\xc7\x72\x5c\x43\x51\x06\x4b\x0b\x75\x49\x0d" + - "\x65\x92\x07\xf1\xde\x9e\xa5\xc0\x79\x7a\x86\x59\x46\x2f\x12\xd2\x26\x05\x50\xf2\x73\xf9\x19\xab\x58\x57\xea\x52" + - "\x95\xce\x10\xa4\x67\x33\x57\x6f\x01\x13\x6e\xb8\x0f\x43\x52\xbb\xc3\xcd\x7f\xc6\x9a\x29\x62\x2c\x12\xfb\xfd\xbe" + - "\xbb\x30\x2d\x30\xd8\x85\x98\xb8\xa8\xd7\xb2\x9a\x0f\x4a\x20\xcc\x8b\x04\x2f\xdd\x83\xc1\xa1\x9d\x11\xb1\x81\xb8" + - "\xba\x5a\x84\x32\xe5\x08\x6b\x6c\xf4\x4e\xe3\x26\x1f\x47\x17\x7d\x58\x74\x6a\x1a\xf0\x43\x51\x62\xe1\x50\x58\x58" + - "\x4a\x52\xc5\xd4\x10\xd5\xa9\x57\x02\x69\xc2\x7e\xff\xff\x07\x91\xeb\x37\xfd\x9b\x90\x82\x12\x6e\x72\xbd\xbb\x52" + - "\x51\x26\x88\xc2\xf7\x6e\x0a\x1b\x49\x4d\x08\xf8\x1b\x15\xcf\x9f\x28\xd1\x39\x38\xe8\x60\x81\xd8\x6b\xdb\x6d\xe8" + - "\x05\xfe\x6d\x8f\xe3\x58\xec\xcb\x77\x45\xa6\x30\x23\xca\x9b\x22\x55\x3f\x68\x53\x45\xd5\x8e\x4e\x5e\x8d\x44\x87" + - "\xe0\xd7\x39\xe2\x2f\x47\xe2\x69\xbe\x5a\x4c\x54\xf9\xac\xeb\x63\x4f\x43\x0d\x08\xbb\x53\x79\x8e\x03\xe0\xc7\x64" + - "\x2a\x34\x7d\x1a\x14\xdb\xac\x0a\x3f\x64\x48\x6c\x95\xd3\x10\x19\xe3\x68\x48\xaa\x8d\x53\x97\xeb\x03\x1e\xa6\x06" + - "\xf6\xb3\xf7\x51\xfd\x8e\x7f\xc6\xe4\xcb\x71\xdb\x4d\x15\x7f\x23\x2f\x4d\x5d\x76\xdf\x86\x72\x0e\xf5\x85\x33\x9e" + - "\xd2\x21\x68\xde\xda\xee\x9c\xbd\x2b\xe5\xf4\x43\x10\x52\xef\xe5\x78\xd4\xbc\x56\xac\xa4\x34\x11\x18\x81\xb2\x46" + - "\xea\x98\x77\x73\xb5\x26\x8c\x41\xa2\x71\x59\xe4\xca\x49\xb4\x32\xcb\x7c\x99\x7d\x4b\xf1\xdb\xc4\x78\x6b\x4b\xb3" + - "\xbb\x13\x01\x2c\x44\xce\x7e\x3f\x58\x90\x9f\x04\x55\xa0\x50\xe4\x55\x44\xb5\x66\xb0\x72\xc9\x95\x2a\x5d\x98\x91" + - "\xcb\x83\x41\xda\xd6\x2a\x9c\x47\xa4\xa3\x0a\x69\x6d\xeb\x26\xb5\x09\xf8\x5e\xa7\x18\x40\x0e\x0e\x66\x13\xbe\xc1" + - "\xed\xc9\x24\x7f\x7f\x2c\x74\x20\x50\x13\x94\xf7\xf6\x18\xdf\xa3\xa6\x6e\x92\x21\xd6\xb6\x20\x6d\x70\xf7\x35\x10" + - "\xd6\xa1\x6a\x60\x73\xf3\x17\xc8\x76\xa7\x92\x00\x11\x6a\x00\x43\xd6\x18\x69\x36\x12\x00\xcb\x66\x59\x16\xba\x02" + - "\x72\xa3\x17\xc0\x9c\x29\x66\x73\xb9\x60\x8c\xaf\x04\x5e\x3b\x48\xbc\xdc\x67\xe2\x20\xdc\x97\xad\xb9\x4f\xd0\xe0" + - "\x96\x84\xd6\x38\xf4\xad\x74\x8b\x6a\x28\xe0\x76\xa2\x77\xa8\x28\x5a\xb2\xa8\xd8\x48\xb8\xd0\x6e\xbb\xf6\x4b\x7f" + - "\xa9\xcd\x54\x96\x9c\x2a\x50\x20\xcb\x37\x2f\xb2\x54\x95\x36\x16\x86\x2d\x1e\x98\xe2\x5b\x4e\xab\x95\x93\x10\xec" + - "\x61\x88\xae\x6f\xaf\x67\x0e\x1e\xb7\x69\xe1\xe0\x92\x08\x40\x1c\x5e\x01\xed\x0a\x94\x5a\x7f\xae\xa3\x53\xa5\x52" + - "\xac\x03\x66\x94\xdf\x34\xb3\x9a\x4e\x15\x31\xdc\xd6\x2e\x44\xcf\x8c\x99\xad\x32\xcf\xc0\x99\x4a\x2f\xa9\xc6\x78" + - "\xb4\x99\x35\x4a\x85\x59\x26\x99\x6b\xf1\xd3\x08\x78\x2d\xaf\xbb\xab\xa1\xc0\x7e\x1b\x1f\xd7\xf5\xb9\x80\xf8\xab" + - "\x46\xb9\xb4\xe6\x46\x36\x0e\xec\x8f\x57\xaa\x2c\x75\x0a\xb4\x29\xa7\x45\x00\xff\x59\xcc\xc4\x65\x56\x4c\x64\x86" + - "\x57\x50\xae\xb0\xec\x4d\x44\xbd\xb6\x51\xe1\xbb\x69\xf0\x76\xb6\x80\x78\x92\xd6\x08\xce\x55\x60\xab\xdd\xa9\x55" + - "\x7b\x25\x3a\x71\x4c\x0a\x8a\x30\xcb\x41\xc4\xb2\x76\x5d\xe1\x3e\xf7\xcc\xb2\xdc\x9c\x4d\xc6\x3b\xa2\xfb\x07\x6d" + - "\x7e\xe8\x64\xa9\x18\x3e\x12\x27\x79\xa5\x4a\x90\x73\x81\x55\x43\x77\xca\x47\xc3\xd0\xc5\x80\xbd\x11\x3d\xa7\xe2" + - "\x78\xd2\x3a\x0b\xe3\x5e\x38\x87\x74\x9e\x42\xf9\x71\x9f\xf4\xdd\xd8\x29\x1d\x4d\x03\x39\x71\x20\xd2\x57\x27\x2b" + - "\x66\xc2\x95\x2c\x70\x4f\x59\x17\x36\xa5\xda\x46\x2b\x9b\xe5\x07\x1d\xe4\x28\xb7\x9d\x77\xfd\x0b\x9c\x3d\x62\x6d" + - "\x45\x54\xf0\xc0\x44\xc6\x62\x42\x35\xa7\xdb\x0e\xd5\xda\x6d\x24\xcc\x2d\xbe\x45\x7c\x23\xa7\x68\x9f\x82\x29\x70" + - "\xc7\x6f\xd5\x26\x84\x87\x85\x2e\x2f\x0b\xa6\x36\x3d\x6b\x5d\xf6\x69\xfd\xe2\x7e\x64\x39\xf3\x4e\xaf\xbc\x55\x69" + - "\x94\x3c\xac\x7d\x23\x1b\x68\xf4\xcf\xc8\x77\x5d\x6f\x28\x3c\x05\x5e\xc3\xc1\x1c\xb3\x2e\xd1\x56\xc8\x78\x1e\x83" + - "\xc0\x27\x36\x8c\x3d\x08\xcb\x95\x4a\xeb\x0a\x11\x95\xb9\x7b\x2e\xb2\xe2\x9a\xb5\xa1\xf4\x25\xe6\xde\x75\xae\xba" + - "\x80\x3f\x14\x22\x8c\x11\x8d\x74\x80\x1e\x1a\x07\x14\xec\xc4\x4f\xd1\x61\x5e\x54\xf7\xee\x14\x79\xf3\x8d\x3d\xb9" + - "\xb7\xbe\xfd\x73\xff\x27\x56\xc4\x5e\x96\xaa\xff\x91\xae\xc5\x64\xa5\xb3\x2a\x9c\xce\xc0\xe5\xad\x0a\xc6\x74\x55" + - "\xf6\x9c\xf4\x56\x2f\xc4\x77\x2b\xce\x98\x74\x5e\xb4\xbe\x04\x3a\x7e\x81\x33\xc4\xfa\x44\xa1\x51\x83\x0e\x06\xfb" + - "\x98\x72\x09\x3f\x9a\x68\xbd\xcc\xd8\x16\x1a\xe3\x78\x8f\xe0\xd2\x72\x67\x9c\x88\x8b\x8f\x75\x81\x7f\x39\xe4\x45" + - "\x80\x70\x49\x94\xc4\x62\xe5\xd8\x96\x13\x30\x51\x31\x09\x3b\x6a\x87\xae\x22\x1e\xf8\xfe\x3d\x7f\xaa\xdd\x45\xe5" + - "\x8f\x77\x12\xe0\x91\x1d\x60\x10\x3a\x47\xd8\xbf\x1d\x96\xfa\x34\x5e\xf6\x2f\x9b\xdc\x97\xdc\xd7\xdf\x95\x28\xb7" + - "\x2d\x74\xae\x17\xfa\xef\x56\xd7\x47\x19\x02\xac\xa8\x86\x56\x40\x02\x00\xa0\x38\xf2\x0f\xc0\x5f\xa3\x33\xb9\x25" + - "\x83\x21\x85\x09\x73\x4e\xf3\x49\x79\x27\x3f\x00\x3d\x34\x36\x11\x3a\xe5\x77\xa8\xf8\x00\xd3\x45\xc4\xb5\xd0\xcb" + - "\xa2\xa8\x3c\xb0\xb4\x11\x32\x17\x27\x58\x04\xc9\xa9\x90\x6c\x88\x46\x5b\x41\x14\xa6\x17\x54\xd7\x2f\xb4\x9a\x88" + - "\x67\xe2\x31\x4a\x6c\xa4\xb8\x1b\x7b\x03\x49\x37\xd0\xa2\x9d\xbc\xf4\xf1\xc8\xb6\x34\xe8\xa5\xaa\xbe\x5b\x9f\xa4" + - "\x81\xa4\x3c\xa8\x55\x33\xdc\x56\x50\x7b\x67\xa7\x5d\xbf\x79\x18\xeb\x37\x89\xfc\xba\xfb\x38\x09\x15\x15\x27\x2f" + - "\x3b\x17\xbc\x12\xab\x0c\x0e\x83\x53\xda\xd2\xf1\x74\x7b\x41\x01\x65\xdc\x6f\xd1\x25\xe7\x3d\xc7\xa4\xfa\xf7\x71" + - "\x1e\x2b\xef\x21\x67\xb9\x93\xb7\xa5\x72\xb8\xec\xb8\x2d\x94\xb4\x4c\x05\xff\xbd\x52\xa5\x9e\xad\xd9\x89\xbb\x5c" + - "\xa3\x5b\xb4\xa9\xd4\x52\xac\x96\x42\x0a\xa4\x5c\x21\xc5\xa7\x8b\xc3\x76\xe8\x86\x9f\xd6\x99\x91\x46\xc2\x7b\xcb" + - "\x91\xb4\x90\x52\xbb\xf7\x56\xb3\x48\x51\x2a\x14\x45\xb0\x35\x0c\x47\x21\x89\x20\xb4\x46\x61\xa9\x28\x45\xa9\x2f" + - "\xe7\x55\xbf\x2a\xfa\x99\x9a\x55\x4e\x17\x10\x5d\xa2\x54\xaf\x09\x24\x07\xc3\x0c\x94\x2b\xdb\x14\x7a\xf8\x60\x24" + - "\x5a\x84\x7e\x5b\xaf\xdd\x1a\x3a\xea\xd0\x19\xfd\xf9\xa4\x28\x2b\xc1\xd9\xd5\x75\x25\x64\xa0\x5e\xf6\xbb\x59\xc3" + - "\xb1\x84\xc3\x04\x09\x67\x30\x83\x7d\x78\x35\x07\xa2\xfd\xad\xef\x23\x01\x6c\xf3\x46\x8a\x3c\xf5\xc9\x93\x43\x13" + - "\xc1\x29\xc6\xd1\xf7\xf8\xca\xa7\xc0\x33\xda\x39\x80\x9f\xcd\x3f\x68\x38\x8b\x44\x3d\xd3\x20\x0f\x85\x30\x1f\x23" + - "\xad\xb4\x1a\xf6\xad\xf8\xbd\x25\xdf\x94\x55\x18\x97\x3c\x94\xad\xf8\x12\xdb\x3c\x31\x22\x0a\xde\x38\xcb\x52\x13" + - "\xbb\xe8\x88\x44\x3a\xc4\x5a\x1a\x28\x52\xfe\xe3\xa4\xb5\x11\x94\x42\x04\x85\x77\xab\x97\x2e\xd5\x42\xea\xbc\x67" + - "\xab\x16\x5b\x5d\xb3\x2c\x9d\xcf\x91\xc5\xcc\xa5\x53\x9d\xfb\x4c\x4d\x31\x46\x7b\x69\x64\x8b\x0e\xfc\x28\x94\x52" + - "\x77\x1b\xc9\xf3\xb6\x0b\x5d\x81\xf8\xd6\x72\xdc\x6b\xf2\x64\xa8\xff\x69\xf5\xe3\xa4\x08\x3f\x64\xd3\x81\x96\xab" + - "\x1b\x35\x5d\x11\xcb\x8b\x4a\x07\xd8\x7d\xc7\x11\xe8\x19\xde\x17\xec\x4d\xb2\x2c\x8b\x2b\x4d\x75\xd3\x91\xbc\xe0" + - "\x2f\x56\xfe\xfd\xe6\x93\x5a\x96\x2a\xe4\xa5\xf8\x0c\x2c\x8a\x94\xea\x6f\x47\x19\x32\x31\x47\xf6\xfd\x7b\x3b\x01" + - "\x61\xc1\x2d\xad\x25\xa9\xec\xb9\x68\xca\x6e\x42\xa2\x81\xb2\x77\xb5\xd7\x43\xd7\x6a\x88\x73\x01\x5f\xef\xf1\x56" + - "\x43\xb8\x00\xfe\x9f\x8f\x6a\x5c\x53\xba\xbd\xce\xf1\x50\xfc\x98\xab\x7e\xa5\x17\x4a\x48\x0c\x28\x60\xad\x0d\xbe" + - "\xc2\x42\xdc\xa6\x92\x13\x2c\x82\x7c\xff\x5e\x4b\x11\xeb\xb1\x65\xcb\x11\xeb\xaa\xa4\xd3\xe9\x36\xeb\x56\x0f\xde" + - "\x17\x3a\x87\x57\x94\x82\x8b\x3e\xb0\xe3\x3b\x35\xeb\x8b\x79\x59\x2c\xd4\xd3\xc3\x2f\x29\xc4\x9b\x94\xf3\x5c\x88" + - "\x3b\x28\xf3\x4d\xf7\xf7\x5a\xc0\x7a\x1f\x56\x41\xde\x52\xcb\xa5\xcb\x52\x9b\x80\x7b\xf5\xd3\xae\x17\xe9\x06\xee" + - "\x67\x37\x2c\xa4\x6d\xa7\x74\x42\x4e\xa5\xc0\xa9\x84\x79\x01\x39\xc7\x91\xbb\x83\x31\x72\xda\x55\xd6\xef\x36\x16" + - "\xf4\x8b\x9a\x7c\xd0\xd5\xd3\xaf\x9e\xfc\x65\xf0\xe4\xb1\xe8\xdb\x4c\x48\x5f\x0f\x0e\x06\x4f\x86\xb4\x5a\xf1\xf8" + - "\x2b\xa0\x89\x37\x58\x7b\x41\xd8\x67\x7f\xe9\x62\x47\x2f\x55\x45\xf2\x05\x25\x09\x9a\x16\x39\x7a\x3c\xe8\xfc\xd2" + - "\x65\x36\x14\x8f\x50\x82\x43\x8f\xc4\x47\xf1\x06\xb9\xaf\xc7\x00\x44\x55\x56\x81\xf7\x6e\xaa\xaf\x6c\x72\x61\xaa" + - "\x1b\x13\x24\xc8\x3a\xec\x61\x86\x21\xfa\x65\xc4\x97\x22\xa1\xa1\x74\x7e\xd9\xf5\x88\x04\x3d\x0c\x08\xda\xca\x82" + - "\xc0\xe6\x29\x48\x7c\xb6\x32\x0a\x5e\x67\x2e\x3c\xe9\xa4\xfa\x0a\x13\x06\xee\x61\xca\x88\xdb\x26\xc8\x28\xe1\x0a" + - "\xf1\x03\x57\x2a\xaf\x7c\xaa\x95\xa1\x4b\x3e\xd5\x41\x47\xb7\x65\x41\x1a\x8c\x0e\x36\xe7\x34\x4d\x0b\x93\xe6\x83" + - "\x85\x9e\x96\x85\x29\x66\x15\xd6\x03\x57\x79\x7f\x65\x86\x99\x9e\x94\xb2\x5c\x0f\x17\xe6\xab\x27\x5f\x7f\xf9\xf8" + - "\xdb\xff\xf5\xf8\x9b\xff\x3c\x1d\x7c\xf3\xd5\xff\x7a\xfc\xed\x40\x9a\xe5\xcd\xfd\x7b\x44\xe8\xda\x20\xc5\x80\x4a" + - "\xf5\x15\x25\xd9\x44\xc6\x6b\x2c\x3a\x4f\xa5\x98\x97\x6a\x36\x7e\xf8\xe0\xe1\xb3\xa7\x43\xf9\xac\x73\x14\x81\x27" + - "\x48\x83\x54\xcb\xec\x02\x5f\xf1\x59\xe8\x3c\xe8\x08\x84\x04\x0f\x22\xd3\x94\xca\x02\x27\x02\x13\xc0\x6c\xa0\xed" + - "\x66\xae\x80\x63\xd8\x5c\xeb\xb4\x9a\x77\xea\xe5\xc9\x7a\x5c\xd1\x4b\x9b\xff\x7a\xfd\x43\xe4\x9a\xb0\x1b\x3d\x8a" + - "\xd2\xe5\x44\x13\xe2\x0e\xf2\x2d\xe9\x73\x30\x11\x0d\xdb\x8e\x1e\x87\x26\xcf\x30\x07\x41\x64\x2c\xc1\x27\x3f\x1b" + - "\x77\x62\xfe\x93\xb2\x67\xe6\xa4\x2e\x44\x9d\x53\x04\x10\x64\xa1\x3a\x5d\xbb\x09\x16\x8b\x83\x34\x54\x9b\xcd\x67" + - "\xee\x0d\x3a\x5a\x0f\x69\x4f\x6a\x9b\x61\xa2\xb5\xf3\xe0\x3d\x57\x43\xed\x13\x76\xd0\x7e\x64\x8b\xbb\x76\xb6\x6d" + - "\xa1\xed\xfb\x33\x77\xec\x13\xea\xf4\xd9\xa4\x46\xad\x59\xf4\x02\xa8\x7f\xce\x6e\x85\x6b\xc4\x8b\xa4\x2a\xc4\x0c" + - "\x19\xd8\x09\x65\x0a\x34\xe2\x7a\xae\xf2\xa8\x9d\xc8\x30\x6d\xe0\x47\x4f\x4f\x00\xd5\x78\xef\x5d\x82\x40\x97\xe9" + - "\x68\x0b\x30\xed\x1c\x3e\x09\x9a\x20\x3c\x5f\xc9\xec\xe8\x13\xce\xc2\x19\xa5\xa4\xba\x70\x19\xe3\xc4\x71\xdb\x51" + - "\xb0\x5e\x44\xc9\x95\xcc\xda\x12\x36\x01\xc0\x12\xae\x7f\x87\xb7\xf4\x95\xcc\x06\xe8\x3b\x83\x9c\x84\xf5\x57\x82" + - "\xa7\x94\x78\x95\x3b\x74\xa5\x56\xe3\x4d\x8a\xd2\x0f\x23\x99\xbc\xed\x26\x9c\xfa\x92\xa5\x6e\xf8\x3f\xaa\x34\x3f" + - "\x60\xae\xda\xb5\xe6\xc7\xaa\xbd\xe2\x79\xdc\xe0\xac\x33\xc2\x6c\x2b\xc1\xa3\x20\xcd\x07\x3f\x5d\x59\x23\x73\x43" + - "\xf3\xec\xdb\xb0\x64\xc5\x2d\x38\x05\xb1\x7f\x8d\x1b\xf0\xb2\x98\xfa\x26\xf8\xc4\x37\xb0\x19\x93\x43\x0d\x2d\x3d" + - "\x71\xcb\xc5\xf2\x83\xa1\x54\x54\x9b\x37\xa9\x07\xc2\x06\x47\xee\x33\x03\xf7\xa6\x7a\x27\x2f\x41\xf4\x1d\xfe\xfa" + - "\x34\x39\xbf\xde\xef\x9e\x9b\x47\xe7\xc3\xe3\x67\xc9\xf1\xe8\xe9\xf9\xf0\xfc\xf0\xd9\xa6\xfb\xc5\xb0\x1b\x0f\xa7" + - "\xcd\xa9\xad\xff\x36\xfc\x75\x70\xf6\xeb\xe8\xc1\xf9\xd9\xf9\xa0\x77\xf1\xe8\x8b\xa1\xe3\x17\xe0\x3d\x1a\x81\x7c" + - "\x32\xe2\xa9\xcc\x1c\xa2\x4a\x60\x9f\x50\x74\xe1\xa8\x10\xe0\x65\xd1\x2a\xe7\x98\xd7\x6b\x9d\xe7\xc5\xb5\xd3\x0a" + - "\x9a\x9e\xf8\x7d\x25\x33\xcc\xb8\xdb\x43\x7e\x36\x08\x2f\x72\x00\xf5\x4a\x70\xd7\xd8\x9b\x5f\x19\x83\xb8\xf1\x65" + - "\xa9\x96\x61\xef\xf5\x33\xa4\xdd\xd1\x18\x3e\x12\xef\xcd\x5c\xe7\x95\xe8\xff\x72\x70\xf8\x8d\xe0\x52\xd8\xae\x4e" + - "\x9c\x1b\x8a\x2d\x48\xfc\xbd\xf3\x33\xdc\xc5\x2a\xa2\xec\xf5\xc8\xfa\xa1\x5b\xaf\xc8\xf6\x9f\x3b\xe5\xc6\x3f\x31" + - "\xe1\xa6\xeb\xa1\x73\xbd\x0c\x41\xf1\x91\xb9\xb0\xca\xcc\x7f\x11\x15\xed\x0c\x09\xb3\xc3\x02\x66\xc8\x5b\xe0\x5d" + - "\x9b\xbf\x0d\x83\x0b\xb6\xd1\x2f\x06\x37\x34\x54\x15\x04\x53\xf8\x84\x0e\xc2\x64\x33\xff\x0c\xd4\x1c\xd0\x62\xb7" + - "\xd1\xda\x48\xa2\xcb\xa5\x56\x42\x30\x7a\x0a\x15\x4d\x33\x52\x70\xc2\x51\xec\xd9\x68\x23\x8f\xbb\xd6\x27\xc8\xb9" + - "\x31\x70\x32\x39\xbb\x1b\xbe\xe5\x0e\x13\xae\xce\x28\x2f\x2a\x2c\xe3\x8a\x0f\xb0\xca\x6b\x63\xe5\xa1\xb3\x8a\xaf" + - "\x51\xd5\x16\x07\x8e\x34\x38\xa0\x98\x56\x11\xe0\xa5\x5f\xc2\x65\x1c\xac\x8b\xc1\x5e\x38\xdf\x0b\x31\x12\x14\x06" + - "\xd4\xfa\xb9\x5d\x70\x63\x0b\x3e\x8a\xb5\x2d\x93\x64\x54\xf5\xf9\x32\xec\x80\xf9\x40\xdd\x54\x2a\x4f\x31\x07\x0a" + - "\x0c\x3f\x6a\x51\x29\x87\xd7\x1f\x19\xa6\xac\x63\xf7\x5c\x47\x6e\xdd\x30\x83\xc0\x79\xca\xa8\x6c\xc6\xad\x8e\x82" + - "\x68\x96\xba\x4a\x79\xb7\xe5\x78\xb8\x70\x5e\x18\x61\xb9\x32\xf3\xd3\x4a\x4e\x3f\x58\x22\x15\x4e\xcd\x62\x74\x23" + - "\xb9\xe0\x8e\xcd\x92\x85\x59\xd4\xda\x3c\x6d\xad\x22\xa2\x76\x53\x60\xef\x33\x4c\x94\xd5\x23\x8f\xa9\xc8\xee\xdd" + - "\x12\x99\x1d\x7b\x33\xd4\x92\x0c\x7d\x7c\x1a\xc1\xee\x87\x02\x7f\x30\x0b\x80\x6b\x5d\x09\xf8\x86\xeb\x5b\x73\x76" + - "\xd5\x2f\x5a\x4c\x00\xa2\x0b\xaf\x8b\x85\x32\xf0\xda\x3d\xac\x8d\x44\xae\x89\xb4\x75\x75\x78\xc3\x3e\x63\x28\xb8" + - "\x88\xae\xec\x84\x66\x24\x46\xc1\xcc\x4a\x55\x85\xa6\x22\xec\xc9\xfd\x3e\xae\xfd\xde\xe7\x7a\xaf\xee\xc1\x28\xb2" + - "\x2d\x79\xc5\x02\x91\x87\x5e\x50\x6a\x7b\x3b\x7e\x6e\xc1\x19\xbe\x04\xe1\x71\x2f\x8a\xc6\x3c\xbb\xe8\x51\x38\x39" + - "\xef\x18\x0e\x93\x17\xd5\x9f\x3d\x06\xa0\x4a\x38\x84\x36\x9f\x30\xc2\xee\x2e\xf7\x49\x7a\x56\xe8\xd8\xab\x56\x4f" + - "\xbc\x2b\x5f\xe8\x34\x3d\x74\x6e\xcf\x01\x2a\xa0\x45\x96\xaa\x38\x99\xb9\x5e\x82\xc0\x84\x96\x0a\x1c\x86\xf4\xc7" + - "\xb6\x5b\x53\x88\x2f\x92\xce\x72\x44\x79\x3c\xbb\x03\x6d\xe0\x17\xa6\xe2\xec\x8a\x6b\xcc\x14\x12\x60\x3f\xb2\x1e" + - "\x12\xa4\x72\x2e\x99\x70\x5d\x88\xce\x92\xaa\x21\xec\xb4\xda\x8d\x82\xc2\xd5\x11\xbf\xd5\xa2\x83\xa6\x13\xd5\x3c" + - "\xee\x96\xc1\xad\xc1\x18\x1f\xe2\x5e\xc2\x5f\xdd\x40\x6d\x7d\xeb\x34\x02\x0d\x25\x0c\xe3\xb4\x28\x26\xef\xd5\xb4" + - "\x72\x4d\x9e\x8b\xa9\xca\xab\x52\x66\xa2\x54\x33\x55\xaa\xa0\xce\x3e\x9a\x77\x78\x52\x56\x1b\xd1\x65\x8e\xae\x28" + - "\x2a\x7a\xd3\xb3\x3a\xc6\xe7\xb6\xde\xea\xb5\x5c\x7b\xe3\x38\x40\x0d\x05\x4a\x82\x86\xb1\xaa\x44\x57\xc6\xeb\x81" + - "\x4e\x45\x71\xa5\x4a\xf1\xb4\x92\x97\xcf\xbc\x52\xf1\xbf\x4e\x4f\xc5\x95\x96\x22\x4a\x51\x2f\x92\x07\xdf\x7e\xf5" + - "\xf8\xb0\xcb\x3a\x97\xaa\xd4\xd3\x8a\xba\x2f\xd5\xb4\xb8\xcc\x11\x33\x44\xf2\xe0\xf0\xf0\xf1\xb7\x07\x23\xf2\x50" + - "\xa5\x0a\xa3\xb8\x67\x4f\x51\xf9\xf2\xfb\x4a\x4f\x3f\xbc\xa2\xdb\x71\xf8\x6b\x72\x3c\x3a\x37\x8f\x92\xa7\x67\xe7" + - "\xd7\xe7\xbf\x5c\xec\x3f\xeb\x9e\xfd\xfa\xec\xe2\xd1\xe6\x41\x72\x76\x7e\xdd\xbf\x78\xd4\xed\x7e\x31\xa4\x25\xea" + - "\x5c\x07\xac\xf2\x2c\x1f\xf0\x83\x3b\x8c\x92\xe1\x55\x82\x17\x1d\xdd\xe8\xde\x2a\xfd\x1f\xcf\xdf\xbc\xfc\xe1\xd5" + - "\x08\xf0\xb0\xd3\xed\x89\x2f\x12\x90\x64\xf0\x0f\x57\xb8\x1c\x7f\xd1\xb9\xf5\x82\xd8\xb6\x42\x2c\x7c\xf9\x84\x84" + - "\x93\x44\xbf\xfa\x1e\xb4\xdf\x4d\x6d\xac\x9b\x75\xdf\xa2\x26\xb6\x2a\x63\xe7\x69\x64\x0d\xf5\x6e\x17\x83\x30\xf9" + - "\x2c\x35\x7d\x16\x35\x75\x26\xbe\x31\xd6\x7e\xf6\xf6\x8a\xe7\xa4\xa5\xa4\xd2\x6b\x34\x51\xfb\x43\x96\x64\x86\x54" + - "\x39\x57\x70\x7b\xfa\x0c\xbd\x52\x71\x51\x68\x9f\xfc\xa0\x97\x7c\xce\x2f\xd5\x0d\xa1\x1e\x75\x6c\x4d\xb4\x67\x1c" + - "\xae\xe1\xf7\x08\xbd\x79\x9d\x05\x27\xf6\x72\xb0\x5f\x79\x5c\xb1\xf9\xdb\x62\xaf\x8d\xd0\x37\x88\x2a\x0f\xcd\xab" + - "\x45\x26\x8a\x12\xb3\xbb\x0b\xb3\x22\xd7\x59\x67\x36\x35\xc2\x4b\xb3\x70\x32\x1e\xb0\xbf\x6a\x90\x40\x70\x6f\x8f" + - "\xbd\xf2\xce\x0e\xd1\x25\xcd\xda\xff\x22\x43\x47\x84\x3a\x30\x64\x57\xf4\x9f\x89\x2f\x12\xf4\x64\xec\x06\x06\x1c" + - "\xd7\x93\xbf\xd2\x1b\xf6\x3b\x4c\x71\x2e\xf3\x29\xa0\x02\xd3\x88\x63\xfb\x0e\xf6\x7b\x14\x38\x1d\x7b\x3b\x8b\x99" + - "\x96\x7a\x59\x91\x7f\xb5\x25\x8f\x98\xa7\x06\x15\x9a\x55\x60\x90\xc1\x24\xed\x48\xb1\xb3\xb5\xc8\xd8\x92\x4c\x89" + - "\xd7\x26\xe4\xfa\x79\x8d\x46\x03\xcc\xb5\x86\x5b\xea\xcc\x0f\x58\x2a\x87\xbb\xe2\x83\xb7\x50\xe5\xa5\x4a\x04\xdd" + - "\x3d\xfc\xcc\x7d\xe9\xa2\x40\xec\xba\x5d\xcd\x28\xbb\xd6\x36\xc3\xb0\x5b\xed\xa0\xb8\xce\x55\x69\x55\xb1\x61\xbc" + - "\xd5\xc8\xa9\x63\x5d\x8f\xb0\x6a\xfe\x3b\xa8\x9e\xd5\xb2\x37\x3d\x74\x6b\x36\xdd\x90\x09\xf3\x92\x34\xdf\x06\xc1" + - "\x46\xed\xed\x79\xe9\xf4\x6d\x26\x75\xfe\x23\x52\xec\x80\xa5\x09\x19\x34\x62\xb8\x08\x77\x74\x5e\xa7\x3c\x76\x46" + - "\x6f\xbd\x63\x75\x31\x73\x8d\xa8\x3e\x63\x96\xa9\x54\x48\x23\x16\xaa\x9a\x17\x29\x1a\x07\xac\x0f\xee\xfd\xc8\x5f" + - "\xb2\x45\x66\x86\x6d\x38\xe3\xd1\x2f\x6a\x6e\xcb\x3b\xd1\x4b\x37\xfd\xa0\x79\x2d\x1f\xd1\x60\x30\x40\xaf\x05\x97" + - "\x1a\x00\xf3\x7a\x99\x20\x95\xbe\x6b\xdd\xc8\x9f\x84\x83\xa1\xb6\x33\xb1\xa4\xb6\x75\xbc\x9d\xd8\x2d\xb3\xc5\x3f" + - "\x33\x26\xa5\x2d\xe7\xed\x81\x4e\x79\x2f\x6b\xb3\x60\xc1\xcc\x29\xee\x2f\x55\xc5\x5a\xfb\xef\xd6\x27\xa9\xdd\xe3" + - "\xc7\x17\x35\x6c\xa1\x34\x6b\x81\xed\x09\x2e\x4f\x9c\x32\x6a\x0a\xbf\xcb\xe4\xf4\xc3\x44\x95\xe5\x5a\x7c\x39\xf8" + - "\xda\xda\x14\xfc\xe7\x64\xd8\x40\x4a\xc9\x9e\xfa\x59\x91\x5f\x62\x9e\x0c\xb2\xb8\x58\x74\x7e\xf0\xf5\xb7\x5f\x3f" + - "\x09\x91\x10\xe7\x6b\xe5\xbc\xb6\xfa\x11\x7c\x7e\x01\xfb\xc2\xa2\x4e\x3e\x8e\x00\x23\xe4\xe1\x4d\x8d\xb7\x08\xb6" + - "\xc4\x0a\x95\x36\xc1\xb5\xc5\x8b\x46\x45\x33\xbf\x03\xf8\x9d\x27\x53\x76\x01\x47\xe1\xeb\x2d\x6e\x5a\xcd\x0d\xdc" + - "\x89\xa9\xb4\xdf\x46\x12\x38\xbf\xc0\x5a\xbf\xdd\xfb\x75\xbf\x07\xe7\x76\xe1\x89\xc0\xe0\xfd\xef\xb8\xc8\xba\x23" + - "\x86\x3f\x98\x9b\x4d\xc0\x18\xb5\x48\x1e\x47\xdb\xe7\x61\xa9\xbc\x7d\x9f\x5c\xcf\x35\x9c\x68\x43\x89\x2c\xd5\xef" + - "\x2b\x7d\x25\x33\x54\x8f\x15\xf0\x95\x8b\xe6\xc4\x31\xa0\x8f\x6e\xcb\x3d\x16\xf2\xef\xd3\x82\x2b\x59\x80\x90\xbe" + - "\x5d\x3a\x8a\xee\xb5\x68\xa2\x2f\x7f\x7c\xcd\xe8\x8c\x43\x85\xd0\x72\x97\x7b\x5d\x1f\x55\xdf\x4b\xbf\xf5\xf1\xae" + - "\xb5\xa2\x4a\xf3\x24\x46\xf3\xb1\x8c\x57\x97\xdf\x9c\x5a\x8f\x25\x20\x89\x0e\xeb\x4b\x25\xd3\x75\x7d\xbe\x2d\x94" + - "\x2c\x60\xa9\xea\x4c\x15\x71\x49\x7e\x67\x07\xd8\x27\x49\xf2\x8e\x4f\xeb\x58\x2e\xbe\xde\xae\x8d\x9f\x1f\x0e\xc5" + - "\x2b\x36\xc3\x87\x95\xd6\xf4\x8c\xa6\xdb\x7a\x01\x1a\xa7\x61\xb1\xf8\x15\x72\x7a\xf1\x36\x44\xda\x06\x37\xc5\x78" + - "\x53\x5a\xbd\x73\x9a\x9b\xe2\xf7\xce\xb5\x0a\x63\x90\x78\xf8\x58\x83\x06\xcc\x0f\xfa\xfe\x85\x3c\x31\xe9\x16\x50" + - "\x48\xb1\x3a\xdf\xbf\x82\xf0\x46\x99\x5c\x75\x15\xba\x4a\x3a\x82\xe2\x73\x69\xa3\xd3\x8a\xac\x90\xae\x01\xbb\x52" + - "\x69\xf6\xdc\x84\x6f\xa3\x9c\xdb\x8e\x43\x6f\x31\x45\x37\x64\x9d\xfb\xf7\x82\x13\x3b\x76\x1a\x17\x87\x3e\x56\x98" + - "\x42\xa1\x87\x68\xa4\x59\x96\xea\xca\xca\x0e\xfc\x68\x03\xcf\x92\xe3\xd1\xcf\x79\xa5\xb3\xcd\xf3\x2c\xeb\x76\x41" + - "\x6c\x80\x8d\xb6\xd7\xea\xe5\x4a\x96\x32\xaf\x38\xdb\xc5\xb2\x2c\xd2\xd5\x14\xc4\x32\x36\x0b\xc0\x5d\x87\xf4\x1e" + - "\xd9\x5d\x74\xca\x28\x8b\x45\xf4\xfe\xfe\xbd\x1d\xdf\x89\x0b\x59\xc3\x2d\xb5\xd5\x64\x38\x31\xfa\x7d\xeb\x2a\x91" + - "\x57\x26\x78\x94\x63\x85\x1c\xf7\x13\xe6\x4c\x3f\xdd\xa6\x38\x43\x80\x53\x93\xa5\xba\xac\x97\x12\xe9\xc1\x05\xd0" + - "\x13\x2b\x58\x6b\x43\xc4\x89\x02\x0a\xab\x72\x95\x63\x8d\xe1\x31\xb7\x8e\xf0\x91\x0f\xf5\x9d\xa9\x29\x1b\x6a\xc8" + - "\x5d\xf4\xe2\x8b\x84\x93\x36\x3d\x65\x1c\xcd\xe5\xe6\xe1\x78\x2b\xab\x4c\x04\xa9\xdf\xad\xc4\x5f\x7c\x4d\xa7\x9a" + - "\x9d\xed\x01\x3e\xce\xdf\x26\x4e\x2f\x98\x1e\xf9\x6a\xb4\xec\x8a\x12\x42\x32\xef\x45\xfa\xcc\x3a\x00\x8f\x42\x7d" + - "\xda\x91\xc8\x8f\x44\x2e\xc6\x22\x6f\x2d\xfd\x43\xaa\xdf\x3a\x08\xf6\xf6\x44\x8e\xe0\x8a\xc3\xd7\xe2\x75\xe4\x6d" + - "\x4e\xdb\x2d\xcb\x70\x7a\x85\x56\x5d\xea\x5c\x46\x4a\x1e\xaa\x4d\x17\xe5\x30\xc3\x27\x26\x38\x61\xf4\xc4\x92\x05" + - "\xd6\xb3\xc2\x0d\x41\x2d\xe3\xc8\xc9\xf0\x1e\xdb\xa6\x01\xbd\xab\x06\x48\x5b\x84\x5f\x43\x0f\x4a\x22\x05\x8f\x8f" + - "\x0e\xf4\xcd\x7c\x8c\x81\x1e\x34\xf4\xb5\xea\x06\x5b\xcd\xf9\x81\xdb\x94\x5e\xa6\x55\x33\x30\x5d\x71\x58\xaf\xcf" + - "\x41\x48\x90\xa8\xeb\x9b\x9b\xe7\x6b\x59\xa0\xbf\xf0\x1d\xda\x25\x43\x9e\x4c\x35\x49\xdf\xc4\x6a\xe8\x2d\xfa\xa7" + - "\x60\xba\xd0\x45\x78\x1b\xb8\x9b\xec\xa0\x86\xa7\x2d\xe0\xa6\x57\xd3\x95\xd5\x93\x9e\xe9\x8b\x23\xfc\x09\xb2\xd8" + - "\x8a\xee\x28\x7b\xa5\x70\xb3\xe9\xaa\x6c\x65\x48\xbd\x4f\x13\x4a\xfc\x8e\x4a\xcf\x4a\x79\x19\xa4\x41\x25\xcf\xd5" + - "\x55\x19\x16\xc2\x3a\xc4\x03\x91\x00\xc4\xac\x1d\x79\x59\x18\x2a\xf4\x98\x4c\x57\x25\x27\xf1\x89\xf2\x94\x51\x02" + - "\xff\x25\x16\xb4\x2f\xf2\x7e\xe8\xb7\x4e\xd6\x55\x2b\x52\x87\x43\xd9\xc3\x67\xb9\xdd\xbb\x8c\x25\xb0\xf5\x1e\xdc" + - "\x35\x67\xc6\xf8\xa0\x02\x60\x9c\x00\xb3\xdd\xe7\xaf\x7e\x5a\x02\xad\xed\xa2\x1e\x42\xd5\xa2\xe8\xb6\x28\xd6\x15" + - "\x23\xff\x77\x80\xdc\xe4\x51\xa5\xca\x85\xce\xe9\xe6\xb6\xea\x58\x10\x2b\x83\x52\xb7\xd7\xba\x9a\xeb\x9c\x3e\xa8" + - "\xe6\x3e\xf5\x53\x2d\x02\x00\xd5\x6a\xa9\xba\x69\x2f\x56\xc5\x7c\xdd\x9b\xc2\x15\x54\xe9\x89\x30\x57\x0b\x7a\xc3" + - "\x20\x96\x38\x0e\x68\xb7\xdd\xb0\x49\x92\xe8\x81\xb8\x40\xd7\x3f\xfb\x23\x46\xb1\x63\x4b\x5e\x4a\x53\x25\xdd\x01" + - "\x5c\x8e\xcf\xb3\x2c\x71\x55\x8a\x47\x2e\xf7\x8b\x9b\x99\x9b\x45\x58\xbd\x37\xd4\xac\x39\x83\xea\x36\x8b\x4f\x6c" + - "\x3c\x8c\xaf\xa6\x5e\x30\xed\xba\x39\xe4\x87\x62\x6a\x43\x23\xc3\x1d\x20\x0f\x3b\xa3\x4b\x1f\x3d\x1a\x20\x44\x3c" + - "\x58\x53\xc9\xae\x81\x5b\x9e\x2a\x7d\xa5\x4c\x5d\x5d\xdc\xe3\x0c\x6a\xa5\x71\x09\x81\x80\x49\x5d\x19\x4e\xcb\x85" + - "\x57\x30\xcb\x47\xc7\x7c\x83\x1f\xa0\xd1\x0f\xfe\x86\x26\x21\x16\xc9\xb4\xd5\xf2\xd6\xa0\x8e\xed\x88\x7c\x3f\xb0" + - "\x22\x31\xde\x86\xf4\x2b\xd4\x10\x81\x08\x9e\x74\x7b\x0d\x43\x5a\x38\x12\xc9\x4d\xdd\x96\x39\x7e\x27\xa7\x1f\x3e" + - "\xd5\x3a\x22\xd3\x50\x8a\x72\xc9\x02\x3c\x1f\x0d\xf8\x44\x8a\x1c\x31\x12\xb5\x27\xf6\x4e\x73\x31\x21\x7e\x32\xee" + - "\xde\xf5\x29\x57\xe9\xf2\x47\x8a\x80\x9c\x18\x4f\xc7\xb1\x51\x8e\x84\x9e\xa5\xba\x24\x16\x2a\x22\x50\xbb\x96\x41" + - "\x0a\x63\x9a\x56\x65\xcd\x26\xad\xe4\x94\x6a\x45\xd0\x21\xd9\x56\x4e\x0e\x2e\x30\x6a\xd1\xac\x7c\x1b\xda\xb6\xb8" + - "\xcd\xde\x1e\xff\x55\x9b\x0e\x90\x22\x6e\x32\xb2\x0e\x4c\x64\x3e\x62\x06\x7b\xdb\xf8\xb1\xe0\x91\x6a\x67\x80\x0e" + - "\x93\xff\x07\xd6\x28\xee\x0e\xf9\xf4\x26\x5f\xab\x6b\x5c\xed\x27\xf5\xee\xbe\xf1\x56\x35\xe4\xb3\xef\x9c\xb0\xdb" + - "\x45\xee\x2f\x60\xeb\xa2\xe9\x22\x8b\xfe\x59\x3d\xd9\xd4\xe0\x2d\xbd\xc1\x20\xcf\xb3\xc6\xba\x3f\xbe\xda\x3b\x66" + - "\xf7\x4f\xf5\xf7\x91\x39\xfe\xcb\xbb\x13\xce\xb7\xb9\x3d\x30\xfa\xbf\x8e\x00\xb5\x25\x34\x87\xe1\x8d\xf9\x44\xd4" + - "\x75\xdb\xd8\xac\xe7\xba\xd9\x88\x3f\x6e\x51\x55\x63\x5d\x29\x7b\x81\xfc\x81\x63\x79\xf9\xef\xb3\xc6\x52\x71\xa9" + - "\xd1\xb0\x43\x27\x3d\xde\xd9\x21\x76\xc0\x6d\x43\xbd\x79\x4c\x8a\xcf\x2e\x7a\xdc\x12\x46\x79\x83\x0a\x4b\x47\xde" + - "\x42\x07\x0f\xf2\x42\x9c\xe5\x3c\x8a\x93\x35\xbc\x7f\x61\xd0\x18\xe1\xdd\x6b\xf5\xdb\xf0\x9c\xb2\xd3\x48\x2c\x2d" + - "\x83\x3f\xcb\xc3\xad\x72\x37\x36\xba\x2b\x72\x74\x52\xff\x2b\x76\xd8\xe9\x20\x9a\xf8\x5b\x3b\xd0\x99\x60\x17\x5b" + - "\x35\x30\xc8\x67\x7c\x8a\x75\xad\x31\x53\xeb\xb2\x54\x0f\x7f\x4d\x5b\xf4\x3d\xa1\xd6\xec\x59\x20\xf4\x62\x76\x85" + - "\xff\x8f\xbc\x7f\xef\x6e\xdb\xb8\xf6\xc7\xe1\xbf\x95\xb5\xfc\x1e\x46\x70\x8f\x4c\x5a\x14\x29\xd9\xce\x8d\xb2\xa2" + - "\xc7\xb1\x9d\xc6\xdf\xc6\x76\x4e\xe4\x36\xed\x23\xab\xee\x88\x18\x92\x88\x40\x80\x05\x40\x51\x4a\xe4\xf7\xfe\x5b" + - "\xb3\x2f\x33\x7b\x06\xa0\xe4\xb4\x3d\x67\xfd\x2e\xab\xab\x31\x05\x0c\xe6\x3e\x7b\xf6\xf5\xb3\x17\xe5\xa5\xf4\xf9" + - "\xf7\x82\xe2\x76\xac\x44\x70\xb3\xeb\xb1\x22\x36\x70\x85\x2d\xa3\xd7\x4f\xe6\xd2\x54\xb5\x51\x25\x04\x29\x00\xd8" + - "\x18\x12\xd8\x87\x60\x97\xb3\x87\x64\x2f\x35\x55\x76\x09\x86\x7a\xd1\x09\xa9\x4b\x21\x91\x05\xfd\x3e\xdb\x82\x6a" + - "\x85\x6d\xf4\x36\x0b\xaa\x1b\x38\x5d\xaf\x6d\x82\x3b\x14\x1d\x1f\xcb\x66\x3d\xcf\x40\x23\xd1\x1b\xbd\x3f\xd9\x1d" + - "\xcd\xbc\xab\x22\x99\x94\x01\x30\x4c\xd1\x5d\xcd\x49\x98\xa7\x65\xb5\x80\x00\xf0\xc9\xdc\x60\x55\xf4\x86\x33\x56" + - "\xfc\xe6\xb4\x5a\xcf\xcb\xe2\xd2\x54\x0d\xd5\xb5\x87\x5f\x36\x26\x15\x09\x9d\x5d\xfd\xf2\x6d\x61\xd9\xae\x22\x55" + - "\x88\xf2\x9a\x15\xdc\x98\xc7\xbe\x87\x40\x80\xb7\x58\x4b\xcf\x55\xe7\x3d\xc3\x90\x57\x53\x47\x41\xdf\x4e\x5d\xc1" + - "\x33\xee\xe6\x96\xbc\xe3\xf9\x35\x0a\x27\x3d\x31\x45\x7d\xe7\x36\xe2\xce\xdc\x87\x81\x9a\xe6\xda\x69\x1e\xb0\xc1" + - "\x53\x7c\x66\xab\x67\xf9\xf8\xa3\x74\x03\xc7\x52\xce\x75\x1a\xc3\xa5\x9f\xc3\x60\x94\x06\x03\x14\x80\x15\xe7\x59" + - "\xdd\xa8\x15\x61\xf1\x1a\xe5\x22\x26\x14\x44\x13\x5b\xa9\xa3\x1e\xdb\x4f\xed\xff\xb7\xa8\xd3\x63\x2b\x74\xe0\x6f" + - "\x9d\x63\x0d\xf6\xc8\x2d\xf5\xc4\xec\xd5\xc6\x7e\x28\x27\x1e\x63\xb0\xb3\x3c\x57\x93\xb9\x2e\x66\x46\xcd\xcb\x35" + - "\xd4\x66\x79\x34\x13\xf5\xe4\xdc\xcc\xb5\xe5\x84\xc1\xed\x63\x61\x97\xa4\xa9\x74\xca\x80\x7d\x58\xa5\x33\x78\x60" + - "\xaf\xd4\xb7\xd7\x2e\xc0\x25\x1e\x18\x34\xab\x27\x8d\xca\xb3\x0b\x03\xa2\x12\xc4\x66\x84\x85\xec\xf2\x23\xc6\x00" + - "\x54\x97\x4c\x2d\x27\x9f\x78\x38\x8d\x26\x5b\x98\x7a\xe8\x9a\xfb\x91\xa1\x72\x78\x36\xfc\xf4\x14\x13\x33\xde\xda" + - "\xda\x82\x56\x11\xce\x53\xb5\x87\x68\x9b\x82\x18\xe1\x73\xe0\xed\x61\x13\x4e\x8c\xea\x61\x17\xd5\x0b\x33\x35\x55" + - "\x65\xd2\xbe\xab\x76\x61\x16\x65\x75\xed\x2a\x46\x9c\x5e\x40\x05\x2a\xa7\x3e\x27\x09\x81\x98\x68\xb0\xd6\xdb\xc9" + - "\xc6\xd4\x41\xd7\xbe\x75\x9d\xa6\x18\x95\x0e\xd2\xac\x9e\x02\xca\xfb\xdc\x60\xaf\xe6\xba\x56\xe7\xc6\x14\xd4\x25" + - "\x88\xf4\x54\x7a\xad\xaf\xc9\xf1\xc6\x96\xb3\x14\xad\x51\x09\xf4\x27\xfb\xd5\xa4\x89\xab\x8c\xb3\x09\x6f\x1c\x03" + - "\x12\xb5\x78\x72\xc4\x72\xc9\x59\x81\x8e\xd2\xac\x14\xa5\x27\xa7\x6c\x5c\xb3\x1d\xf6\x55\xd7\x4d\xb9\x7c\x5b\x7c" + - "\xa7\xf3\xda\x8c\xb7\x20\xc2\xa6\x5a\x2d\x71\x8d\xc1\x9d\x01\xf4\xbb\xa2\x25\x8e\x0f\x22\x57\x1e\xac\x65\xe4\x58" + - "\xf0\xe7\x54\xae\x0e\xae\xbd\xe0\xd8\x73\x78\x1f\x52\x1c\x47\xac\xaa\x72\xd1\x26\x3f\x5d\x44\x27\x9b\x02\xb4\x0e" + - "\x87\xf8\xf5\xd6\x86\xfc\x76\x98\xfc\xa0\xcc\x67\x05\x12\xae\xdc\x45\xc9\xbb\x07\x2d\x55\x52\x6f\x23\x01\xba\xb9" + - "\xd9\x4c\xc5\xfa\x81\x77\x28\x69\x17\xd5\x6f\x1f\x07\xbe\x0c\x5e\xd8\x96\xd4\x59\x19\x58\xd7\x0d\xec\x11\xdc\x70" + - "\xaa\x37\x25\x54\xfc\x69\x59\xcd\x4c\x83\xb1\x75\x76\x81\x08\x93\x16\xf6\xee\x80\x04\xe8\xef\x2c\xc5\x6a\x4a\x75" + - "\x51\x94\x6b\x3b\x0b\x78\x46\x75\xad\x74\x8e\x26\x18\xd8\x7c\xa0\xd9\xb2\x3f\x6e\xfd\x2c\xab\xad\xfc\x64\xaf\xb3" + - "\x1c\xbe\xa3\x40\x64\xfc\xe5\xbe\x04\xd9\xd9\x2d\x7d\x53\x62\xd7\x7b\x80\x25\x92\x11\x3e\x8a\xdd\x74\xd7\x76\xd3" + - "\x71\x6e\x4a\xf3\x73\xd6\xcc\xfb\xbe\xb6\x93\x46\x57\x0d\x57\xf9\xb2\x48\x59\xe8\xcf\xcb\x72\x89\xdb\x2b\x6e\xff" + - "\x07\xaf\x40\x04\x53\x48\x6a\xae\xc0\x05\x20\xea\xb0\xef\x59\xcf\x45\x6e\x9e\x5f\xab\x0a\xd9\x08\xb7\x4d\x44\x57" + - "\xa0\x2a\xae\xf7\x19\x82\x14\x05\xe4\xc5\xbe\x82\xf9\x71\xfa\x4a\xb8\x60\x89\x5a\xc0\xe8\x6d\x79\x84\x0f\xab\xcc" + - "\xd2\x68\xb1\x64\xb6\x78\x0d\x65\x8f\xd4\x36\xdf\x50\x70\x0e\x3d\x8a\x21\xce\xaa\x27\x6a\x35\x2f\x57\x70\x5e\x20" + - "\x1d\x98\x63\xb7\x60\x13\xf8\x1b\x72\x48\x0f\x76\x76\xa0\x1c\xa9\x8e\x81\xee\x1c\x09\x65\xaf\x18\x31\x44\x43\xbb" + - "\xa5\x00\xe8\x3f\x59\x06\x9f\x1e\x85\x0f\x7f\x60\xc3\xa6\x1d\x5a\x00\x59\x4e\x93\x1f\xb4\x45\x9a\x54\x98\xba\x9d" + - "\x1d\x25\xdb\x7e\xaa\x64\x85\x87\xf2\x5d\x4b\xbf\x6d\xbf\x3f\x0d\xbe\x76\xc8\xb5\x76\xa8\xa0\x9f\x19\xd0\xcf\x03" + - "\x60\xfe\xec\x41\x06\x52\x04\x69\xb4\x68\x82\x04\x4d\x93\x88\x60\x3c\x8f\x98\xa0\x48\x01\x9a\x1f\xdc\x00\xa0\x8e" + - "\x5d\x55\x80\x04\x89\xcb\x8b\x57\xba\x4e\xd3\xdb\x95\x97\x7e\x2e\x44\xd2\x23\x37\x92\x68\x70\xb8\x35\x22\xcf\x66" + - "\x78\x38\x8c\xf2\x6b\xd3\x7a\xf2\x5b\x42\x1c\x68\x63\xb3\x09\xeb\x30\x0d\xce\xd7\xe0\x76\xf1\xe1\xbd\x2e\xbf\x8f" + - "\xda\xe4\xd3\x21\xc5\x60\xf5\xba\x92\x1b\x44\xa7\xc4\xd3\x75\xef\x2f\x41\xde\xe3\x8e\x7f\x7f\x66\x69\x80\x3f\x4f" + - "\xc0\x84\xf8\xfc\xf3\x70\x82\x5d\x2d\xe4\x83\xc1\x67\x2e\x52\xaf\xb5\x77\x45\x88\xc3\x06\x84\x09\x22\xe2\x6b\x4d" + - "\xe6\x58\x22\x0e\x94\x6e\x93\x8a\x5a\xaa\x5b\xd3\xee\x6e\xed\xe3\xad\xad\x9e\xcc\xf2\xd8\x53\xba\x9a\x05\x09\xe2" + - "\x02\x8e\xd3\xbe\x8c\xb8\x4a\x5d\xcd\x02\xe7\x21\x30\x1a\x05\xf6\x5c\xfb\x57\x0f\xcb\x79\x3f\x1e\xa7\x6c\x8d\xa1" + - "\x5a\x02\x47\x24\x14\x7b\x78\x47\x93\x41\x95\x32\xbd\x4c\x87\x73\x5d\x53\xbd\xe1\x57\xb0\xec\xa4\x7d\x8f\x9a\xf5" + - "\xfe\x43\xc1\xc6\xb1\xa5\x76\x76\xec\x3f\x12\x19\x80\x95\x5c\x2d\xd9\xcf\x7b\xd8\xd4\x4b\xcb\xb7\x3b\xd8\x29\x07" + - "\x46\x80\x8b\xd9\x6a\xde\x7b\x2f\xf9\x6d\xdc\xef\x39\x2d\xb9\x80\x1e\x00\x23\x86\x5d\xdb\x82\xec\xce\xf6\x6e\x91" + - "\x8c\x20\xef\x1e\x5f\x9e\x17\x9f\x8e\xe3\xb9\x95\x0a\x8e\xe5\x31\xa3\x17\xe1\x01\xbb\x95\xca\x21\x62\xac\x65\xde" + - "\xe8\x12\xf6\x69\x5a\x8b\xd2\xb5\xd4\xcc\x4d\xe1\x8b\xdb\xfd\x88\x31\xd5\xc0\x3e\x7a\x2e\x90\x07\x7c\xdb\x81\x8d" + - "\x88\x31\x6c\xdb\xc3\x90\x1c\xf0\x37\x9d\x51\x0d\x6d\x1f\x22\x3c\xc3\x42\xb2\x16\x87\x13\xa1\xf0\xe5\x09\xc4\x6b" + - "\xf3\x53\x0f\x61\x7c\x36\x56\xad\xc0\xa3\xf6\x01\x01\x6b\xa7\xa5\xea\x6e\x58\x4e\xff\x4b\x66\x09\x77\x70\xb2\x82" + - "\x7c\x31\x74\x35\x1b\x40\xdb\x03\x2a\xd2\x57\x32\x75\x85\xdc\xf5\x0e\xfe\x02\x2e\x79\x09\x81\x21\x9d\x8a\x69\xe1" + - "\x32\xcc\x49\x1f\x1e\xca\xf6\x2e\xa1\x17\xd8\xf4\xd3\xa3\xe0\x2a\x8b\x4e\x9e\x7c\xe5\x11\x3c\x83\x73\xd7\x59\xd9" + - "\x2b\x1a\x56\xbb\x2e\x78\xb3\xa1\xaa\xb6\x33\x60\x48\xc4\x6f\xdb\x0d\xe8\xbc\x97\x4d\x95\x56\xb3\xec\xd2\x14\x7e" + - "\x57\x40\x36\x19\xb7\x2d\x86\xf7\xbc\x9d\xa5\xf0\x06\x2d\x5b\x0a\xbe\x73\x96\xad\xf5\xdc\xc0\xdd\x89\x98\xa3\x5e" + - "\x22\xf2\x07\x56\x37\x08\x4a\x80\x55\x46\xa6\x77\xa7\x3b\x13\x39\x04\x0b\x6f\xe7\x73\x7b\x61\x5a\x0c\x78\x1b\xa2" + - "\xdd\x53\x6d\x6f\xf7\x1c\xcf\x21\x4e\xb0\x53\xfa\xb4\x0e\x40\x9e\x8b\x4e\xb5\xcf\x00\xa0\xaf\x74\x1d\x81\xf8\x36" + - "\x8d\xa8\x07\x63\x94\xde\x32\xe9\xdf\xf3\x45\x05\x55\xa5\xa5\x9d\x29\x80\x02\xd6\xc5\xb5\x95\xd4\xa1\x1c\x5d\xc8" + - "\xb7\xf4\x80\xf9\x4b\xc7\xcc\x48\xcf\x94\x3b\xba\xf0\xaa\x56\x59\xa3\x38\xf0\xfa\x58\xb6\xd8\x79\xf9\x72\x9c\x8b" + - "\x6d\x3a\xae\xeb\x87\xd2\x0a\x04\x3c\x9c\xac\x50\x59\xe3\x24\x0a\xdb\xc9\x06\x07\x94\x97\x81\x39\xca\x03\xf8\xd1" + - "\x30\xe2\xde\x13\x0e\x61\x4c\x1b\x6f\xe1\x56\xee\x1e\xb0\xed\x03\x0f\x17\x7f\xdf\x36\x58\xe8\x59\xeb\xc4\x80\x36" + - "\x20\xd8\x3c\x4e\xae\xa7\x23\xc4\xee\xc9\x45\xea\xc9\xa1\xe3\xcc\xed\x3d\x22\x77\xbc\x03\x80\x0b\x59\x0e\x4f\x68" + - "\x21\x7f\xc6\x36\x32\xf5\x37\x37\x8e\x75\xf4\x33\x02\x1f\x1e\xe1\xf7\x8c\xb9\x26\x5f\x9c\x86\x6d\xa0\x96\x58\x1d" + - "\x8b\x3f\x7a\x7d\x35\xc6\xef\xcf\x0e\x6f\xbf\x2a\x91\x0b\x75\x4c\x85\xb8\xaa\x63\x97\x66\xbc\xa6\xa2\x32\x9f\x4c" + - "\x96\x78\x92\xc3\xbb\x3e\x9a\xe8\xf6\xe4\x76\xee\x2f\xbb\x61\x78\xe6\x59\x8b\xde\xe6\x35\x6e\xe9\xcd\x3b\x2f\x30" + - "\x87\xfd\xc1\x5c\x77\x24\x71\x83\xce\x87\xdd\xd1\x2d\xf3\x69\xe5\xfb\xb2\xa0\x94\xff\xb0\x7e\xb7\x6d\x36\x5c\x61" + - "\xa9\x23\x0e\xb0\x4f\xed\x28\x5c\x40\x68\x87\xa3\xdb\xbd\xcf\xb6\x58\x57\x14\xd0\xd3\x55\x31\x09\x1c\x99\x56\xcb" + - "\x1c\x50\x6f\x4e\xb1\xf5\xd1\x48\x69\x28\x3a\x00\xd6\xca\x6e\x38\x53\x98\x6a\xe0\x7e\xd1\x85\x8b\x29\xb9\xfc\x61" + - "\xde\x3a\x55\x49\x65\xea\x32\xbf\x04\xdc\x8c\xb4\x2c\xec\xbf\xb1\xe2\xa7\x97\x80\xc8\x8b\x67\x38\xe9\x0f\xdc\x37" + - "\x69\xa2\x38\xb6\x01\x2a\xb2\x62\x84\xad\x67\xaa\xb3\xfc\x13\xeb\xb1\x9f\x44\xf5\x14\x65\x93\x4d\xaf\x13\xb0\x6e" + - "\x95\xb3\xca\xd4\x75\x67\x5d\x5c\x8d\x3a\x83\x2f\x39\xfe\xb5\x41\x47\xbf\x64\x69\x00\x5f\x27\xe1\x3c\x94\xe5\x22" + - "\xab\x9d\xa3\x22\x95\xeb\x5a\x48\xb7\x52\x0d\xc2\x08\x6d\xf9\x3d\xb4\x85\x69\x06\x3a\xbf\x4a\x69\xd5\x86\x76\x0e" + - "\x03\x26\x78\x68\x67\xa3\x93\x2d\xee\x70\x11\xa7\x86\x2c\x13\x2a\xd7\x7f\xf4\x50\x4d\x8b\x17\x65\x01\x66\xa9\xef" + - "\x74\x96\xdb\x7f\x7f\xa4\xd9\xf1\x28\xb6\xcc\x92\x4d\x0b\xa2\x24\xd8\x62\xd4\x1e\x4d\x25\xef\x33\x01\xf2\x51\x98" + - "\x35\x3c\xdd\x28\x32\xe1\xbe\x93\x3c\x61\x36\xc0\x87\x2d\xb1\x69\x5a\x08\xde\x4f\x78\x38\x4f\x31\x19\x09\x85\x98" + - "\xf0\x5f\x01\x5f\xc7\x73\x79\x0a\x79\xa0\xd5\x0d\xa6\x81\xbe\x51\xbc\x1d\xd4\x19\x22\x30\x94\xd5\x5a\x57\x80\x1f" + - "\xa7\x19\x1e\xb7\x74\x63\x70\x15\xfa\xda\xa0\xa3\xa7\x07\x67\xea\xac\x23\x72\x99\xfb\xed\x62\x34\x8f\xec\x10\xa0" + - "\x8b\xac\xb0\xd8\x44\x73\x1c\xa1\x75\xdf\xca\xe0\x19\x3f\x74\x7e\x3d\xe4\xdd\x18\x8b\x7a\x71\x81\x5e\x5f\xbc\xdc" + - "\xa2\xad\xc5\x03\x1c\xd2\x21\x54\x61\x21\xdc\x6d\xa2\x10\x18\x63\xc2\x32\x3c\x91\xa2\x1c\x1e\xba\x50\xba\x6c\x45" + - "\xb7\x6c\x71\x71\x9e\x4b\xf0\xae\xd9\x55\x89\xa5\xc9\x89\x3a\xc3\x29\x02\x21\x98\x87\x78\xec\x9b\x70\x83\x22\xd7" + - "\x93\x01\xf2\x84\xa7\x7e\xda\xce\xf0\xfe\xea\x98\x5e\xc1\x26\x8b\x0c\x81\xfe\x27\xee\x78\x87\xc0\x02\x2f\x7d\x83" + - "\xd1\xe9\xa2\x6c\x8c\xda\x75\xd2\xee\x26\xe8\x39\xef\x15\x57\xee\xd5\x54\x95\xe7\xbf\x58\xfe\x98\x51\xe8\x06\x94" + - "\xd5\x07\xbf\xd4\x28\x33\x67\x35\xe9\xe8\x49\x09\x22\x23\x50\xa8\xa8\x3c\xce\xb6\xca\x16\xc1\xb1\x0f\xb7\x5d\x7a" + - "\x8f\x48\xff\x5c\x9e\xff\x32\x50\x7e\xdb\x8c\xf9\x77\xa8\xe6\xc1\xf1\xf1\x20\xbc\x39\xd0\xe7\xd6\x58\x66\xcb\xce" + - "\x20\x39\xaa\x6e\x08\xef\xdd\xea\x0d\x2d\x1d\xf2\x35\x3c\xa3\xab\x65\x8f\xc2\x07\x27\xec\x55\x7e\xef\xb3\xdf\x4f" + - "\x27\xec\x59\x23\x0e\x98\xf6\xd2\x23\x77\x09\x00\xed\x25\x23\xa8\x7b\xfd\x58\x49\xa0\x4b\xea\xe1\x2d\x24\x82\x34" + - "\x00\xac\xf1\x73\x1f\x78\x2a\x20\x8a\xc8\x98\x18\x94\x2a\xfd\x25\xc9\x5a\x3d\xd7\xa5\x80\x83\x07\x9f\xab\x0e\x72" + - "\x32\x1a\x29\xbe\x8b\xec\x0e\xc7\xfb\x52\xdd\x28\xbe\xf2\xe8\xda\xf2\x37\x96\x68\x41\x46\x7c\x9d\xd2\x17\x1f\x60" + - "\xb2\x6e\xb8\x2a\xfc\xf3\x8c\x59\xe8\x43\x37\xf2\x0f\x28\x35\x95\x1c\x7a\xfa\x91\x26\x1e\xe8\xec\xdf\xd5\x81\x3a" + - "\x83\x99\xe6\x0f\xfd\xdb\x47\xfc\xc6\x7e\xdb\x61\x64\xf7\x74\x94\x09\x0f\x0f\x46\xdd\x28\x22\x1f\x67\xc1\x06\xe4" + - "\xb9\xde\x3f\x0b\x7d\x26\xdc\x24\x75\x14\xec\x24\x26\x6e\x47\x1f\xbb\x33\x30\xfe\x1d\x1c\xe0\xe1\xa6\x5e\xf9\xc6" + - "\x78\x2b\x30\x83\x49\xe0\x1d\x7e\xef\xbf\xd6\x17\x86\xa1\x03\xb1\x2f\x8e\x7c\x04\xe7\x87\x48\x8e\x2f\x26\xea\x00" + - "\x76\x18\x79\x5e\x60\xe8\x30\x3b\xda\x3d\xf6\xa3\x90\x4c\xde\x96\xfd\x83\x5c\x24\xb9\xaa\x41\x58\x69\x90\xa4\x33" + - "\xcf\xe1\x20\x6c\xdf\xf3\xee\x08\x5c\x38\xf6\x9b\xa5\x2a\xe6\x26\x5f\xc2\x2d\xb9\x8e\x78\x8d\x7a\x75\x5e\xda\x5b" + - "\xd5\xee\xca\xd1\x43\x35\x50\xc3\xe1\x70\x20\x9f\xbe\x11\x0c\x47\x98\x9a\x7f\x8b\x76\xc6\x5f\xd0\xfa\x79\xa4\x40" + - "\x2c\xa1\x61\x88\x95\x72\x78\x26\x28\x6b\x07\x5f\xb5\x93\x83\x23\x1a\xe4\xaa\x00\xa3\xfa\xaa\xb0\x44\x2b\x37\xf6" + - "\x04\x89\x3e\xd5\xd4\xfc\x42\x67\x05\x52\x0d\xaa\x1d\xdd\x0c\x31\xd3\xb4\x18\x58\xf7\x05\x2d\x4a\x04\x77\xf4\xb1" + - "\x72\xde\xb7\xfb\x51\xc7\x16\xba\x6e\x4c\xe5\xa6\x75\x68\x6f\x8c\x70\x16\x26\x65\x51\x93\x47\x00\x66\xd2\x50\x18" + - "\x75\xeb\xbe\x19\x60\x70\xdd\xaa\xc6\xb0\xf3\x61\x4c\xc4\xc5\xa8\x10\xfc\x26\x18\xc9\xb8\xc5\xcf\xc9\xf4\xe5\x7f" + - "\x5e\xa6\xb6\x90\xd3\x8a\x03\xe9\x2f\x9b\xb9\x3b\xc3\xe8\x1f\x43\x44\x13\xad\xd6\xf0\xed\x0a\x3e\xb4\x53\x13\x98" + - "\xb1\x32\xe7\xb3\x5a\x0f\xd8\xc2\xde\xd2\xf4\xb8\xd2\x68\x11\x6d\x05\x7d\x13\x03\x78\x24\x39\x5f\xb2\x98\xf3\x1b" + - "\xb7\x59\x42\x3f\xf1\x0d\xfb\x49\x8d\xb1\xa9\x40\xea\xa5\xde\x11\x33\x02\x03\xfc\x4b\xd4\x61\xc1\xb6\x23\x01\x43" + - "\xd9\xb2\x3d\xc2\x48\x3a\xa6\xbc\x2d\x6a\x6f\xcf\xaf\x4d\xbf\xb3\x5a\x9a\xe6\x3b\xeb\x25\x5a\xed\x45\x56\xbe\xb3" + - "\x44\xbf\x07\x6e\x1c\xcf\x5d\x45\x54\x3f\x3f\xf0\xb4\x46\x8a\x81\xc0\x17\xbb\x83\x2f\x4f\xcd\xa1\x6a\x2a\xa3\x1b" + - "\x0c\x76\xae\x95\xae\xdd\x4d\xe5\xa8\x52\x87\x63\x57\x34\x9d\x47\x96\xc5\x53\xa4\xd1\x0b\xd5\x75\x71\x87\x6f\x2b" + - "\x1b\x0d\xe5\xb6\xa2\x51\x2a\x4f\x30\x42\xb6\x43\x6b\x82\x63\x88\x1b\x6b\x13\x5f\x1e\x17\xec\xe4\xd0\x37\x17\xf3" + - "\x7c\x3a\xf1\xe8\xfe\xf4\xc0\x91\x89\x86\x36\x88\x28\x44\xdf\xb3\xe7\xc4\xbe\x8b\xfd\x13\xb2\xef\x82\x75\x8f\xda" + - "\x68\xef\x8d\xd6\xae\xef\x77\x1b\x0e\xc5\x2e\xde\x18\xcc\x31\x1a\x85\xc6\x92\xb5\xce\x20\x3a\xb0\x2c\xec\x15\x06" + - "\x6a\x4f\x37\x2a\x41\x17\xdd\x2e\xda\x96\x07\xe5\xb7\x80\xc2\x85\x67\xe4\xae\xa9\xea\x08\xf7\x74\x15\x05\xfc\x7e" + - "\x84\x41\xf3\x4e\x5e\xdd\xe0\xed\x50\x16\xea\xc5\xdb\xd7\x1c\x99\x8b\xa2\x9f\x4e\xaf\x7f\x40\xd5\xa8\x0c\x31\x43" + - "\xc5\xd0\x51\x97\x7e\x9b\xb8\x62\xa9\x4f\xf2\x8e\x6d\xf0\x9d\xef\x15\xed\x8d\x69\xe1\x73\x2d\x48\x4e\x65\x53\xe8" + - "\x23\x6a\x3d\x6d\x0b\xae\xbb\xf6\x3c\x53\x02\x98\x63\x75\x62\x1a\x10\x3b\xaa\x95\x41\x17\xa1\xac\x51\xe5\x64\xb2" + - "\xaa\xea\x21\xe0\x1e\xfd\x64\xbf\x18\xa3\x39\x5b\xc0\xe4\xc0\x8d\x6a\x2a\xfc\x54\x4f\x2e\xd4\xbc\x5c\xab\x85\x2e" + - "\xae\x55\xd6\x98\x05\x90\x0c\xbb\xc8\x78\x63\x98\x29\xea\xb3\xe9\xd2\xc3\x4e\x90\x95\x3d\xab\x4c\x3d\x54\x27\xc6" + - "\xa8\xfb\x5f\x7c\xf9\xd5\x01\x8c\x4b\xa7\xd7\x3f\xeb\xac\x19\xab\x03\xd7\xe2\xf7\x65\x9e\xaa\x1e\xf8\x58\xe4\x46" + - "\xd7\xa6\x1f\xd7\x74\xef\xb3\xad\x79\x99\xa7\xdc\x5d\x37\xd7\xf6\x61\x80\xe0\x27\x1f\x04\x53\x6d\x9b\xdc\xdd\xc5" + - "\x1d\x22\xb7\x78\x18\x07\x8d\xf9\x91\x79\x1f\x09\xd6\x88\x18\xff\x35\x27\x64\xb3\xd3\x9d\xd5\x2e\x74\xbb\x8a\x3b" + - "\x06\xd3\x23\x43\x84\x1c\xf8\xbe\xcf\x58\x48\x5a\x28\xe8\x33\x38\xf1\xe1\x11\x62\x65\xa3\x0b\x0b\x87\x81\x41\x85" + - "\x02\xbb\x74\x6f\x2f\x1e\x9d\xbf\xed\x69\x5d\xa3\x48\x9e\x88\x2d\xfc\xc9\x20\x06\x15\xba\x1c\x76\x8c\x69\x2b\xaa" + - "\xcd\x79\x80\x50\x05\xaf\xa6\x4a\xab\xa2\xac\x16\x3a\x87\x4f\x7f\x8a\x16\x1e\x78\xd2\x49\x45\x89\xea\xc0\xd5\xce" + - "\xf6\x92\x1c\x75\xc0\x81\x50\x8e\x6d\x9b\xc7\xb6\xb3\xd3\x35\x38\x99\x35\xad\x73\x3c\xaf\xe4\xd4\xfa\xa4\x48\xe7" + - "\xe5\xaa\xb0\x72\x79\xc9\xa8\xf2\x48\x1c\xe8\x30\x87\xf4\xc5\x01\xa8\xa8\x53\x8e\x2d\x3a\x93\x3c\xfa\xbb\x2a\x9b" + - "\xcd\x00\xd7\xf3\x1a\xeb\x95\x5b\xd4\x63\x16\x79\xe2\xd0\xe0\x07\xb8\x79\xaa\x68\x5f\xca\x10\xee\xa8\x64\x4f\x25" + - "\x50\x73\xc2\x64\xb9\xe3\x8b\x72\x3a\x8d\x8b\x7d\x0c\x48\x1b\x67\xfd\x79\x17\x1d\xca\x39\xf5\x06\xb3\xa6\xe4\x53" + - "\x35\xc9\x8d\x2e\x56\x4b\x12\xd8\xc9\xc1\xcf\xbb\xf4\x32\x4b\x4d\xa2\x99\xc3\x0e\x41\x0b\xf2\x4b\x5b\xe7\x0f\xc4" + - "\x4c\xf4\x54\xf2\xe2\xed\xeb\xe7\xe8\x6c\xff\x43\xa9\x53\x93\x26\x03\x5f\x03\xa1\xbb\x61\x6f\x11\xe4\x76\x43\x2d" + - "\x79\xa9\x37\x7f\x19\x1c\xd9\x18\xa8\x32\xa0\xab\xa1\x57\xa2\x53\xac\xf0\xad\x43\x9b\xc0\x9f\x53\xff\xe8\xa8\xcd" + - "\x39\x4b\x59\xad\x99\xcc\xd5\x44\xd7\x06\x1c\x26\x2b\xa3\xfe\xe0\xd1\xc7\xb8\x5f\xe0\x73\x47\xa6\x02\xe7\x3d\x7a" + - "\x5e\x95\xeb\xda\x54\x6e\x25\xbc\x33\x1f\x50\xe5\x8a\x4c\xa6\xe8\x5c\x00\x04\xbb\xa9\x32\x54\x1d\x59\x11\x00\x8a" + - "\x9e\x80\x4e\x00\xe1\xd1\xf5\xa4\xc9\x2e\x4d\xa2\x6c\x27\x10\xd0\x3d\x6b\x14\xe0\x0f\xa6\x2a\xab\x6b\x7b\x2b\x82" + - "\x97\x29\xe8\x9d\x0a\x43\x75\xa7\x59\x3d\x29\x2f\x4d\x85\x0e\x74\xcf\xe7\x55\x56\x9f\x40\x15\x63\x46\x58\x3f\x5f" + - "\xcd\x6a\x0a\x96\x03\x78\xf5\x26\x9b\x5c\x98\x66\x74\xf0\xe8\xd1\x57\x8f\xee\x4f\xca\x85\x1d\xe9\xf8\xe0\x73\xb7" + - "\xe5\xc5\xa6\x70\x3d\x04\x77\x17\x5e\xc1\x44\x7a\xfe\x13\x31\xcd\x1a\xa5\xeb\xeb\x62\x32\xaf\xca\xa2\x5c\xd5\x98" + - "\xf4\x55\x03\xde\x3d\x43\x37\x41\xbf\x01\xc4\x7a\x55\x64\x0d\x14\x48\x4d\xae\x05\x71\xdc\xaa\x4d\xf3\x2e\x5b\x98" + - "\x72\xd5\xb8\x93\x87\x33\xca\x0b\xe6\xc9\xbd\x13\x7c\x6a\x9c\x11\x7b\x12\xae\x23\x2f\x67\x64\x3f\x78\x38\x3a\x4d" + - "\xff\xd5\x0d\xce\x8d\x3d\xb3\xcf\x9c\x47\x25\xed\xfa\xb2\xb0\x3b\x7c\x20\xdc\xbd\x29\x4b\xf1\xba\xac\xb0\x0b\x54" + - "\xb0\xa3\x03\xb7\x9e\x0d\xa6\x01\x1e\xb0\x91\x29\x9d\xd3\x3e\xc0\x39\x90\xa9\x21\xfe\x94\x81\xbf\xe3\x34\xe2\x23" + - "\x28\x75\xdc\xa5\x29\xd8\x2a\xb6\xb2\x5b\x37\x2d\x4d\x8d\xa8\xc6\xdd\x9c\x8c\x8b\x55\x80\xba\x5f\xaf\xf2\x26\xf3" + - "\x00\xc9\x44\x63\x38\x7b\x24\x27\x6e\x22\x91\xa7\x9c\x06\x2e\x64\x8e\x37\x83\xd7\xa3\x1a\xdd\x9e\x97\x0e\xa8\xeb" + - "\xdc\x30\x4d\x07\x2f\xe1\xac\x79\x50\x8b\x2c\x79\xc8\xb6\x69\x48\xee\xe8\x8f\xb3\xfb\x3b\x8c\x19\xa2\xa0\x9b\x0b" + - "\x73\x4d\xf2\xd7\x40\x4d\xe6\x3a\x2b\x50\x0b\x06\x7e\x02\x7f\x34\xcd\x40\x55\x7a\x2d\x82\x19\xbc\x72\xa3\x9d\x50" + - "\x19\x53\x72\xaf\xf2\x0b\x75\x64\xab\x15\xa8\xe7\x84\x0c\x68\x9a\x1a\x59\x2a\x27\x58\xcb\xcb\x03\x5d\xc9\xec\x87" + - "\x04\x04\x8f\x5a\x63\x77\x8c\x5c\xef\xa4\x63\x26\x23\x9b\x66\x05\x7d\x19\xb0\x38\x38\xf4\x60\xbc\x19\x0c\xf9\x34" + - "\x23\x4c\xcc\xd6\x48\xc5\x15\xcb\x5d\x2e\x0b\x5a\x0f\xbb\xcf\x84\xc4\x8b\xe2\x7c\x27\x98\x4b\x47\x5f\x3d\xef\xdf" + - "\x21\x72\xb1\x66\xc0\x5d\xf7\x7a\x2d\x47\x29\xc3\x8b\x60\x82\x05\x65\xf9\xd6\xfe\x2d\xd2\x8e\x55\xab\x22\xc8\xed" + - "\x61\x8a\x26\xab\x8c\x83\xd8\x44\x51\xd0\xad\x29\xd8\x0a\x04\xde\x35\x0b\xe3\x4e\x38\x02\xbb\x95\x5f\x46\x86\x04" + - "\x33\x57\x13\xb3\x24\x6c\x14\xdc\x91\x41\xc6\x1a\xa1\x39\x09\xa5\x2b\xda\x1e\xd3\x42\x56\x1f\xc7\xfb\xf9\x3d\xd9" + - "\x36\x0b\xd8\x0a\x36\x04\x66\x87\x1d\xff\xd8\x0e\x4c\x42\xb5\x62\x11\x61\x20\x6c\x02\xe6\x9d\xf2\x41\x81\xcd\x02" + - "\x7d\xb2\xf3\x76\x4c\xed\x90\x8e\x45\xce\x1d\x14\xcc\xec\x3e\x8b\xbe\x84\x95\x8d\x71\x49\x02\xac\x67\xbf\x61\xc0" + - "\x8d\x03\xb3\xb0\x8f\xdd\xf5\xfb\x47\x83\xcc\x16\x4c\x1f\x3a\x7a\x84\xcb\xe6\xb0\x1f\xec\xb1\x3c\x16\x3d\xd8\x77" + - "\x3d\x18\xbb\xad\x2e\x2c\xee\xcc\x31\x39\xfc\x80\xda\xf9\x3a\x69\x0e\xa4\x01\x22\x04\x4e\x01\xa9\x6e\x74\x18\x0d" + - "\x61\x4f\xd8\xb2\x79\xa1\x1b\x1d\x32\x1e\xeb\xc2\x31\x7f\xe0\x62\x6b\x4b\xd5\xa0\xf0\x1b\xe3\x23\xb5\x07\x09\xc6" + - "\xe9\x0f\xfe\x73\xf8\xf2\x87\x97\xaf\x5f\xbe\x79\xf7\xe1\xcd\xdb\x17\x2f\xe3\x77\x2f\xde\x3e\xff\x73\xfc\x72\x8f" + - "\xa2\x27\x44\xd9\x67\xa0\x43\xee\x04\x7b\x67\xd3\x92\xed\x5d\x8c\x0d\x71\x73\xd3\xf5\xfc\x6b\xf0\x48\xed\xa9\xdd" + - "\xe8\x5d\x5f\xcc\xa1\xdb\xf5\x76\x1a\x7a\x6e\xd0\x2e\x15\xc5\xb3\x22\xad\xca\x2c\x55\x4f\xd5\x13\x42\x1f\x7a\x9b" + - "\xa7\xea\x67\x73\xfe\xa7\xac\x71\x77\x0b\x4e\x30\x45\x9e\x93\xcb\xf6\x4b\x2b\xf5\xd6\xf6\x54\x8f\xa6\x95\x31\xbf" + - "\x1a\xba\x4b\xa8\x16\x1a\x4d\x61\xd6\x9c\x54\x0b\x97\xcb\x1e\x7d\xa3\x09\x94\xb3\x28\xd5\xe9\x69\x6d\x9a\xb3\x33" + - "\xba\x18\x00\x0f\x81\xda\x41\xaa\x45\x30\x84\x64\xd1\x1d\x4e\x5c\xec\xdc\x40\xed\x0f\xf0\x34\xcc\x4c\xd3\x61\xe6" + - "\xa7\x0e\x60\xf4\x9a\x4f\xf3\x70\xef\x33\x0c\xae\xe7\xb4\xa6\x32\x93\x01\x3c\xd8\x0d\x33\xf5\x33\x3b\x6b\xa7\x6f" + - "\xb8\xca\x52\xc2\x1a\x83\x3f\x35\xed\x9c\xe0\x36\xc3\x0d\x77\xe8\xbe\x91\x38\x53\xb6\x67\x17\x26\x10\x4c\xe5\x66" + - "\x04\x9f\x57\x4c\x33\x86\x35\x61\x24\x02\x07\xa9\x30\x8a\x02\xc2\xf7\x65\x85\x5a\x94\xa9\xb1\x54\x07\x99\xd8\x9a" + - "\x7d\xc6\x2d\xdb\xe9\x7d\x61\x8b\xb2\x81\x04\x61\xea\xfe\x57\x8f\x1f\x7f\x3e\x74\x46\x08\x60\x6f\x9c\x56\xc3\xc0" + - "\x39\x44\xc0\xe2\x69\x55\xfe\x6a\xf8\x7c\x0d\xfd\xd5\x20\xc7\xec\x3b\x1e\xcd\xf7\xbe\xbc\x13\xec\xa5\x9c\x1a\x64" + - "\x1e\x21\x04\xf6\xb7\x0e\x37\x48\xe0\x29\xa1\x32\xda\x22\xcc\x82\x03\x3b\x4e\x31\x45\x17\x06\xb9\xcb\x55\x01\x16" + - "\xaf\x23\xfc\xe2\x54\x05\x6b\x79\x16\x08\xc3\x30\x70\x0c\x1d\x62\x5e\x1b\xc7\x41\x75\x70\xc7\x5d\x95\xbc\xc4\xa0" + - "\x96\xe0\x6e\x9e\x98\xc9\xaa\x02\xde\x38\x2b\x40\xbe\x2e\xf6\x4c\xb1\x5a\x98\x0a\x59\x11\xfb\xf7\xba\xca\x30\x0c" + - "\x85\x73\x25\xc1\xb7\x4d\x75\xed\x4d\x67\x3c\x05\x71\x87\xed\x94\x20\xa9\x1e\x2b\xea\x07\x5d\x0d\x9d\xa7\x20\x33" + - "\x3c\xf1\x03\x39\xaf\x92\xbd\xed\x3a\xd8\xfc\xee\x3b\xc1\xf8\x6a\x45\xd9\xb8\x61\x78\xd0\x4a\xd6\x50\x5e\xdb\xad" + - "\x8f\x84\x26\xd9\x53\xe2\x92\xbb\x75\x14\xd8\x79\xea\x7a\x6c\x0f\xef\xec\x70\x5b\x69\xf9\x52\x06\x1d\x4e\x02\xcb" + - "\x3c\x2e\x9c\xa7\x00\xa7\x3c\x5b\x67\x11\x6c\x60\xf4\xf2\x48\x9c\x7f\xa1\x85\xf4\xbd\xc5\xb0\xfb\x80\x80\xb8\xfe" + - "\xea\x46\x47\x37\x3d\x40\x57\x54\xe5\xd2\xbb\xa9\x81\xb4\xb9\xd0\x18\xf9\xc7\x15\x53\x4e\x37\x76\x31\x00\x68\xbe" + - "\xd4\xb8\x8f\xa2\xdc\xab\xa6\xb0\x5b\xc5\xb9\x35\x24\xd0\x7c\x22\xb7\xae\xca\x8a\x3c\xc3\x1d\x0c\xe6\x02\x91\x5e" + - "\xd5\x35\xa8\x9a\x79\xb9\x9a\xcd\xe1\x62\x84\xc3\x84\xd5\xce\x75\xca\xa2\x8c\xb9\xb2\x32\x4b\x1a\xee\x79\x98\xb5" + - "\x0b\x73\xed\xce\x33\xf6\x92\xc9\x6c\xd7\xa4\x1e\x46\x40\xd1\x63\x75\xca\x53\x26\x78\xa3\x33\xf0\x43\xbc\x17\xa1" + - "\xdb\x00\x3d\xeb\x8c\x6a\xa7\x46\xa0\x80\x5d\x37\xb6\x11\x6d\x6a\xea\x37\x3e\x6d\x99\xa9\xd5\x47\xd1\x5c\xc0\xd2" + - "\xd9\x4d\x5f\x99\x7a\x2e\xb3\xec\x59\x19\x9b\x29\x8d\xe5\x3d\xe7\x28\xe2\x4e\xca\x65\x66\x04\xb6\xb2\x63\x84\x5f" + - "\xda\xeb\xcb\x01\xea\xc2\xc4\xf4\x5b\x71\xef\xbc\xd7\xbb\x26\x6c\x40\x01\x65\x87\xdc\xa5\xb7\x0c\x57\x6b\xa5\xc6" + - "\xe5\x35\x3b\xa9\x38\xb8\xdd\xc2\xec\x9d\x5f\xef\xd9\x85\xe7\xfc\x7a\xd1\x71\x88\xf8\x56\x64\x15\x6d\x0d\x96\x48" + - "\x05\xd1\x6b\x6e\x62\xe1\xad\x9d\x58\x0c\xdf\xc2\x3f\x3b\x4d\x08\x5b\x41\xd6\x6a\x77\x48\x66\x9d\x87\x44\xc8\x35" + - "\xf6\x04\x67\xc8\x9c\xd9\xd5\xcb\x52\xea\x76\x56\xab\x29\x2a\xfd\xca\x0a\x65\xeb\x73\x43\x9b\xdb\x69\x57\xde\x98" + - "\x35\x96\xae\xe3\x12\x98\x78\xdb\xef\x74\xf6\x3f\xe2\xcb\x4e\x73\xc8\x37\x22\xcc\xb2\x80\x49\x13\x57\x98\x75\x7e" + - "\xcd\x55\xd1\x17\xc8\x8e\xc0\x2c\xd1\x15\xa7\x9e\x51\x87\x83\x6b\x08\xa0\xe0\xcf\x8d\x73\x26\x1a\x32\x05\xe8\x3a" + - "\x1c\xad\x73\xe4\xce\x09\x4d\x26\xca\x9c\x52\x1a\x3b\x16\x27\x6d\xac\xa8\x1e\x5b\xec\xcc\xcd\x39\x0e\xa6\x7b\xda" + - "\x3b\x48\x13\xc0\x00\xa0\x3f\x2b\xc4\x08\x05\x2a\x31\x03\x6b\x33\xc6\x97\x54\x44\xa9\x83\xa1\x7a\x53\x42\xab\x6b" + - "\x2d\xa0\xc6\xdd\xfb\x47\x76\x72\xf0\xac\xb6\x4b\xa1\x86\xab\x28\xa9\x27\x22\xf7\xa7\x6f\xe2\x1d\xfb\x62\x80\x6a" + - "\x34\x51\x4b\xdd\xcc\xd1\x4d\x1b\x4e\x1d\x78\x16\x9b\x46\xe8\x21\x52\x66\xf6\x59\xf1\x06\xa8\xb6\xd8\x42\x53\xd2" + - "\xfa\x83\xa9\x69\x69\x40\xdb\x96\x5f\x6f\x1e\xdb\x3b\x2f\x63\xc6\x67\x88\x87\x07\xc6\x26\xbb\x19\x70\xf6\x14\x29" + - "\xdf\x89\xe1\xc0\xea\x80\x20\xb4\x57\xf0\xe6\x06\xcf\x4f\xaf\x67\xdf\x79\xfc\x0e\x2e\xc9\x44\x8e\x13\x93\xad\x4c" + - "\x58\x81\x04\x6f\xa3\xd6\x8f\x3c\x08\x55\x70\xc4\xf8\x86\x77\x0e\xaf\x50\x7a\xbb\x63\x43\x71\x4d\xe3\x76\x4d\x8c" + - "\x5f\xa8\x17\x26\x87\xfc\x6a\x17\xe6\xba\xdf\xf2\x4f\x39\x7d\x78\xf6\x33\x9b\x55\x6c\xdb\x84\x2c\xab\x69\x1b\xc0" + - "\x31\x06\xb7\x04\x0d\xaf\xed\x5a\xb2\x02\x02\x0e\xa4\xa5\xa9\x7e\x87\x00\x7c\x5b\xa5\x90\x3e\xaa\x1e\x5c\x42\x60" + - "\x8c\x84\x85\xa8\xfb\x28\x08\x6c\x5c\xc0\x67\x4e\xce\x03\xb8\x00\xa6\x91\xe1\xfe\xec\xe8\x86\xfd\x2f\x61\xd6\x36" + - "\x9d\xa7\x46\xe4\xf9\xcf\x40\xaf\x6b\xb7\x68\x6d\x1a\xda\xa1\x4e\xaa\x6c\xd6\xa5\xc3\x36\xa7\x3b\x75\x59\x66\x64" + - "\x5e\xf0\x72\x0e\x28\x33\xae\x96\xe8\x2d\x06\xdb\xe9\x5c\x93\xe1\x12\x37\x30\xd4\x6a\x4f\x4f\xa3\x2f\x4c\x71\xfa" + - "\xf0\x4c\xd0\x86\x2e\x5d\x8d\x97\xe4\x2f\xcc\xb5\x23\x08\xad\x28\xb1\x0e\x3a\x4c\x19\xec\x11\x18\x07\xd6\x7a\xf0" + - "\x9f\xba\xf3\x37\x9c\x83\x4f\x61\xc1\xba\xae\x66\xe2\x55\x15\xe4\x20\xb0\xbb\x04\x50\x38\x94\x47\xe1\x20\xc2\x83" + - "\x47\xaa\xee\xb8\x9b\xc9\xe3\x80\xb5\x18\x74\xe7\x21\xff\x9f\xd8\x19\x48\x28\xc7\x3c\x35\x81\x15\x0d\x87\x43\x57" + - "\x10\xb6\x3a\x2c\x18\x44\x5f\x01\xec\xaf\xbf\x32\x06\x90\x50\xa4\x97\x5c\x18\xf0\x71\xbf\xd4\x79\xd2\x57\x96\x93" + - "\xd0\xcd\xaa\x32\xde\x45\xd5\xd6\xea\x6f\x2e\xc4\x56\x40\xf6\xcf\x1d\x36\xdf\xa4\xdb\x70\x8e\x05\xa4\xfc\x27\x8d" + - "\xc9\x73\xf5\x61\x5e\xae\x3f\xd0\xd9\x02\x74\x81\x14\x1c\x59\x71\xe5\x5d\x1d\x70\x00\x97\xb9\x26\xd5\x22\xa2\x80" + - "\x50\x4b\xf6\xc9\x50\xdd\x3f\x78\xf4\xe5\x57\x5f\xb8\x0f\xde\x59\xde\x12\x7a\x08\x8e\x4d\x4b\x53\x20\xbc\xb1\xdd" + - "\xb8\x38\x39\x2e\xc0\xcc\x6e\x55\xea\x2d\x00\xec\x80\xc2\x74\x38\x29\x8b\x89\x6e\x60\xae\x11\x1b\x29\xa6\x26\x42" + - "\x8b\x14\x70\x27\x50\xc0\xcb\xc8\x9e\xfa\x38\xca\xc6\x5d\xac\x90\x15\xa2\x55\x07\xe9\xcf\x16\x41\x8b\x36\x58\xf9" + - "\x16\xba\xc8\x96\xab\x5c\x3b\x49\xc5\x6f\x49\x07\x3f\xe1\x59\x1f\xea\xfd\x29\x1e\x7c\xec\xc7\x86\x80\x6c\xb6\x9f" + - "\xc2\xac\x73\xc8\x0b\x6c\x47\x62\x9c\xeb\x01\x58\x7c\x32\x72\xf9\x6a\xf1\x71\x84\x4d\xc3\x3b\xed\xfc\xda\x65\x98" + - "\x47\x19\x71\x9e\x35\x06\xea\x0b\xfb\x06\x9d\x3a\x0c\x9f\xc1\x3f\x6e\x38\x1c\x48\xbb\xe5\x30\x97\xc6\x8c\x3d\xb5" + - "\x09\x7e\x47\xb5\x22\xca\xf1\xe8\x50\xdd\x41\xa0\x6d\x57\xd2\xfa\xad\xd4\xe4\xa6\x31\xcc\x93\xd8\x6f\xd0\x25\xe7" + - "\x2c\xd6\x12\x0e\x10\xc9\xd7\x4a\xce\x1b\x95\x1a\x1c\x6d\xd3\xc9\x50\xb7\xe8\x46\xa7\x5c\x8f\x30\x20\x80\x3e\xe8" + - "\x11\x17\xb7\xd2\xac\x9e\xe8\x2a\xdd\xd8\x30\x6c\x8d\xee\xfa\xbc\x5f\x0b\x0c\xf4\x13\x3a\x10\x18\x74\x09\x1a\xca" + - "\x92\x8d\x0f\xcb\x2a\xbb\x24\xff\x27\x54\xb1\xb9\xdc\x97\xf0\x1a\x6c\x34\xad\xd7\x8c\x6a\xb4\xe5\x72\x58\x62\x22" + - "\xf4\x93\xd5\x62\xa1\xab\x6b\x58\xb0\x83\xa1\x7a\x59\x4c\xcb\x6a\x62\xd4\xb3\x1f\x5f\xa9\x7a\x55\x4d\x2d\x75\x44" + - "\xe9\x6f\xa1\x8b\x26\x9b\x60\xe2\xed\x26\xc3\x4c\xe1\xb8\x71\x0f\x86\x5f\x0f\xaf\xd4\x79\xa5\x8b\xc9\xfc\xde\x67" + - "\x5b\x8f\x86\xea\xd5\xc2\x72\x66\xe4\xea\x53\xa6\xab\xdc\x3c\xa8\xd5\x42\x67\x80\x62\x4c\x59\xc6\x11\xb9\x23\x5d" + - "\x4d\x18\x4b\xc9\x72\x11\x7a\x86\xfe\xb2\xba\x99\xd7\xa8\x33\x20\x6f\xc8\x85\x99\xcc\x75\x91\xd5\x0b\x7b\x18\x1e" + - "\x0f\x9d\x01\xaf\xb6\x1b\x34\x2e\x63\xbf\xa4\xdc\xc2\x2a\x59\x02\xb0\x97\x49\x60\x18\x89\x9d\x9c\x04\xe6\xc9\x56" + - "\xf4\x64\xa8\x3e\xbc\x31\x97\xa6\xfa\x60\xaf\xd2\xb2\x36\xa2\x38\x50\x68\xb4\xba\x56\x6a\x52\xa6\x46\xf5\xde\xbd" + - "\x7d\xf1\x76\xac\x5e\x58\x41\xe6\x03\xca\xea\x1f\x90\x48\xda\x79\xee\xdf\xfb\x6c\xeb\xf3\xa1\x7a\x06\x89\xa1\xa0" + - "\x36\x08\x3b\x0e\x67\x3b\x35\x8d\xce\x72\x2b\x70\x61\xbd\xc4\x93\xa8\x9e\x99\x0d\x39\x5f\xba\x60\x3a\x6c\x9d\x5f" + - "\x0c\x5d\x52\x7b\x0d\x86\xfa\x0a\x6f\x76\x2b\x82\x45\xb5\xaf\x96\xb3\x4a\x63\x6e\x8e\x9f\x8d\xbe\x78\xad\x41\x3a" + - "\x7b\xb4\x7f\xf0\xe4\xde\x67\x0f\x47\xe4\xc5\x74\x5e\xd9\x35\xe5\xac\x52\xbf\x61\x4a\xa9\x87\xef\x3f\xde\xbc\x3f" + - "\xe5\xdf\x67\x98\x4f\x6a\xab\x02\x4c\xa7\x17\xba\x9e\xdb\xf2\xbd\xd3\x67\x7b\xff\xff\xb3\xfe\x68\x16\x42\x7d\xda" + - "\x89\x78\x06\x29\x4d\x84\xb5\x42\x48\x84\xb6\x51\x7b\x9e\x9d\xdd\x0b\x15\x65\x40\xa7\xec\x6d\x03\x92\x9a\x00\x97" + - "\x19\x28\xcb\xf1\xb8\x8c\xc4\xe8\x02\x3d\x1a\x91\x62\x92\x23\x78\xbf\x7f\xf7\xfa\x87\xcf\xe1\xd9\xde\x43\x9f\x7b" + - "\x85\x4d\x68\x4e\xe8\xf7\x1c\xc3\x86\x54\x91\x74\x2c\x89\x0e\x26\x50\x61\xa2\x76\xe1\xce\xa9\x0c\xa4\xb1\xee\x29" + - "\x3f\x0f\x03\x95\xec\xfd\xe1\x20\x51\xfd\x30\x69\x30\x1c\x55\x6c\x74\x53\xda\xed\x10\xc8\xef\x4e\xe5\x84\xd4\xe5" + - "\x61\xbd\xbe\x6c\x53\xad\x20\x4f\x37\xf8\xca\x70\xba\x62\xff\x1a\x6c\xc1\xf6\x3d\x1a\x85\xdb\x05\x8a\x55\x9e\xdb" + - "\xf7\x10\x4b\x32\x16\x97\x8b\xbd\xa6\x89\x95\xc0\xc3\x57\xac\xc0\x3f\x08\x4c\xab\xa0\x9a\x2f\x1e\x34\x0c\x4b\xe6" + - "\xef\x4d\xaa\x61\x17\x5a\xd8\x55\x49\x82\x5e\xf9\xf6\xaf\x63\x85\x4f\xb9\x15\xdc\x7d\x84\xa5\x47\x9b\xe4\x38\xc8" + - "\x90\xf4\x7f\x4e\xde\xbe\x71\xaf\x64\xdf\x0f\xa5\x9e\x90\xd4\x84\x41\x66\x2b\xce\x65\xb5\x36\x4e\x57\x85\x52\x56" + - "\x09\xba\x54\xd1\xf7\x14\x93\x34\x20\x3d\x66\x92\x89\x7c\x7b\x6b\x0f\xb7\xfd\xc5\x68\x3d\xc2\x48\xe6\xc8\xe8\x4e" + - "\x1d\xfe\xd8\xed\xb3\xd7\x71\x7f\x75\xc0\x56\xfa\x9e\x51\x79\x57\xea\xe6\xc6\x5f\x04\xf1\x4b\xe1\xcf\x9f\x76\xb4" + - "\xc1\x5c\xba\x54\xd9\xb4\xda\x93\x76\xe2\xf0\x03\x51\xbb\xa7\x7c\xdd\x6d\x70\xed\xbe\x5a\xfc\x22\x2c\x13\x86\x1f" + - "\x20\x81\x7d\x03\x52\xba\x6e\x5c\x00\x36\x5c\x05\x40\x71\x81\x88\x0b\xa2\x8b\x12\x13\x04\xe5\xd2\x69\x25\x90\x30" + - "\xb8\x98\x48\x41\xe3\xaa\xf0\xb7\x27\x45\x26\x41\xb4\x56\x6d\x08\xce\x4e\xa5\x66\x59\x99\x09\x6b\x89\x3e\xfc\x2b" + - "\xf3\x07\x4b\xf2\x49\xf3\xf7\xe1\x77\x4d\x20\xd4\xbb\x71\x02\x6f\x4f\x7c\x10\x8f\xa3\x5b\x95\x93\xc9\x9e\xa2\x9c" + - "\x41\xb9\x2e\x1c\xc2\x37\x3e\xb5\xd4\xb6\x26\x42\xe7\xc8\xaa\x4f\x7f\x75\x18\x58\x69\x61\x0d\xbd\xf9\xfb\x0e\x71" + - "\xae\x05\x18\xda\xef\x20\x82\xb8\x99\x66\x7c\x5a\x45\xa2\xaa\x8d\x89\x36\x76\x76\xd4\xb6\x9f\xc6\x99\x3f\xe8\x09" + - "\x9d\x1e\x4b\xac\xeb\x24\xf0\xe7\xb6\xbc\x2b\x0c\x35\x42\x89\x69\xb1\xaf\xcc\x2d\x87\xe9\xf6\x0f\x0e\x76\xc5\x8b" + - "\x77\x56\xe6\x81\x79\x73\xf8\xfc\xb4\xe7\x80\x08\xf7\xee\x1f\x3c\xf9\xea\xeb\x27\xce\x8f\x1b\x81\x7a\x6c\x79\x0e" + - "\x86\xf5\x61\x96\x74\x55\xf9\xb7\x43\xba\x5d\xb7\xc4\xb7\xc0\x74\x13\x94\x7a\xcf\x5d\x6b\xe8\x48\xb2\x1f\x86\x95" + - "\x52\x7d\x6d\x59\x49\x80\xcd\x7e\xde\x0f\xc2\x2d\xe3\x2b\xdf\xef\x1b\x8f\xd2\xda\x05\x04\x44\x3f\x3e\x0a\xaa\x8e" + - "\x2b\x52\x6f\x5a\x91\x81\xf4\xc7\x8d\xa5\x8b\x90\xd6\x4a\x85\x12\xba\xd6\x30\x20\x65\xb4\xfd\x62\x95\x59\xe4\x57" + - "\x13\xe0\xb5\x42\xbc\x62\x47\x64\x5a\x78\x69\x60\xac\x99\x90\x2d\x3f\x76\x39\xa2\x33\x55\xa0\xe0\xd6\x0d\x61\x30" + - "\xcc\xc6\x0f\x84\x28\xfb\x27\x73\x7d\xab\x34\x7b\xcf\xdb\x86\x18\xc7\x31\x44\xc6\xc7\xb4\x35\x56\xd2\xa6\xe4\x0e" + - "\x7d\xd6\xb1\x81\x6a\x9a\xbf\xef\x91\xe6\xbb\x42\xf1\x17\xac\xa1\x3e\x5d\x82\x5e\x2e\x8d\xae\x6a\x54\x57\x12\x45" + - "\xe8\xb3\xb2\x9c\xab\xf8\x07\x8c\xe6\x1f\x1e\x0e\x15\x78\x3c\xdb\x92\x3b\xed\xa0\x62\x43\x95\x78\x3b\x23\x1b\x90" + - "\xee\x3c\x57\x95\xa9\x57\x39\x58\x40\xff\xe1\x3e\xfc\x07\xf0\xbc\x31\x51\x22\x6d\x97\xfd\x8a\x6b\x80\x74\x8d\xd0" + - "\x75\x70\xcb\xb1\x5c\x2a\x04\xd3\xd9\x43\x63\x1b\x46\xad\xae\x4e\x95\x46\xb2\xec\xac\x06\x0b\x9d\x92\xd6\x24\xc8" + - "\x3d\xd7\xa1\x48\x0d\x54\x3f\xcf\x7c\xb5\x33\xd3\x44\x9c\x2a\x01\xe4\x6e\xf1\xe0\x48\xd2\x07\x1d\x4a\xbd\x97\xd5" + - "\x77\xd1\xb7\x60\x63\x09\xf6\xb6\x3b\x6b\x56\xfb\x54\x88\xa4\x75\xff\x46\x57\x61\xd7\x65\xbf\x72\xec\xf3\x6d\xdd" + - "\x75\x5b\xf6\x7f\xa0\xcf\x09\x3b\xae\x26\x9e\xbf\xcb\x0a\x57\x12\xa5\x82\xc9\xaa\x6e\xca\x85\x14\x0e\xda\x93\x2c" + - "\xc9\x17\x77\x78\x20\xfb\xf6\x1f\xea\xfb\xcf\xec\xbf\x5b\x19\xd0\xf2\xcd\x75\x45\x46\x0c\xd7\x7f\xe6\xab\x41\xe9" + - "\x43\xba\x1e\xe1\xdf\x2e\x83\x6c\x4f\x04\x5f\xcb\x2a\xc5\xdb\xe8\x94\x47\xce\x13\x3b\x1f\xa1\x9b\x35\x1a\x02\x21" + - "\xe2\x82\x53\x2a\x97\x2e\xe2\x74\xcb\x49\x5c\xc0\x88\x2d\xb2\xd9\xbc\x79\xc0\x9c\x16\x56\x00\xdb\x43\x7b\x1d\x60" + - "\x0a\x32\x13\x7e\xcc\x44\xac\xbd\x45\x90\xf8\x05\x5b\xc4\x77\x95\xd2\x30\xb7\xe5\x3a\x14\x0f\xcb\x25\x20\x00\xa2" + - "\x92\xbc\x74\x9f\x61\x77\xd8\x13\x02\x2e\x20\x02\x91\x49\x75\x3d\x47\xbf\x15\xd1\x4f\x40\xc9\x1e\x86\x5a\x4a\x18" + - "\x1f\xda\x1c\x96\x4b\xe7\x85\x2c\x04\xf1\xe1\x70\xf8\xf0\x16\xd2\xef\x77\x50\xa8\xeb\x87\x16\x1e\x0e\x87\x43\xf5" + - "\xaa\xa0\x13\x56\x9b\xd0\xae\x20\x26\x58\x7d\xd0\x80\xbd\x98\x5f\x7f\x70\x1f\x93\x9f\x99\x1d\xc7\x20\x80\xc8\xcb" + - "\xeb\x78\x25\xa7\x50\x95\xfb\x72\x55\xb0\xb0\xc3\x53\x33\x0c\xf5\x97\x8e\x3f\x48\xf6\x12\x44\x92\xdf\x3b\x60\x8c" + - "\xd1\x8d\xbb\x7d\xd3\xcd\xd7\x72\x37\x0c\xee\xc1\x01\x25\x36\x26\xc7\xda\xae\xf0\x4d\x2e\xe2\xef\xfb\x5b\xe5\x0c" + - "\x61\x7d\xb8\xfb\xbe\x6e\x8b\x20\xf1\x8d\xfd\xb1\x15\x14\xd6\x96\xda\xfe\xb9\x32\x2b\xd3\x66\xd5\x2d\x3b\x11\xca" + - "\x03\x76\xf7\x43\x61\x29\xf1\x07\x39\x7f\xc8\x39\x8b\x50\x21\x6f\x6e\x54\x32\xbd\xb2\x0c\xc8\xae\x4a\xe0\xc3\x04" + - "\x67\x11\x7e\xf3\x19\x8a\x59\xd7\x86\xfd\xee\x1c\x71\x58\xda\xbd\xb1\x5a\xaa\xd4\xe0\x87\xe7\xd7\x96\xc6\xa3\xed" + - "\x6b\xd5\x28\x48\x13\x8d\x09\x1c\x39\x53\x3d\x44\x16\x6b\x95\x97\xe5\xc5\x6a\xe9\xef\xbd\xd0\x9e\x8f\x9e\x30\x58" + - "\xa5\xcf\x9a\xe0\x2c\x21\x54\xd8\x6f\x91\x76\xaf\x43\x79\x08\x27\xac\x95\x85\xd1\x16\xdf\x18\x84\x08\x75\x12\x22" + - "\x95\x74\x6d\x08\xb0\x59\x69\x23\xb8\x9e\x9e\x9e\xc5\x61\x5c\x34\x33\xdd\x8b\xc8\x43\xa0\xc5\x91\x4b\x73\xe8\x9d" + - "\xcb\x78\x74\xd4\x7f\xf8\x33\xac\xc5\x21\x0d\x55\x8d\xc3\x8b\xc3\xfe\xcb\x3c\x69\xe0\xe9\x8b\x8f\x09\xee\x15\x9f" + - "\xcf\xcb\xf2\x42\xf8\xf7\x7d\x80\x22\xdf\xdb\x87\x5d\xad\x14\x98\xf5\xb2\x4d\xf9\x39\x19\x88\xe9\xe8\xa0\xc7\x3d" + - "\xb8\x27\x03\xa7\xd4\xf4\x8a\x46\x07\x50\x27\xf0\x33\x1d\xb0\x2f\x0f\x81\x2c\x93\xe3\x08\x06\x84\xd7\xa6\x68\xb2" + - "\xc2\xe4\xf7\x84\x33\x31\xb0\xd4\x59\xe1\xb0\x99\xbc\x77\x71\x6b\xc0\x87\xf1\x44\x11\xf4\x61\x97\x7b\x32\x6f\x72" + - "\x84\x9c\x6d\xf5\x00\xb3\x55\x62\x1c\x47\x30\x14\xe0\x6d\xce\x0d\x6b\xa9\x46\x23\xa5\x57\x4d\xb9\xd0\x4d\x36\x81" + - "\xfb\x98\xc7\x29\xc4\x4f\x0f\xd4\x7a\x25\x60\x50\xb1\xe7\xab\x02\xfb\x1e\x0d\xb1\x75\x51\xa3\x9e\x76\xb5\x24\x20" + - "\xf8\xba\xa1\xee\xd4\x4d\xb9\x14\xf1\x09\xde\x1e\x00\xcb\x0e\x38\xc6\x14\xc3\x2c\xdd\x99\x07\xaa\x00\x60\x37\xdc" + - "\x1b\xed\x14\x1b\xdb\x72\xb3\xed\xec\x70\x39\xea\x3a\x56\x0d\x0c\x37\x00\x58\xf4\xba\xa2\x1b\xed\xdd\x67\x2f\xd9" + - "\x22\x35\x98\xf5\x7d\xb9\x3a\xcf\x41\xdd\x5f\xd4\xab\x05\xf2\xd0\x7b\x6a\x66\x0a\x53\xe9\x06\x52\x6f\xf9\x8d\xe9" + - "\xd2\x6f\x95\x95\x43\x8b\x97\x08\xbd\xe8\x0a\x29\x76\xf2\xed\xe7\xcf\x9e\x32\x10\xce\xf0\x29\xd3\x44\xf8\x12\x09" + - "\x63\x4b\xe1\x12\x33\xcb\xa1\x86\x2c\x24\x3f\x70\x59\xe1\xcc\x10\xfa\xe3\x1d\x40\x64\x1b\x20\x5c\x36\xa9\x65\x4e" + - "\xc3\x6e\x27\xd8\xa5\x33\x2f\x1a\x76\xdd\x37\x9d\x7a\x9b\x16\xad\xea\xbe\x6a\x6a\xd3\x34\x60\xf1\x79\xd4\xa1\x61" + - "\xde\x0c\xec\x4b\xfc\x99\x2d\x70\x28\x2f\x25\xa2\x77\x18\x57\xd5\x98\xaa\xe3\x50\xb6\xee\xef\xa7\xdc\x89\x48\x86" + - "\x0e\x89\x24\xe5\x55\x0e\xc8\x50\x14\xab\xdd\xd6\xdb\xfb\xec\x64\xa4\x0d\xbe\x8d\xdf\xdd\x4c\xa0\x29\x6f\xa6\x98" + - "\x40\xc9\xa2\xb9\xfc\x0a\x78\x72\x9c\x67\x24\x7c\x1c\x10\xd4\x80\x1e\xfb\x4a\x63\x25\x54\x48\x44\x76\x76\xb0\xa6" + - "\xd3\xfd\x33\x5c\x8b\x2e\xfa\xd8\xa6\xd9\x51\xf5\x31\x5b\x85\x16\xc9\xf6\x8d\x26\xcf\xd2\xdd\xbc\xd1\x9d\x8d\x8a" + - "\xc6\x80\xaa\xfd\xf7\xa7\xb6\xc7\x15\x8a\x7b\x74\xe0\x4c\xc5\x1f\xc9\x69\x3f\x44\xda\x72\x40\x48\x10\x48\x03\x15" + - "\x70\x4c\x98\xa9\x1a\x9d\x61\x9e\x6b\xfc\x52\x57\x06\xb4\x08\x56\xb8\xea\x4d\xaf\xec\xa5\x65\x89\x0e\x34\x77\xee" + - "\x52\x9c\xf4\x21\x95\x56\x0b\x62\x0b\x37\x82\x00\xda\x02\xd8\xc4\x05\xb9\xd9\x22\x9c\xcc\x11\x84\xa7\x33\x14\x41" + - "\x57\x3c\xa8\xd7\x92\x82\x46\xef\x88\xd3\x15\x92\xf6\xb0\x95\x1b\x95\x11\x10\xba\x2e\x6c\x0f\x1a\x82\xad\x4b\x8e" + - "\x2a\x95\x80\x6e\x18\xa8\xcc\x8d\x5a\x7a\xe3\x3a\xd0\x32\xc3\xff\x2e\x82\x60\x67\xa3\x83\x1e\xb4\xed\x1c\xb7\x70" + - "\x48\x5d\xb6\xfd\x66\xb1\xec\xe6\x61\x6d\x9f\x41\x83\x39\xe8\xa2\xf4\x3c\x16\xec\xfc\x62\x09\xde\x6e\x8b\x25\x5e" + - "\x64\x7e\x72\x60\xb6\x28\xac\x1f\xda\xa2\x9b\x0e\x20\xc9\x1d\x06\x5e\xe4\x45\xc0\x2b\x41\x57\xa1\x44\x8a\x68\x47" + - "\x49\x3a\x32\x0d\xbe\xd8\xc5\x6a\x01\x69\x99\x4e\x77\xf7\xce\x8e\x7b\xc7\xe3\xf7\xe9\xc3\xf7\xc3\x9b\xfe\xfb\x74" + - "\xb7\x77\x3c\x3e\x35\x2f\xcf\xe0\xc5\xfb\x74\xf7\xa6\x3f\xea\x0f\xeb\x72\x55\x4d\x8c\xb3\xcf\x4f\xea\xfa\x25\x18" + - "\x79\xc1\x47\x24\x79\x57\x2e\x93\x81\x4a\x7e\xb2\xc2\x9f\xfd\xf1\x6d\xd9\x34\xe5\xc2\xfe\xfa\xc1\x4c\x9b\x84\x9c" + - "\xa0\x40\x39\x5f\x7f\x9f\xa5\xa9\xe9\x8a\x0e\x33\xb9\x70\x87\x75\xe5\x50\xa0\x3c\x37\x1c\x80\x0c\x7c\x10\x6e\xe0" + - "\xfb\x98\xbd\xcb\x55\xc4\xde\x9b\x00\x04\x0d\xe9\xa3\x6a\x33\x10\x49\x52\xd1\xc5\xa8\x36\x93\x52\x40\xdd\xde\xfb" + - "\xcc\x99\x07\x4c\x6e\x37\x81\xfd\x43\x4e\x26\x6b\x2b\xfd\xc5\x9b\xa4\x59\xbd\xcc\xf5\x35\xeb\xa1\x93\xa2\x2c\x4c" + - "\x02\x01\x45\xad\x34\xc7\xa0\xc4\x07\xbf\x88\x17\x2e\x22\x5f\xd8\xb7\xdc\xbc\x54\x10\xa2\xaa\xcf\x73\xd2\xf6\xab" + - "\x1e\x98\xb5\xe1\xe9\x79\x79\x75\x53\xe9\x34\x2b\xfb\x7f\x18\x65\xde\x09\x22\x26\x81\x80\x46\x49\xa9\x79\xed\x3e" + - "\xe5\xc0\x5f\xf4\xaf\xe1\xe6\xbf\xa3\x12\x74\xe8\x53\xf0\xc0\xe0\xcf\x86\x7a\xb9\x34\x45\x0a\xe9\xe9\x7a\x71\x0d" + - "\x2f\x71\x22\x7b\x76\xfc\x97\x60\x62\x80\x1a\xb2\x62\xb9\xea\x68\xcf\x97\x86\x02\x09\x5f\x2c\xa3\x91\xba\x7f\x70" + - "\xf0\xe8\xe0\x4b\xb5\xc7\xa1\x52\x90\xc2\x99\x62\x74\x1d\x2a\x05\x7a\xf2\xd4\x22\xe0\x1c\x0a\x80\x97\xa9\x37\x92" + - "\x4b\x53\xc5\xcf\x10\x66\x5c\xdb\x5a\xd5\xb3\xe5\xb2\x56\xbd\x9f\x7f\x7e\xd6\xc7\x42\xff\xb0\xd5\xfd\x03\x74\xbc" + - "\xff\xb0\x47\xf4\x1f\xa8\x7f\xb0\xb2\xbf\x33\x6f\xc3\x6d\xf9\xf3\xcf\xcf\x20\x4d\xee\x72\xd5\x04\x2f\x7b\x2a\xb1" + - "\xdf\xd9\x2d\x0d\x4b\x41\xa7\xba\xb3\x20\x75\xd4\x96\xe5\x9f\xb7\x94\x06\x57\xbb\x81\x4a\xfc\x14\xa5\x96\xd5\x93" + - "\x0b\x81\x53\xec\x27\xd0\x0d\xf9\x44\x4f\x75\x95\xa9\xcf\x87\x07\x03\x95\xbd\x3d\xc1\x1f\x1c\xbd\xf2\x64\x78\xe5" + - "\xff\x78\x34\x7c\x8c\xdf\x96\x61\x88\x1a\xd8\x92\xf3\xb2\xf0\xd3\x8b\x38\x7d\x93\xb2\xaa\xcc\xa4\xc9\xc1\x39\x4c" + - "\x26\x7c\x26\x77\x94\x21\x14\x7f\x0e\x5f\x1e\x29\xdb\x63\xa8\xe5\x4d\x99\x1a\x86\x1e\xe9\x78\x62\x05\x08\x18\xd3" + - "\x90\x5a\x73\x43\xf2\x56\xef\xc6\x5c\x35\xba\x32\x1a\x95\xf8\x7c\x00\xfa\x7c\x0f\x02\x40\x0e\x01\x55\x2e\x4d\x95" + - "\x5f\x63\xf7\xd3\x68\x66\x5e\xbd\xfc\x7a\x8f\x6d\x57\xb6\x77\x59\x51\x98\xea\xfb\x77\xaf\x7f\xb0\x8c\xe1\x53\x6e" + - "\xe3\x9b\xab\xa7\x23\xf7\x1b\x98\x45\x1e\x5e\x51\xc2\xd8\x9e\xd3\xa4\x1c\xa9\xed\xed\xee\x41\xfa\x21\xc9\x0e\x42" + - "\x16\xbc\x1e\xd3\xda\xba\xa9\x3c\x1f\xe8\x32\x3a\x85\x99\xf9\xed\xff\xb8\xf1\x69\x39\x59\xd5\x59\xf1\xed\xea\xfc" + - "\x1c\xe1\x8f\x93\xb2\xa0\x67\x89\x5d\x0f\x0c\xa8\xa7\xcf\x2e\x75\x75\xef\xb3\xad\xea\xc2\x5c\x43\x74\x3d\x38\xc4" + - "\x5c\x98\x6b\xf2\x7b\x29\x57\xb5\xf1\xcf\x7b\xc7\x63\x78\x72\x03\x7e\xb8\xa6\xba\x21\xa8\xae\x85\x29\x56\xfd\x9b" + - "\x49\x9e\x4d\x2e\xf0\x3b\x68\xed\x75\x59\x2d\xe7\xfc\x1d\xb5\x0f\xff\xdc\xc0\x7f\xcb\x55\x73\x9e\xaf\x2a\x76\xb1" + - "\xb1\xa3\x02\x95\xe5\xd2\xb9\xe5\x9c\xfe\x7d\x78\xf6\xb0\x6f\xef\x96\x61\x6f\xb8\xdb\xbf\xe9\xff\x61\x14\xba\xdc" + - "\x20\x89\x7d\x57\xad\x0c\xd1\xb0\x30\xf1\xfb\xc7\x8e\xc2\x90\x1b\x27\x2c\xcd\x19\x6c\xc2\xe2\xb5\x9e\x9a\x67\xe0" + - "\xe5\xce\xa4\x08\x3f\x72\x0e\x29\x7c\x59\x3a\x80\x04\x59\x18\xa8\xb3\x0f\xe5\xaa\x40\x22\x50\x1f\xc3\xac\x7a\xdf" + - "\x03\xb6\xa0\x40\x68\xb1\x14\x64\xa1\x0b\x3d\xcb\x8a\x19\x41\xa9\xa8\xbd\x3d\x90\x49\x97\xba\x6a\x38\x7f\x14\x89" + - "\xa4\xb0\x04\x53\x3d\x31\x43\xcc\x2f\x57\x95\x4b\x82\x30\xd3\x85\x7a\x99\xae\x75\x95\xd6\x0f\x14\xc3\x26\xa8\x3c" + - "\x3b\xaf\x34\x85\x3b\x41\xb4\x3d\xd5\x96\xa5\x46\x63\x9a\x3a\x1f\xbe\x6b\x68\xc9\x51\xe1\x30\xcb\xcb\x73\x9d\x8f" + - "\x31\x84\xb0\x9d\x11\xda\x4b\xae\xf5\x80\x21\x55\x38\x86\x2b\xcc\xf7\xc9\x0c\x26\x16\x7a\x7b\xfe\xcb\xab\x62\x80" + - "\xe3\xc4\x20\xa3\x81\x67\x3d\x71\xf4\x03\xd5\x0c\x7c\x69\x52\x28\x2d\xcd\x24\xd3\xb9\x6b\xca\x89\x33\x6e\xf7\xd4" + - "\x56\x02\xcf\x66\xf6\x26\xf4\x9c\xe9\x0b\xa1\x86\x0f\xd9\x2f\xe9\x91\x8e\x49\xe4\x31\x69\x03\xaf\x40\x53\xaa\xa2" + - "\x84\xcf\xad\x38\x64\xae\x9a\x11\xc1\x7e\x50\x38\x68\xef\x7c\xd5\x50\x4c\x05\xba\x05\xb3\x83\xfd\xbd\x20\xd1\xf9" + - "\x0b\xa9\x4c\xec\xc4\xed\xb1\x82\x37\x24\x62\x2a\x30\x8d\x7d\x56\x88\x60\x6b\x48\x03\xe6\xec\x39\xf6\x5d\x9e\x99" + - "\x15\x2f\x22\xcd\x85\x6b\x91\xfe\x1e\xce\x23\xbc\x1d\x31\xf3\xea\x88\x4b\x1d\x8a\x57\x95\x7b\x0c\x85\x86\x41\x11" + - "\x91\x51\x55\x96\xe1\xc7\xd1\x70\x04\x4d\x66\x5c\x25\x6e\x03\xe3\x4b\x29\xb7\xcf\xab\x17\x03\x84\x1a\x83\x34\x6b" + - "\x45\x3a\xe2\x3c\x66\x8d\x77\x4f\xc2\x69\xe4\x51\xcd\x56\x59\x1a\x0d\x89\x1e\x3a\xe1\x64\xc6\xd1\xa4\x01\x30\x52" + - "\x91\x11\xf8\x01\x9e\xd2\x07\x35\x41\x9e\x58\x0a\x3b\x69\x40\xf4\x2d\x52\x70\xd0\xf4\x1b\x59\xa8\x89\x5d\x5a\x75" + - "\xdf\xa5\x1e\x6d\x12\x74\x03\x81\x38\x56\x7c\xe2\xe5\x96\x4d\x25\x82\x10\xc9\xb0\x3e\x82\x85\x11\x9f\x60\x77\xa2" + - "\x4a\x37\x15\x0b\xb9\xe3\xc0\x44\xfb\x02\x3d\x77\xd1\x6b\x0d\x59\x59\x9c\x02\x90\x2e\xe5\xf1\x67\x20\xa6\x1e\xd8" + - "\xb6\x5d\x05\x98\x16\x91\x33\x62\xc6\xc8\x3e\x5a\x2d\xf5\x0c\x2d\xe6\x2b\x00\x76\x61\x43\x29\x53\x66\xbc\xbb\xc8" + - "\xde\x6d\xc5\xaf\xe0\x72\xf3\xc0\x83\x41\x17\x28\xde\xc6\x00\x16\x88\x73\xcb\x0e\x4a\x5a\x9e\xda\x52\x5b\x06\x21" + - "\x47\xa2\x14\x82\x5f\x46\x39\x37\x3e\x46\xbb\x83\x66\xd3\xb9\x4b\xd0\x2a\xf9\x98\x88\x73\x40\x25\x65\x4f\x72\x20" + - "\x78\xce\x78\x01\xc9\x28\x92\x44\xf5\x37\xb9\x86\xdb\x97\xa8\x87\x6f\xe8\x0e\x0f\x1c\x6a\x58\x60\x6c\x5a\x02\x63" + - "\x78\x33\x0e\xcd\x95\x99\x50\x93\xa7\xcd\x19\xfb\x9d\x07\x92\x2a\x13\x3f\xdb\xce\x62\x79\x7a\x40\x6f\x3d\x7d\xc4" + - "\x5e\x2f\x96\xa7\x8f\xce\x5c\xb7\xeb\x65\x9e\x59\x76\x7b\x08\x7f\x94\x55\xd3\x8b\x3c\x2a\x2a\xa3\x1e\x2e\x56\x75" + - "\xf3\x10\x02\x6e\x99\xe6\x96\x44\x2c\xc1\xdb\x9e\x1b\xd8\x83\x40\x07\xa6\xcf\x5e\x7a\xdd\x96\x2a\x12\xc4\x39\xcd" + - "\x0a\xc6\x23\x15\x5a\xe3\x57\x53\x86\x22\x02\xcb\x5d\x0d\x39\x56\xb0\xc1\x15\xfb\x3b\xe3\x2d\x10\x02\x79\xb1\xc6" + - "\xca\x38\xff\x46\x52\x93\xb8\x5b\x43\x80\x0e\xc0\xb6\xa1\xc7\xa4\xab\x24\x5f\xf7\xc3\xa0\x27\x8e\xe8\xd1\xe6\x19" + - "\xf8\x38\xb9\xa8\x17\x7a\x99\xb1\x42\x85\xc3\x13\x08\xc7\xd8\x75\xc3\x19\xbc\x5c\xad\xc7\x5c\xc9\x30\x35\xb9\x99" + - "\xe9\x06\x25\xb8\xb1\x7b\x7c\x9e\x15\x29\x62\x4b\xd8\xde\x91\x5a\x82\xfb\x47\xc0\xb5\xdc\x0f\x17\xf9\x84\xd1\x97" + - "\x95\x01\x07\xd0\x7f\x73\x0e\x1c\xa9\x07\xb6\x59\xd7\x35\x5b\x5e\xe3\xd9\x0f\x6f\x18\x89\xef\xe0\x54\xb9\x34\x05" + - "\x63\x9c\x27\x7c\xc0\xdb\x75\x1c\xdd\xda\xe4\xaf\x27\x9c\x80\xa8\xa1\xb1\x23\xce\xf8\xd8\xd2\x7a\xf7\x0c\x28\x3f" + - "\x03\xa4\xd3\x24\x8f\x7d\x82\x6e\x7c\x61\xa5\x37\x86\x00\x1d\x07\x79\xc0\x3d\x24\x45\x85\x27\x79\x28\xcb\x92\xc3" + - "\xae\xe7\x6a\xb8\x3e\xde\xf9\x63\xc1\x85\x0c\x7f\x29\xb3\xa2\x97\x0c\x13\x74\x67\xfb\x38\x90\x97\x66\x60\xb1\xf4" + - "\xf7\x52\x00\x4b\x47\x46\x28\x06\x14\x0d\x6e\x1f\xbe\x2e\xdc\xce\x3f\x22\x7a\xc5\xcb\x28\xf4\x66\x1b\xcb\xc8\xc4" + - "\x4e\x5c\xc8\x6d\xc3\xe7\xa4\xfc\xdb\x97\x0a\x62\x70\x8d\xb6\x67\x30\x46\xe3\x62\x38\x89\xe0\x44\xd4\x6e\x28\x51" + - "\xf2\x5c\xaf\xe8\xe3\x5d\x5e\x9b\x66\xb5\x84\x8c\x3f\xf2\x41\x60\xfb\x41\x8e\x52\x72\x79\xf2\x12\x94\x19\x31\x85" + - "\xf3\xa2\xf3\x84\x6c\x75\x58\x38\xff\x75\x16\x60\xe5\x68\xc0\x9f\x4a\x7c\xb1\x38\xc5\x8f\x0b\xf6\x01\x20\x7c\x1a" + - "\x86\x4e\x85\xd7\x80\x78\x18\x8c\xcc\x9f\x99\x48\x7d\xbe\xed\xde\x0c\x3b\x79\x1f\x71\xdc\x86\x11\x1f\x24\xff\xec" + - "\xf4\x1a\x64\x4c\xd6\x32\xe2\x88\x78\xc9\x30\x15\x0e\xef\x86\x1a\x05\xf9\xb2\x10\xbb\x2f\x4e\xe6\x2f\x36\x11\xa7" + - "\xa4\xeb\xde\x55\xbb\xbb\x00\x21\x13\x0e\xbb\x65\xec\x76\xdf\xa2\xb9\xbb\x5d\xda\x0f\xe4\x4f\x41\x6e\x6b\x74\x84" + - "\x73\x3b\xf0\x12\xce\x55\x85\x3e\x3b\x96\xd1\x1c\xa0\xff\x1c\xb2\x3d\xcb\x26\x5b\x64\xbf\xfa\xb0\xb6\x80\x34\xa2" + - "\xe4\x23\x8e\x4b\x04\xbd\x25\x01\xe3\x41\x64\x70\x8c\x51\x59\x61\xfc\xed\x94\xfb\x01\x8a\x47\xef\x45\xd8\x19\x51" + - "\xda\x2d\x49\x39\xda\xa5\x16\x7a\xb9\x34\x70\x19\xd4\xa1\x40\xf5\x0b\x4a\x3c\x30\xb9\xff\xab\x42\x54\xec\x91\x4f" + - "\x6e\x33\x9b\x24\xac\x48\x1a\x02\x0c\xa5\xbb\x19\xe8\x4e\x61\xe9\x6d\x31\x41\x95\x9b\xb1\xf3\x6e\x3b\x3f\xf4\xea" + - "\x03\x32\x90\xd4\x87\xb8\x72\x84\x12\x52\x2e\xb2\x86\xc0\x08\xfe\x3f\xc5\xbc\xfd\xb9\xb0\x3c\x84\xbf\xb0\x6b\xd5" + - "\x2b\x0b\x42\x47\xe1\x6a\x41\xce\x61\x18\x81\xbe\xe3\xa3\xfc\x6e\xed\x66\xe1\x10\xff\x02\x9e\x65\x05\xd7\xde\xb2" + - "\xe4\xe1\x61\x0a\xcd\xc3\x64\xe9\xc0\xb9\x50\x8d\x3a\xeb\xdc\xf1\x1d\x5e\xcf\x1b\xd8\xc6\xdf\xc9\xdc\xfc\x07\x79" + - "\xb1\x5b\x6f\x58\xb9\xc0\xb0\x23\x68\xe5\x76\x76\x20\x30\xf1\x27\x33\x7b\x79\xb5\xec\xa9\xa4\xf7\xf7\x9b\xf7\xef" + - "\x87\xfd\x44\xed\xb6\x39\x88\xf7\xef\x87\xbd\xe3\xf1\xf0\xe1\xfb\xf7\xc3\x9b\x7e\x02\xde\x51\x3d\xfb\xfb\x0f\xfd" + - "\x24\x60\x23\x28\xd7\xa3\x8b\x7e\xf5\x60\xbc\x5b\x8e\x3a\xd8\xf9\xf1\xb7\x43\xdd\x19\x90\xfa\x8b\x0c\x48\x95\xfc" + - "\x1c\x7f\x75\xaa\x7e\xf1\x59\x66\x70\x5f\xf4\x02\xe2\x74\x73\x23\xf6\xf1\x91\xd0\x16\x0c\xdd\x63\x4b\x2b\x68\x97" + - "\x78\xc9\xde\x7e\x18\xde\x63\xc1\xc7\x74\xf7\xc9\x0f\xed\xa4\xda\xa5\x58\x2c\x89\x37\xf3\xa5\x3d\x39\xe8\x47\x1f" + - "\xb9\x05\xb7\xfc\x86\xd3\x69\x04\x4d\x6d\x2c\x92\x3c\x7c\x08\x86\xec\x8e\xa2\xfd\xd6\xbd\x2c\x6e\xc2\x5f\x38\x31" + - "\xab\xe4\x4c\x3a\x2b\x71\x6c\x49\xf7\xe5\xe9\xf3\xa2\x7e\x94\x55\xf1\x16\x25\xe5\x89\xa8\x26\x7c\x73\x0b\xe3\xb1" + - "\x99\xa5\xf1\x9b\x0b\x3c\x5f\xb2\x49\xc4\xa9\x02\x8f\x4a\xae\x51\xa9\xaa\xcb\x85\xe1\x14\x9f\xa9\x15\x11\x17\xe8" + - "\x45\x4f\x67\x04\xfc\x7b\xb9\xda\x9e\xbe\x2c\xb3\xb4\x56\xcb\xb2\x31\x45\x63\x0f\x30\xd0\x74\x5b\xb4\xae\x39\xc9" + - "\x72\x59\xa8\x74\x05\x91\xe9\xd0\x84\xce\xed\xbd\xda\x2d\x01\xf6\x3d\xa9\xf2\x7b\x7e\x67\xc7\xed\xb0\x76\x44\x4d" + - "\xc8\x87\x36\x46\x57\x69\xb9\x2e\x24\x2b\xca\xcf\x42\x4f\x24\xc9\x87\x46\xea\x97\x6e\x5e\xd4\x81\xc4\x3a\x98\xe7" + - "\xd0\x13\xb0\x55\x4b\xec\x46\x4d\x2e\x52\x21\x85\xe9\xc4\xf3\xfa\xc9\x3b\xa9\x71\x30\x2d\xc3\xc2\x16\xa5\xca\xcb" + - "\x62\x66\x2a\x60\x85\xee\x7d\x76\x2b\xe6\x92\x23\xe8\x51\xd4\x76\xd4\x55\xec\xc3\x26\x47\xa0\x04\x6b\x49\xda\x68" + - "\xf2\xa4\xde\x09\x58\xa0\x4b\xb0\x71\x22\xaf\x8f\xdf\x97\x45\x7e\xfd\x3d\x6f\x9e\x80\xed\xc9\x06\x6a\xb2\xaa\x90" + - "\xe1\x51\xe7\x60\xee\x78\x87\xf2\x77\x81\x53\x3a\x27\xb6\x9d\xd9\x1d\xcf\x15\xfd\xa8\xc1\x1f\x11\x9d\x06\xc0\x4d" + - "\x8a\xf1\xc4\x29\xba\x8b\x6e\x87\xb9\xae\xdf\xfa\x95\xc7\xce\xa1\x29\x0f\x22\x36\x49\x4d\x85\xb7\x04\xbe\x6e\x5f" + - "\xd7\x9d\x75\xb8\x12\xb2\x22\xcf\x29\xe0\x8d\x6e\x85\x47\x35\xc6\x1b\xc4\xd6\x3b\x59\x55\x78\x85\x70\xd8\xd9\x51" + - "\xab\xff\xb1\x2e\x3b\x2d\x79\x15\xed\x9d\xcf\x99\x5a\x03\x0d\xf6\xbd\xcf\x36\x86\x8c\x3d\x66\x93\x76\xf8\xf8\xab" + - "\xdb\x79\x33\xb0\xef\x8c\xce\xf3\x55\x65\x8f\xfe\x12\x43\xd8\xc9\x02\x34\x2a\x57\xcd\x21\x3b\x1a\x75\xa5\x15\x5f" + - "\x50\xfa\xf0\xa2\x5c\xbb\x8e\x09\x83\x12\x91\x79\x62\x1f\x36\x68\x0b\x6f\xe3\x1d\x9d\x13\x88\xf7\xfb\xb6\xb3\xfc" + - "\x8d\x0c\x08\x1b\x8d\xd4\x1b\x5e\x8a\x54\x51\xbd\x87\x0e\x6a\x42\x55\x66\x66\xae\x96\x76\x54\x70\xd9\x12\x0d\x62" + - "\x36\x08\x77\x1d\x65\x3b\x09\x76\x02\x34\xeb\x97\x36\xe0\x43\xc4\xb5\x1f\xf8\x85\xca\xe7\xcc\xd9\xd1\x81\xc7\x6d" + - "\xce\xf5\xba\xe1\x8c\x93\xbe\x7a\xaa\xf6\x2d\xd9\x4b\xca\x22\x21\x2e\xeb\xf0\x56\x3b\x03\xcf\x24\xda\x8a\xd8\x91" + - "\xf1\xad\x77\x68\x44\x17\xe9\x42\x0e\xd5\x47\x3d\xb3\xbd\x08\xfe\x3d\x8d\x71\x3d\xcf\x48\x65\x8b\xa5\xd0\x7b\xcd" + - "\x32\x3f\xb2\x49\x96\xb6\x49\x41\x4c\x15\xca\xb0\xb4\x9d\x1d\x7a\xda\x91\x86\xe0\x3c\x6b\x16\xba\xbe\x18\xab\x1d" + - "\x75\x80\xa0\x9d\xba\xc9\x2e\xfd\x9d\x73\xa8\x76\xd4\x23\x78\x41\x9a\xe7\x1e\x79\xf3\x5a\xfe\xb2\xef\x46\x30\xcc" + - "\x6a\xae\xf1\x28\x24\x3b\xc7\xea\x91\x1a\xab\xc7\x87\xbe\xa8\xb4\x55\x76\xe9\x7c\xba\x8a\x7e\xa8\x0c\x4f\x92\xf8" + - "\xfe\xd8\x4d\xc8\xbf\xcf\x0d\xf2\xec\x7a\x60\x66\xbb\xde\xb9\xd1\x05\x3b\xe1\x92\xde\x1e\x11\xca\x30\x20\x1c\xfd" + - "\x82\x55\x65\xf8\x46\x60\x7e\x1d\x42\xcf\x62\xcf\x27\x92\xe1\xf0\xc4\xe9\x6a\x66\x9a\xd0\x28\xc1\x0f\x8f\xbc\x2b" + - "\x8c\x30\x71\x81\xc5\x1f\xd2\xa7\x14\x93\x72\x01\xe8\x71\x1c\xce\xbc\xac\xcc\xd2\x10\xe4\x1c\x51\x49\x38\x70\x8c" + - "\x8b\xe1\xb2\x35\x54\x33\x97\xb8\x3c\xc4\x04\xa0\xac\x90\xd0\x97\x53\x1a\xe9\x19\x4d\x49\xcb\xcf\x9e\xee\x18\x5f" + - "\x4e\xec\xab\x67\x08\xbd\x1f\xea\xb2\x9a\x52\xa5\x95\x5e\xab\x72\xd5\xd4\x59\xca\x39\xcd\x0b\xa4\x9f\xbf\x5b\xfc" + - "\xc0\x69\x0c\x36\xd9\xce\x8e\x67\x39\x68\x1b\xb6\x1f\x85\x06\x0e\xf2\x81\x6d\xb3\x1b\x9d\x74\xd9\xa1\x39\xd3\x98" + - "\x97\x55\xb9\xd4\x33\xc4\xcc\x00\x2c\x0d\x4b\x09\xd2\x4b\x5d\x58\x79\x70\x69\x2a\xf5\xf3\xe3\xe7\xce\x0c\xb2\x34" + - "\x13\xd5\xbb\xff\xf5\xd7\x9f\x1f\xf4\xa9\x3a\x74\x30\x80\x8d\x55\x8a\x8c\x21\x0d\xf8\xe0\x30\xc0\xff\xa1\x5a\x03" + - "\x89\x44\x80\x5b\x54\xa8\xa8\xc0\xa3\x49\xd9\xab\xbc\x77\xff\xeb\x2f\x1f\x3d\xe9\x6f\x9e\x19\xc7\xa1\x15\x25\xb5" + - "\x6b\x1f\x3a\xb6\x05\xbd\x77\x9c\x1e\xc2\xfb\xca\x7b\xb6\x40\x1d\x75\x8b\x77\x81\x24\x47\x09\x31\x5a\xf7\x8d\xa8" + - "\x66\x97\x3d\x3d\xbd\x21\x03\xae\xe5\xc9\xaa\x1a\x2e\x75\x65\x8a\xe6\x4d\x99\x1a\xc1\x97\x39\x40\xf1\xc9\xaa\x82" + - "\xff\xb4\x0a\xfb\xaa\x1c\x73\x42\x5a\x2f\x5b\xba\xef\x9d\xfa\xf0\xcb\x96\xfe\x0b\xd4\xb2\x3a\x4d\x69\xce\x89\x1f" + - "\x9f\x95\x8d\x5c\x19\xd5\x33\xc3\xd9\x70\x80\xee\x04\x6c\xa8\x56\x60\xd8\x68\xf4\x64\x6e\x52\xf5\xe2\xed\x6b\xc1" + - "\x3f\x43\x73\x47\x47\x18\x33\x1b\x3a\xa1\x49\x86\xa3\xbf\xb9\xf3\x56\x2a\x63\xb7\x96\xcc\xac\x59\x50\xc3\x71\xe3" + - "\x8a\xd9\x67\xd4\xe9\x6e\x68\xda\xef\x32\x29\x3b\x94\x85\x20\x62\x76\xcb\xc2\x86\x21\x2d\xb5\x97\x60\x7b\x38\xc9" + - "\xae\x3f\xa7\xd9\xee\xee\x19\x68\xa7\xb6\x99\xd0\xff\xe8\xf7\xfe\x49\x53\x5a\xd1\xb5\x27\xb7\x8d\x60\xec\x8e\x54" + - "\x86\x79\xf5\x70\x90\x62\x27\x10\x2c\x47\x4b\x3b\xd0\xb6\xd3\xd0\xb5\x23\xcc\xf4\x5b\xce\x54\xdb\x8b\x55\x66\xc0" + - "\xd3\x7a\xae\x19\x89\x86\xea\x9f\x4a\x6e\xf3\xac\x43\xd5\x86\xdf\x61\xbd\xa1\xdb\xa8\x93\x4b\x02\xa1\x9e\x49\x09" + - "\x7c\x27\xa3\x89\xc4\xce\x7a\x13\x5c\xa4\x61\xc7\x89\xfd\xd8\xd9\xb1\x35\x9c\xf2\x9f\x67\xed\x76\x9d\xb8\x8c\x2d" + - "\x0a\x3b\x8b\x87\xed\xa6\xad\x1e\x6d\x26\x7f\x09\xdd\xd1\x65\x62\x60\x83\x6f\x3a\x64\x30\x2c\x40\x11\x32\x2f\x70" + - "\x6b\xf6\x3a\x62\xa8\x3e\xfa\x6b\x50\xb0\x58\x11\xc8\xf5\x79\x99\x5e\x73\xb4\x8d\x49\x39\xed\xa9\xad\xd2\xa5\x99" + - "\x4f\x01\x73\x45\xb2\xb2\x6d\xc2\xc6\x3b\x92\xba\xf3\x23\x57\x18\xec\x47\x54\xb2\x38\x22\xf8\x81\x1b\x12\x62\x2a" + - "\x3f\x73\x37\x84\x3f\x8d\xe5\xb2\xd7\x6f\x5f\x16\x5e\x29\xd2\xb1\x1a\x2d\x42\xca\x9c\xa3\xd2\xcc\x5d\xbd\x78\xfb" + - "\x9a\xd1\x43\xe9\x5c\xd2\xd5\xef\x61\xdc\xf4\x82\x5c\x31\xe1\x3f\xba\xf6\xa7\xd7\x47\x9e\x3a\x39\x25\x9c\x3c\x38" + - "\xec\x48\x1a\x30\x3b\xcc\x03\xc6\x53\xa5\x4b\xe4\x52\x57\x99\x06\x0f\xb7\x73\xa3\x7a\xf7\xbf\x38\xf8\x72\xbf\x2f" + - "\xf6\x82\xdf\x9d\x1d\x89\x35\xec\xe8\xdc\xa5\xdc\xff\xc4\xab\x44\xf4\xb6\x32\x7b\x8d\x4b\x81\xa5\xca\xe2\xbb\xb7" + - "\x6f\x89\x28\x81\x7f\xc4\x1a\xfd\x8d\xc1\x6e\xfd\xdd\xdb\xb7\xbd\xbe\xcb\x28\xb5\xe5\x09\x39\xf6\x41\x9c\x1a\xa9" + - "\xce\xb1\x45\x22\x0b\x95\x2f\x1b\xe7\xf0\x96\xfd\xa3\xed\x23\x7a\x48\x38\x8e\x6e\x3d\x88\xb7\xaa\x01\x0b\x71\xed" + - "\xb3\xac\x21\x61\x4b\x21\x19\xd1\xb9\x43\x3c\xdc\xda\x20\x62\x49\x0f\x79\xee\x1f\xf6\xce\x9d\xa7\xcd\x9f\x86\xbe" + - "\x8b\x9f\x3e\xea\x66\xb1\xdc\xa4\xa7\x8a\x43\x68\x24\x29\x90\x58\x40\xe4\x27\xd2\xd2\x39\xf8\x75\x66\xd7\x25\xad" + - "\x1c\xbc\x7c\x20\x1c\x39\x98\x00\x3a\x06\x46\x88\x4c\x52\x18\x0a\x46\x3f\xcd\xae\x7a\x91\xfc\x42\x1a\x8c\x5f\x06" + - "\xaa\x32\xcd\x80\x10\x29\xd2\x96\xa9\x86\x48\xef\x7f\x53\x38\xcf\x29\xa3\xcf\x54\xb3\x3b\x53\x07\x0b\xb5\x74\xeb" + - "\x92\xc1\xf8\x96\x3b\x6f\x19\xd0\x5f\x07\x36\xa3\x8d\x2c\x6e\xfc\x9d\xcc\xaa\xce\x30\x75\xd3\xec\x6a\xcf\xa4\xe1" + - "\x7c\x56\x1a\xa0\xab\x9b\xb9\x46\x22\xd2\xb3\xdb\x11\x5c\x48\xfa\xc1\x14\xdb\xaa\xec\xa8\x4f\xf7\xcf\xf8\x6e\x17" + - "\x42\x96\x63\xe9\x58\xfa\xa0\x7c\x91\x42\xe6\xa5\xa0\x4d\xf3\x82\xf6\x00\x44\x39\x39\x53\x07\xea\xaf\x49\x0c\xb5" + - "\xf2\x48\x6e\x20\x87\xd8\xb9\xce\x72\xcb\x50\xa5\xa6\xce\x2a\xa1\x31\x63\xb2\x2b\x2b\x14\xec\xba\x78\x4c\xcb\x83" + - "\x33\xce\x9b\xed\x77\xb3\xec\xd2\xcb\x22\xda\x13\xc1\x7a\x38\x45\x67\xab\x55\x6f\xed\x93\xb2\xce\x4f\xab\x42\x58" + - "\x79\xc1\xc1\xe0\xd0\x4e\xc8\x35\x98\xcd\xd6\xba\x60\xb0\x84\x65\x20\x2f\x9c\x9b\xc2\x58\x91\x61\x55\x6f\x60\xc1" + - "\x68\x3f\x7b\xb3\x01\xf4\xf6\x14\x92\xe9\x7c\x32\x2f\xe6\xae\x6c\x8a\xa1\x74\xab\x4b\xb5\x0f\x49\xc6\x44\x11\xcf" + - "\x75\xc2\xf7\x42\x9a\x2f\xf8\x1b\x61\xc6\x68\xf7\xe5\xd5\x62\x61\xd2\x4c\x37\xe6\x0e\x06\x51\xa8\x1f\x0c\xfb\xd0" + - "\x01\x6e\x39\x02\x2a\xab\x83\x3e\x9a\x9e\x8b\x52\x1a\xd9\xca\xca\x7d\xfc\x88\x0b\xf0\xdb\x5e\xdd\x57\x5a\xd5\xab" + - "\x73\x06\x6e\xfe\xe7\x4a\xe7\x68\x9f\x2f\x6b\xb4\x69\xce\x0d\x65\x5b\xc4\xf6\x7a\x80\x45\xeb\x00\x93\x65\x53\x7d" + - "\x09\x72\xb0\xdd\xa1\x87\xb8\xb9\x89\x15\x11\x1f\x2a\x73\x87\x0d\xc5\x5f\x84\x72\xab\x49\xdb\xd0\xdb\xf3\x5f\x0e" + - "\x83\x22\x24\xa0\xfb\x1a\x53\x4e\xd1\xb2\x45\x6e\x81\x40\x9c\x7a\xdd\x24\xa5\xc3\x6e\x44\xa4\xa5\xcf\x5a\x72\x67" + - "\x31\x12\x3e\x10\x3e\x11\xf0\x16\x33\x43\x72\xbf\x80\x5f\x60\xdd\x32\xc6\xd8\xbe\x6c\x82\x7b\x20\xfe\x2b\xe2\x49" + - "\x2b\xd3\x74\xab\xfa\xef\x60\x34\xdd\x7b\x7b\xaa\xc4\x3e\x13\x05\x3e\xde\x75\xcd\x05\x34\xad\xac\x9b\x3b\x89\x5a" + - "\x9b\x70\xc9\xaf\xb8\xef\x5d\x2f\xbb\xe8\x57\x47\xd0\xea\x86\x1b\x97\x4f\x5b\x87\x96\x7f\x1e\x68\xf5\xdd\x8d\x48" + - "\xd8\x4c\x60\x07\xfe\xd4\xeb\x30\xf6\x5a\xea\xb6\x9d\x51\x58\xa3\x17\x0e\x49\x59\x75\x28\xc4\xcd\x22\x75\xe4\x30" + - "\xa0\xb9\xa3\x91\xfa\x36\xd7\x93\x8b\xbd\x79\x99\x1b\x75\xf2\x97\x3f\xaa\xa7\xab\xda\x7c\x03\x69\x95\x34\xe6\xa7" + - "\x34\xa6\x56\xbd\xfb\x07\x8f\x0f\xbe\xda\x67\x1d\x09\xc2\xa0\x16\x65\xb1\x97\x9b\x69\xb3\x07\x31\x12\xc8\x69\x01" + - "\x2a\x6a\x01\xf2\xed\xb4\xbc\x52\xbd\xfb\x8f\xbf\xfa\xe2\xc0\x2b\x40\xc2\x01\xa1\x8c\xe5\x95\xf0\x3b\x3b\xaa\x47" + - "\xa7\xfa\x7c\xd5\x34\x65\xe1\xcf\xb3\x0f\x6c\x84\xc6\x12\x79\x70\x85\x22\x02\xb3\xcc\xda\x3b\xb2\x5b\x23\x61\x65" + - "\xd8\x79\x56\x47\x14\x0f\xb9\xdf\x65\x55\x42\xaa\x07\x68\x00\xf8\xf4\x34\xab\x35\x30\x8f\x2e\x06\xb3\x77\xff\x8b" + - "\xaf\x0f\x0e\x06\xea\xfe\x57\x07\x5f\x7c\x3e\x50\xf7\x0f\x0e\x1e\x7f\xf5\x08\xfe\xfd\xf2\x8b\x27\x92\x4f\xb7\xed" + - "\xba\xcf\x5d\xea\xdb\x8d\xc3\x11\xa7\x8c\xf6\x89\xf4\x62\x73\x89\xff\xec\x4d\x00\x09\xdc\x82\x79\x8c\x52\xb9\x6d" + - "\xb2\x6e\x67\x92\x1d\xf7\xc3\x9e\x94\xc5\x34\xcf\x26\x24\xdf\xb8\x9c\x5c\x9c\x64\x4a\x60\xd9\xd8\x4d\xf0\x68\xff" + - "\xb1\x23\x43\x35\xc0\x70\x77\x58\x7b\x77\x55\xa2\x12\xd1\x16\xcc\x08\x8d\xeb\xd4\xee\x7f\xcb\xf6\x6e\xa2\x49\x5b" + - "\x71\x41\x49\xb8\x85\xd7\xa2\x07\xb2\xf6\xe9\x73\xe1\x68\xe1\x02\xa3\xe1\x80\xe5\x6f\xb0\x83\x8c\xe3\x0f\x86\xd3" + - "\xac\x48\xc5\x57\x8c\x52\x73\x0a\x5f\x9d\xa9\x7e\x04\x0e\xe8\xc1\xee\xba\x46\xd4\x31\x86\x4d\x4e\x5e\x1d\x70\x79" + - "\xb2\xc6\x96\x35\x37\x24\x10\x58\xeb\x6f\xb0\x2b\xc7\xa8\x34\xf0\xe4\x88\xb7\xcf\xc7\x8d\xb6\x6f\x49\x6c\x39\x7f" + - "\xb9\xcf\xd0\xde\x43\x58\xcd\xfc\x7a\x0f\xee\xe4\x7e\x40\x2d\x3a\xce\xf0\xd3\xd8\xeb\x22\x0e\x61\xe8\xe8\x32\xce" + - "\xb5\xef\xb3\x77\x2b\x40\xaf\x82\xb0\x85\xbe\xea\x04\xdc\x93\xd5\x1f\x06\x5e\x6b\xaf\x8a\x49\xbe\x4a\x4d\x0d\x26" + - "\x7b\xa1\x14\xae\x55\x3d\xd7\x94\x14\xf7\x4f\x1c\x19\x66\x79\xe2\xd7\x2e\x20\x0c\xe3\xc9\x97\xf5\x58\x25\x3a\x6f" + - "\xfe\x64\x58\x7e\x04\x40\xc7\x89\xc9\x41\x6e\x9a\x34\x15\xc0\x5b\x85\xdc\x1b\x2a\x26\xe6\xba\x86\xc4\x75\xda\x16" + - "\xa8\x4c\xae\x1b\x93\x52\x01\xb0\x7f\xd9\xc7\xa4\x4f\x68\xb2\x85\x39\x69\xf4\x62\xa9\x2e\x33\xb3\x46\xff\xbe\x84" + - "\xed\x68\x2a\xe9\xe3\x78\xa6\xd9\x15\xa1\x6a\x70\xa0\xd2\x85\xb9\xe6\x27\x76\x3a\xb8\xbf\x93\xb9\xae\x94\xfd\xcf" + - "\x73\x4b\xe8\x2e\xcc\xb5\xfd\xbf\xfd\x1d\xd5\xb9\xb5\x85\x11\xc2\x1d\x37\x97\x65\x47\xb2\x42\xe7\x6d\x50\x16\x74" + - "\x3e\xb4\x64\xc8\x56\x2c\x5c\x70\x84\x82\x0a\xcb\xb0\xbd\x22\xd2\x78\xd1\x4b\xd7\xc4\xd0\xf5\x74\x9b\x0d\x1c\x1d" + - "\xef\xc6\xfe\x19\x0d\x26\x54\xe5\xc9\x3b\x3a\x36\xc3\x43\x4c\x5f\xd7\x44\xd1\xd5\x82\xff\x00\xb9\x37\x45\xf3\x57" + - "\xfa\xf7\x6f\xaa\x9c\x4e\x6b\xd3\xfc\x95\xfe\xfd\x1b\x84\x7e\xfc\x15\xfe\xfb\x37\x55\x4f\x2a\x63\x8a\xbf\xd2\xbf" + - "\x7f\x53\x4d\x49\x91\x71\xff\xea\x1c\x13\xaa\x05\xf2\x53\xe5\x64\xa0\x52\xfb\x9f\xf3\x32\xbd\x26\x1f\x6c\xea\xac" + - "\x98\x38\x7c\x22\xb4\xb0\xcf\x75\x3e\x59\xd9\x8d\x86\x5d\x1d\xfd\xcd\xca\x75\x8b\xac\xae\xd9\x57\x85\x46\x38\xfa" + - "\x9b\xd2\x97\x3a\x83\x3d\x1c\xaf\x1d\x0e\x92\xd7\x6e\x67\x47\xac\x05\x4d\xcf\x76\xe7\xba\xbe\x28\x27\x11\xd3\xb1" + - "\x59\xa5\x4e\xf4\x28\xf5\x9f\xbc\x28\x27\x43\x7e\x2b\x42\x0c\xed\xb0\x4b\x48\x48\xef\x4a\xd9\xbf\xdd\x85\x12\x74" + - "\xb9\xdd\xd3\x5d\xcc\x57\x0d\xaa\xe4\x72\x32\xac\x27\x55\x99\xe7\x3f\x98\x29\x74\x06\x2a\xde\xd9\x81\x7f\xa3\x57" + - "\xfb\xaa\xaf\xf6\xc2\x6f\xb1\xca\xce\x6f\xc3\x57\xfb\x8e\xb2\xfb\xce\xfd\xad\xdd\xb9\xbf\x75\x77\xee\x5d\xb9\x54" + - "\x1b\x3a\xc7\xaf\x36\x76\xae\xf3\xdb\xf0\xd5\x7e\x87\x06\x3c\x3c\xd4\xc0\x84\x8c\xd5\x01\xdc\xca\x96\xa5\x3b\x54" + - "\x8f\xe0\xf7\x22\x4b\xd3\xdc\x1c\xaa\xc7\xf0\x17\xb8\x30\x70\x0d\x6f\xca\xc6\x8c\xe9\x14\x31\xde\x68\x51\x56\x0b" + - "\x48\x03\x92\x0e\x54\x5d\xaa\x14\x18\x0c\x4c\x73\xe1\x77\xdc\xb6\xa4\x08\xb6\xc7\x58\xc5\x06\x21\x25\x24\x1f\x3d" + - "\x2e\xbd\xa3\x0e\xd4\xb1\x3a\x80\xdc\x15\xee\xd1\x23\x75\xac\x1e\x87\x8f\x9e\x90\x91\x7b\x3f\xca\x4a\x7b\x27\xf9" + - "\x98\x66\x57\x1b\xb4\x69\xf2\xe0\x74\x78\x05\x44\x20\x39\x41\xe5\x2c\xe2\xb0\xc7\x85\x53\xc5\x79\x8c\xbf\x50\xf3" + - "\x46\xbe\x66\x34\xab\x78\xa1\x85\x59\x8b\x48\xba\x80\x2c\x82\x50\x4d\xe0\xe8\xe3\xb9\x4d\x7c\xcc\xfb\xf1\xa5\x74" + - "\x6d\x20\xc8\x32\xbc\x68\x18\xd9\x84\xef\x1d\xe1\x91\xe5\x86\xbe\xcd\x65\x9d\x5b\x70\xd7\x17\xea\x48\xb9\x3a\x71" + - "\x2d\x45\xe4\xb5\x74\x78\xe9\xab\x63\x6c\xd3\x93\x6c\xe6\xd5\x5c\x04\x77\x67\x79\xbe\x09\xb9\xb4\x0c\x3c\x84\x19" + - "\x75\x3d\x18\xe2\xfd\x4f\xdf\xc1\x1f\x2e\x01\x4d\x58\xa4\xcf\x89\xae\xe0\x4f\x1a\x35\x2b\x3f\xdb\xfe\x1d\xe1\x84" + - "\x3a\x8f\x70\x2b\x79\x94\xcb\xeb\x2e\x77\x6a\x09\x9e\x02\x59\xf3\xb0\x28\xf3\xe7\xbc\xe5\x45\x86\xbd\xa0\x8d\x20" + - "\xd5\x9e\xc0\x44\xe6\x18\xff\xe7\x65\x95\x96\x97\x5a\x3d\x1a\x7e\xae\x7a\x88\x69\xd0\x47\xce\xfd\xf3\xcf\x9d\xf8" + - "\xe6\x7d\xa6\x29\xa9\x2b\x68\x5a\x34\x71\x26\x87\xae\x92\xd4\x5c\x66\x13\x83\x8a\x74\x02\x46\xb8\xf7\xbb\x9c\x25" + - "\x02\xda\xdf\xd1\x5b\xc2\x6a\xf8\x62\xb8\xbf\x3b\x50\xcf\xe7\x95\xdd\xdf\x4f\xd5\xa3\xaf\xee\x71\xb2\x37\xe2\x9c" + - "\x38\xf3\x2c\x45\xe9\x59\xf6\xbf\x80\xa4\x1d\xf7\x3f\xdf\x7f\x62\xe5\xaf\xc7\x07\x4f\x1e\xf7\xc3\xb3\xc9\x17\x52" + - "\xe4\xfa\xb5\xc9\xad\x43\x7e\x12\x19\xbc\x43\xc6\x93\xf7\x0b\x01\xad\x1c\x47\x0f\x5a\x37\x3d\x6d\x0d\x76\xa5\x13" + - "\xbc\x2a\xa9\x25\x88\x3f\xc9\x4b\x9d\x8e\xbd\xab\x16\x9b\x3c\xbc\x85\x21\x5b\xe8\x99\x19\xda\x62\x41\xf8\x85\x93" + - "\xbb\x9d\x77\x02\x94\x81\x7a\xd8\xad\x60\x0c\xf2\x27\x8c\x05\xd9\x93\x72\xb2\xaa\x45\x63\x60\x8f\x0e\x34\xff\xd9" + - "\xd4\xa7\x29\xab\x4b\x75\x9e\xaf\xaa\x11\x7c\xa5\x6a\xf3\xcf\x15\x00\xca\x66\x35\x23\x62\x20\x11\x68\xf9\x3d\x86" + - "\xde\xa8\x20\x97\x41\x70\x6c\x07\x08\xc1\xce\x0e\x91\x1d\x68\xc2\x0b\x3e\xfe\xa1\x57\x23\x45\x08\x07\x42\xb8\x09" + - "\xb5\x26\x18\x7e\x97\x30\x48\x84\x1f\xbd\x1d\x0c\x0f\xfe\x93\x7a\x7d\x74\x47\xaf\xc1\x29\x30\xea\xb4\x7d\xf6\xef" + - "\xf5\xb9\x5c\x35\xa2\xd3\x74\x47\xfb\x25\xb3\xf7\x36\x01\x81\x0c\xd4\xb4\xb5\x80\x75\x19\xa1\x97\x30\xd6\x8f\xbf" + - "\xc5\x3f\x65\xec\x43\x0f\x76\xc6\xad\x25\x6e\xdc\xa8\xf8\xf1\xc6\x48\x7b\xd4\xde\xe8\x85\x03\x1a\x73\x30\x37\xf1" + - "\xe4\xc0\x87\x9f\x38\x3b\xc1\x80\xab\xb2\xae\xf7\x28\x41\x35\xc0\x17\x42\x5c\xdb\xe4\x7a\x40\xcc\x86\x9c\x07\x6e" + - "\x45\x95\x85\xca\xb3\xe2\x02\x25\x16\x36\x28\x6f\xbc\xdd\x63\x90\x23\x3f\x28\x49\x23\x06\x2a\xd1\x49\xe8\xdd\x41" + - "\x7d\xc5\xf4\x62\x18\x28\xce\xeb\x25\x15\x8f\xb7\x18\xe9\x42\xe2\xc8\x4a\xb4\x47\xfb\xbb\xee\x25\x3f\x63\x98\x1a" + - "\x9d\x9b\xaa\xe1\x30\x45\xec\x37\x82\xc1\x4c\x33\x93\xa7\xcc\x97\xd5\xa6\x91\x9a\xf3\x40\xe1\xbb\xdd\x4a\xa4\x03" + - "\x6f\x63\xea\x15\xfa\x1a\x04\x6f\x87\xb2\xdd\xa3\x96\xc6\xb4\xed\x83\xc0\xe4\x2f\x5b\x80\xdc\xd2\x86\x6e\x23\xec" + - "\x2b\xa4\xa3\x28\x81\x0b\x18\xac\x1f\xb3\xd9\xec\x1a\xf2\x4e\x97\x85\xd2\x76\xe1\x5d\xe0\x5b\x53\x2a\xae\xd5\xbe" + - "\xc9\xa6\x00\x7e\x0d\x20\x95\x9c\x1a\xf6\x3b\x7d\x61\x22\xda\xdc\x94\x0a\x1c\xf6\xb1\xaa\x07\xb5\x8a\x34\xd8\x08" + - "\xe9\x8d\x93\x4c\xb5\x70\x2b\xa9\xd3\x2f\x10\x49\x66\x73\x7f\x43\x16\xf3\xb4\xf4\x36\x6a\xf2\x27\x80\x56\x5c\xf6" + - "\x57\xd3\x0a\x29\x46\xca\x1d\xb3\x1a\x7d\xe1\xe7\x8d\x3f\x37\x85\x1e\x67\xf5\x09\xf7\x0e\xe9\xbe\x08\x49\x76\x83" + - "\x1e\x53\xfa\xb3\x2d\x9f\x04\x0d\x37\x47\x38\xdd\x9d\xd6\xee\x9e\x32\xac\x2a\xf3\xb0\x5d\x61\x9c\x63\x37\x8c\x81" + - "\x0c\x35\x10\x18\x91\xbc\x2d\x6f\x71\x17\xb9\xdd\xf8\x20\xf2\xa8\x39\xb4\x17\x11\x91\xd0\x81\xab\x26\x3d\xe9\xa9" + - "\x05\xef\x2c\x2e\x3e\x8d\x03\x6b\x37\xbd\xef\xa9\xd0\x37\x5f\x84\xd4\xc6\x1d\x6b\x77\xa9\xae\x26\x03\xc5\xec\xe7" + - "\x6f\xa8\xc4\x42\x67\x4d\x54\xc3\x37\x19\x5a\x27\xd7\x59\x33\x2f\x09\x5c\xfe\x41\x61\xd6\x0f\xd4\x85\xb9\x5e\x97" + - "\x55\xca\xbd\xdf\xee\x21\xa8\x07\x29\xef\x1d\x26\x05\xb6\xd9\x8f\x70\x1c\xdb\xdc\xac\xec\x08\x75\x1d\x7b\xf3\x32" + - "\xf4\x06\x40\x8b\x4b\x05\xa2\x68\x5d\x4d\x86\x32\x7c\x0e\xe8\x7b\x2c\x67\xd4\xd5\xe4\xd0\xbd\x24\xd9\x84\x3f\xf4" + - "\x66\x8a\x97\x78\x84\x1c\x43\x43\xce\xbd\xce\xd5\x6f\xa1\xaf\x45\x4a\xa0\x85\xae\x00\xf9\xac\xf6\xde\x4a\x54\x0f" + - "\x40\x5a\xb8\x88\xdf\x72\x6d\x2a\x05\xd1\x2f\xe0\xcc\x53\x19\x73\xa8\x2a\x33\xcd\xad\x78\x05\xa8\x0a\xc8\xc3\x20" + - "\x7c\xf9\xd0\xf5\xb2\xbd\x17\xa9\xcf\x69\xfc\x98\xd3\xf6\x76\xbe\x8c\xf3\x94\xb5\xc9\xbc\x48\xac\x3f\xdc\xf7\x35" + - "\x05\x44\xd5\x59\xe3\x8e\x85\x6c\xf9\xce\x67\x08\x13\x30\x50\x87\xe1\x9a\x91\x91\x4c\x1e\xce\x68\x11\x82\x85\xfe" + - "\x71\xd5\x28\x73\xb5\xcc\xb3\x49\xd6\xe4\xd7\x2e\x76\x32\x4c\x27\xce\xd1\xd5\x1d\x9b\x42\xee\xe2\xae\x5c\xe6\xdd" + - "\xdb\xcb\x09\xc4\x4d\xb6\x30\x35\xe8\x44\xb3\xa9\x77\xa6\xc6\x86\xf8\xca\x83\x1d\x80\xa8\xc3\x38\x12\xa7\x47\x3d" + - "\x0a\xf6\xa4\x7b\xec\x61\xcd\x8b\x72\xdd\xeb\x0b\x78\xb5\xea\x02\xfc\x82\x6a\xcb\xc2\xc3\xee\xc1\xbc\x23\x2d\x99" + - "\xde\x85\x48\xe3\x41\x76\xae\x8f\x74\x96\xb3\xda\x63\x54\xbc\x78\xfb\xfa\x31\x6f\x64\x99\xdb\xda\x6e\x4a\x3b\x69" + - "\x2f\x9f\xbf\x7e\x76\x32\xa9\xb2\x65\xa3\x7e\xd0\xc5\x6c\xa5\x67\x46\x7d\x9b\x15\x29\xc4\x1c\x8c\x46\x6a\xde\x34" + - "\xcb\xf1\x68\xb4\x5e\xaf\x87\xeb\xc7\xc3\xb2\x9a\x8d\xde\xfd\x34\x7a\xb4\xbf\xff\x78\xf4\xf3\x8b\xbd\x17\x6f\x5f" + - "\xef\xfd\x60\x2e\x4d\xbe\xf7\x78\x0f\xdb\xd8\xb3\xaf\xf6\x1f\x3f\x3e\x18\x99\xc9\x42\xef\xd5\x50\xf3\xde\x39\x56" + - "\x38\x9c\x37\x8b\x3c\xa4\x3b\xc2\xb2\x73\x84\x54\xaf\xb5\xcd\xc7\x12\x54\x6c\x00\x45\xda\x5e\x03\x1d\x85\x6e\xf1" + - "\x31\x88\x4b\x83\x9a\x5d\xd2\xf1\x36\x0b\xca\x57\x63\x9b\x9c\x10\xbd\xd8\x7c\x48\xfd\xe9\x08\x20\xfa\x81\xb7\x89" + - "\xee\x0f\x7f\xb9\xdc\x72\xb1\xd8\xe1\x45\x1c\xc1\xbf\xde\xdf\xf6\xe4\xdc\xd5\xe3\xa8\x69\xd1\xe5\x6e\x43\x7b\xd0" + - "\xe7\xae\x45\xf9\xd7\x3b\x7f\xcb\x12\x7f\xca\x28\xba\x3e\x8f\x86\xd3\x55\xa4\x17\x98\x7f\x30\x0b\x77\xd7\xc8\x3f" + - "\x8a\xf3\x49\x14\x05\x34\x4a\x76\x5f\x54\xa3\xdc\xe8\x4b\x07\x7f\xb4\x02\xe5\x38\xbc\x2d\x2f\x4d\x35\xb2\xb7\xaa" + - "\x66\x0f\x94\x3d\x4b\x3a\x50\x78\xaa\xa1\x32\xaf\x5c\x41\x0d\xc5\xc1\xe7\xbb\x1e\x54\x4e\x4f\xe6\x00\x02\xe3\x9b" + - "\x1a\xab\xc4\xd5\x9c\x0c\xf8\x15\xb4\xef\x5e\xad\x1a\x78\x43\x90\x83\xfc\x19\xfd\xe9\x3e\xa4\xbf\xf9\x53\x7e\x0d" + - "\x72\xe1\x47\x99\x65\xca\xae\x99\x15\x02\xaf\x68\x3a\xbb\x1d\x4f\x6c\x29\xcc\xa0\x6d\x27\x32\x14\x39\xa7\xd9\x15" + - "\xca\xc6\xe4\xee\xcd\x4f\xee\x39\xc7\xac\xcd\x02\x13\x60\xb5\x1a\xe2\x4a\xb7\x1a\xe9\xab\x36\x60\x89\x0a\x99\x65" + - "\x2f\x1d\x08\xcb\x58\x80\x83\x83\x56\xeb\xc8\x13\xe7\x30\x94\x02\x61\x0a\xc5\xa2\x4e\xd8\x65\x44\x44\xee\x72\x8b" + - "\x59\x1d\x84\xb6\x90\x82\x87\x6b\x7b\xf3\xed\x58\xbd\x29\x23\x43\x1d\x49\x53\xd0\x0a\x68\xc3\x47\xd0\x18\x39\x43" + - "\xb3\xf0\x89\xaa\x96\x7b\x5e\xad\xcd\x2d\xde\xdc\xa8\x1e\xff\x06\xcb\x3f\xd6\x2a\xbc\x71\x3d\x12\x2e\xcb\x92\x5c" + - "\xbe\xdf\x72\x15\x77\x11\x9b\xb1\xcf\xd0\xa1\x93\x55\x83\xd7\x1c\x68\x4e\x1e\x42\x78\xe7\x0a\x1f\xca\xc3\x8e\xca" + - "\xa7\xd9\x95\x0c\xec\x20\xf6\xb0\x32\x42\x29\x7e\xe8\xc0\xec\xfd\xe1\x4a\x98\x51\x4b\x30\x0c\x12\x4e\x10\xa8\x42" + - "\xd8\x40\xd8\x21\xcd\xb2\x9a\x6f\x40\xba\xbf\x7b\x9f\x51\xa8\x72\x37\xcc\x67\xb8\x9d\xe1\xac\x29\x52\x5e\x39\xc5" + - "\xce\x40\xa1\x42\xc7\x6b\x4d\xd4\x6d\x87\x83\x95\xa0\x08\x87\xe8\x72\x10\x4f\xf4\xb2\xc1\x70\x6c\xde\x45\x4e\x5c" + - "\x23\xf6\x13\x35\xb8\x75\xb9\x30\x65\x61\xc0\x87\xb0\x76\xf1\x9f\xdc\xf4\xbd\x00\x0c\xb2\x0a\x25\x8f\x50\x94\x0e" + - "\xcf\x28\x49\x6c\xa0\x8e\x1e\x44\x9a\x86\x8d\x3e\xb7\x21\x94\x04\x7b\xa6\x76\x1f\x7e\x3b\x7e\x77\xf6\xb7\x00\x88" + - "\xa8\x4b\xf1\x03\xc9\x9d\xc0\x44\x87\x97\x41\x6c\xcd\x13\x87\x7a\x0b\x41\xd2\xc0\x57\xa5\x9d\x8f\x01\x2c\x99\x30" + - "\xe9\x11\xfa\x8f\xfb\x4a\x40\xa0\x97\x93\x0e\xa4\x22\x5c\x37\x87\x9f\xd1\x85\x9a\xb1\xb9\xd9\x01\xe6\x58\xc4\x96" + - "\xc8\x80\xb6\x4b\x60\x05\x5e\xed\xc6\x41\xf0\xff\x4b\x33\xa1\xf6\xd4\xc1\xa7\xcd\x46\xa7\x88\x79\xdb\x84\x74\x04" + - "\xaa\x77\xac\x40\x94\x78\xe7\xb6\xe9\xf3\x1d\xeb\x50\xe2\xc0\x75\xdb\x8f\x72\xe0\x06\xf9\x2d\xee\x7d\xb6\x15\x70" + - "\x1a\x0c\x00\xe4\x51\x50\x30\x52\x71\x5a\x0c\xd4\xe8\xe1\xab\x37\xef\x5e\xfe\xf4\xe6\xd9\x0f\x0f\x47\x96\xb3\x97" + - "\x9e\x73\x76\xcc\xdf\x15\x83\x28\x52\x05\x01\x39\x28\xc9\xa6\x56\x0b\xbd\x54\x84\x7e\x5f\x8f\x5a\x0e\x2b\x02\x1b" + - "\xbf\xee\x4e\x0a\x39\x1a\x31\x66\xce\x1e\x07\x07\x87\xfd\x54\x32\x82\x0c\xab\x73\xde\x4e\x9d\x70\xfb\x5d\x55\x8a" + - "\x8a\x82\x10\x4f\x01\xc6\x41\x53\x2d\x20\x49\x63\x78\x47\xf8\x6f\x08\x50\xd3\x78\xe8\x24\xa7\x60\xf5\xba\xb4\x78" + - "\xc2\x19\x9b\x06\x6c\x74\x03\x9c\xee\x0e\xea\x4f\x8e\xe6\x61\x80\x79\x10\x91\xba\xb3\x83\x19\x81\x42\xbf\x00\x3f" + - "\xee\x01\xa4\xf7\xc1\xfe\x16\x56\x36\x0b\xc6\x48\x13\xb0\x71\xa4\xb4\x53\x7d\xe2\xa1\xb0\x99\xce\x95\xe8\xcc\xb5" + - "\x1d\xf4\xc8\x4f\x86\xeb\x1b\x76\x4e\x24\xf8\xeb\xcc\x00\x1d\x9d\x1c\x59\x27\xef\xe3\x3b\xea\xfb\x7d\x4b\xec\xb5" + - "\x62\x94\x75\x29\x74\xc6\x85\x36\x42\xa1\x3f\x9c\xb2\xed\x69\x11\x5b\xa2\x3b\x57\x14\xa0\xca\x65\xae\xf4\x2d\x3c" + - "\x70\xf6\xe2\xa2\x0c\x85\xd3\xe2\xb6\x5b\x0c\x1c\x50\x0a\x44\xcf\xe3\xc4\x9f\xb5\x71\x91\x38\x58\x9a\x19\x1e\x84" + - "\x66\x2e\xa6\xa5\xbc\x01\x7b\xfd\x61\x39\x9d\xf6\x02\x1f\x5c\xd7\x69\xec\xcd\x1d\xdc\x0c\x41\x1f\x51\x44\x06\xa8" + - "\x5a\x01\x54\xa7\x2e\x11\xc7\x15\x51\x01\x08\x43\x06\x59\x7f\xac\x97\xc6\xc7\xe8\x72\xd4\x18\xfc\x65\xb9\xb8\xe0" + - "\x41\x04\xc2\x2b\xb5\x97\xad\x3c\x2c\xed\xdb\x24\xb8\x93\x21\x7b\x85\x4f\xc5\x52\x23\x15\x8c\xb1\xa5\xb1\x7e\x9f" + - "\x4f\xa5\x2c\x5a\x9a\xf2\x4e\x7a\xda\x95\xad\xe5\x0e\x02\x7c\x20\xd2\xb6\x94\xd3\xe9\xad\xcd\xf8\x06\x02\xd0\xeb" + - "\x81\x8f\x9c\x72\x67\x13\x22\x01\x11\x57\x2c\x12\xbb\xdd\x73\xe1\x1a\x29\x09\x08\x6f\x32\xc5\xaa\xe3\x28\xbc\x06" + - "\x4a\x4a\x81\x21\xaa\xed\x50\x4c\x3a\xf5\x25\x8e\xa5\xc1\x5d\x17\x89\x1e\x12\xc0\xa0\xcb\x4f\x7f\x17\xd0\xc8\x76" + - "\x3b\x63\x09\xc6\x1d\x1f\xc4\xa2\xcd\x30\x82\xec\x6c\xf1\xed\xf0\x98\xb6\x75\xc7\xb9\xfd\x57\x6e\x34\xf2\x24\x39" + - "\xf5\x8b\x78\xc6\x64\xf9\xee\x6b\xc4\x1e\xcc\xf8\x1e\x09\x6e\x90\x3b\x2f\x8f\x18\x56\xd1\x13\x33\x0a\x28\x6e\x51" + - "\x70\xde\x7c\x5d\xa3\xb1\xc3\x98\x16\x67\x9b\xef\x95\xcd\x17\xca\xbf\x42\x51\x3b\x4f\xf7\xed\x87\x3b\x4c\x42\x29" + - "\xce\xf7\xc6\x93\xdd\x8d\x19\xd4\xb4\xd2\x81\xfd\xce\x8e\x38\x63\x8d\xaf\x89\x9d\xa3\x63\xd2\x42\x45\x29\x80\xf7" + - "\xee\xa4\x64\x32\x4b\xf3\xfe\x99\x3f\xf4\x41\x1a\xcc\xd0\x8a\x7a\x4b\x9f\xc8\x22\xe3\xb9\xd9\x8f\x51\xb6\x4e\xca" + - "\xe6\x70\x35\x6f\x16\xf9\x3b\x3d\x53\x47\x6a\xf4\xb4\x77\xbc\xad\x2b\xa3\x6f\xce\xab\x9b\x49\x99\xdf\x98\xc5\xb9" + - "\x49\x6f\xe6\xd5\x4d\xb6\x98\xdd\x80\xd5\xf9\x26\xcf\x8a\x8b\x9b\x85\x69\xf4\x0d\xa4\xab\xee\xf7\x7a\xa7\xef\xd7" + - "\xe3\xb3\xdd\xfe\xe9\xdf\xbf\x39\x7b\xd8\x7f\x3f\xfa\x66\x34\xcb\x30\x4b\x83\x9e\xbd\xc1\x3c\xe9\xa3\xa7\x5c\x08" + - "\xf3\x37\xd8\x16\xe1\xf1\xcd\xce\xfd\xe3\xf7\xeb\xdd\x43\x7c\x5c\x94\xaf\x8a\xc2\xf8\xb7\xbd\xe3\x31\x6a\x5e\x6f" + - "\xea\xe6\x3a\x37\xd0\x74\x7f\x94\x51\x16\x2c\x32\xc3\x1f\xf9\xc4\x27\x6c\xba\x07\x9d\x73\x35\x71\xf9\x34\x46\xf4" + - "\xf3\x7d\xfd\xb0\x77\x3c\x3e\xfd\xfb\xd1\xd9\xcd\xd1\xfb\xfa\x21\x27\x06\x19\x52\x9d\x15\x36\x46\xf0\x0f\xa3\xbf" + - "\xff\xe1\xe6\xfd\xa8\x77\x3c\xfe\x45\x5f\xea\x1b\x33\x59\xe8\x3e\xbe\x6f\x15\x7e\xad\x6b\x6a\xe7\xef\x76\xb6\xdf" + - "\x8f\x7a\xc3\x87\x34\xd0\x49\x6e\x74\x41\x7a\x69\xfb\xfe\x7d\xfd\xf0\xe9\x76\xef\x78\xfc\xfe\xf4\xf9\x8b\x67\xef" + - "\x9e\xbd\x3f\xbd\xd9\xdb\xeb\xdf\xd8\x07\x67\xef\xcf\xec\xef\x6f\xde\xd7\x0f\xff\x30\x9a\x39\xa7\xeb\x9f\x5d\xea" + - "\x5e\x35\xc9\x4b\x0c\x8c\xb4\xff\xd5\x33\xc0\x18\x21\xf1\x5e\xfd\x15\xd2\x8d\x60\x24\x01\x84\x93\xac\x2b\xbd\x7c" + - "\xad\x97\x2e\x2d\x43\x94\xb0\x44\x7d\x6d\x9f\x95\x4b\xd4\x5b\x9e\xaa\x83\x81\x4a\x9e\xe2\x49\x72\x98\xe6\x47\x0f" + - "\xf8\xd7\x83\x6f\x12\xfb\x7e\x84\x05\xbe\x49\x00\xf6\x0a\x95\x86\x46\xa7\xee\x7b\xf0\xb9\xa3\xa2\xf4\x9b\x00\xb2" + - "\x26\x65\x6e\x4b\x3d\xf2\xa5\x9e\x4e\xca\x7c\x56\x95\xab\x25\x95\x77\x7f\xc6\x9f\x36\x55\xfc\x65\x73\x5e\xa6\xd7" + - "\xdc\x0c\xfc\x6e\x7d\x03\x7d\x7a\xdc\xfa\xe6\x69\x53\xf1\x77\xd5\x37\xdd\x1f\xdb\xcf\xbd\x2b\xc3\xa9\xda\x1f\xa8" + - "\xc4\x7e\x92\xa8\x33\x97\x43\xa9\x3d\x95\x34\xdb\xc3\x72\xd9\xc0\x28\xd4\x91\x12\x8f\x32\xf2\x2b\xe6\x47\x0d\xb9" + - "\xe1\xba\xbf\xa7\x65\xd9\x88\xbf\x79\x2e\xe4\x23\x8d\xd9\x24\xc5\x47\x76\xea\x0f\x45\xa5\x73\xf9\x32\x6d\x75\xf4" + - "\x60\x78\xa5\x26\xe5\x62\xa9\x9b\xec\x3c\xcb\xb3\xe6\x1a\x5e\xbf\xd6\x45\xb6\x5c\xe5\x84\x9b\x83\x01\xf2\x95\xf9" + - "\xe7\x2a\xab\x20\x5d\x25\xf4\x54\xe4\x39\x59\xb8\xe2\x65\x81\xf7\xbd\x4b\x07\x5e\x16\x8d\x67\x60\x37\x7a\x7a\x20" + - "\xc6\x1b\x34\x94\x38\x9c\xc5\x56\x31\xaa\xcc\xbb\x98\x59\x59\xf0\xe0\x40\x1d\xbb\x66\xc6\xae\x0c\xc4\xa0\x42\x52" + - "\x1c\x5b\x71\x05\x00\x69\xe4\x5d\x98\x9b\xc5\x70\x66\xd8\x05\xba\xfe\xf6\xfa\x1d\x12\xa4\x5e\x02\xe3\x4a\xfa\xa7" + - "\xfb\x67\x6c\x65\x44\x54\x67\x99\x08\xa9\x0d\x64\x12\x65\x9b\xe2\x5a\x18\x48\x89\xa2\x4b\x3f\xd2\xcc\xff\x64\x96" + - "\xb9\x9e\x98\x51\x65\x30\xe3\xb4\xcb\xb3\xe7\x13\x74\xdb\x2b\x1a\x69\x83\x8b\x84\xb2\xbc\x43\xad\xa7\x84\x97\x20" + - "\xa6\x5b\xac\x02\x05\x40\x21\x59\x09\x6e\x07\xe8\x33\x43\x95\xf2\xf8\x7d\x02\x28\xc4\xa2\xc3\xb4\xd5\x56\xec\x03" + - "\x3c\xa8\x91\x65\xbc\xdc\x87\x87\x7e\xf5\xfc\x78\x44\x5a\x1c\x18\x4b\x47\xcb\xf6\xfa\x42\x78\xb3\x23\xd5\x22\x8d" + - "\x04\x65\xeb\x7b\x47\x9a\x13\x1f\x9c\x13\xf8\x01\xd0\x00\xe0\xc5\xa9\x3a\x40\xa7\x4c\x29\x28\x0a\x6f\x81\xd6\xe0" + - "\xbc\x01\xb4\x35\x0c\xda\xf1\xd5\x05\xcd\x3a\x58\x12\xe7\xfa\x12\x1c\xfa\x19\xd7\xc0\x98\x42\x99\x4b\x9d\xaf\x34" + - "\x18\xbe\x7d\x8a\x1f\xd3\xfc\x11\xa0\x24\x5e\x5e\x6a\x72\xb6\xa8\x07\xaa\x32\x53\xde\x5e\x62\x22\x20\xa2\x0c\x28" + - "\x51\x4e\xd0\x0d\x02\x3b\xf5\xde\x67\x2e\xb2\x2e\x53\x4f\x55\x1e\x84\x99\x79\xcd\x51\x6d\x9a\x9e\xdb\x99\x9c\xf1" + - "\x2f\x99\xb9\x2e\x24\x03\xb5\x2d\x5b\x0f\x92\xb7\xc2\xc1\x14\x6f\x3b\x3e\x47\x56\xcf\x19\x78\xee\xc9\x74\x46\x90" + - "\x79\xea\x79\xb9\xbc\x96\xfe\x0b\xa9\xa9\x1b\x39\xc6\x81\xca\xd9\xdf\x63\x69\x5b\x7e\x6b\x4f\x20\xfc\x7a\xbe\xaa" + - "\x06\x6a\xe5\x9e\xad\xdc\x33\xd4\x5f\x8b\xb5\xb7\x75\x46\xa7\x3c\xe4\xca\x02\x73\xf6\xc1\x50\xd9\x4e\x29\x3b\x44" + - "\xdd\x60\x42\x7f\xf2\xfe\xac\x25\x38\xb5\x69\x26\x43\xd7\x42\x1b\x7d\xba\xae\x26\xde\x73\x8e\xbb\xde\xa9\x61\x84" + - "\x92\x87\xae\xd8\x73\x08\x7d\x0c\x97\x08\x86\xe0\x67\x40\x09\x28\xb7\x5a\x1d\xb9\xe7\x43\x39\x74\xe1\x2d\x56\xc7" + - "\x60\x99\xdc\x50\x00\x96\xe9\x1e\xba\x7a\x7d\xce\x85\xdb\x41\x95\x45\x84\xe3\x40\xe5\x2d\xc4\x61\xde\x95\x1d\x3b" + - "\xb1\x53\xb8\xc6\xc1\x36\x1e\xea\xde\xd5\x04\x3b\xac\x53\xa7\x29\x57\xf0\x11\xad\xe0\xaa\x36\x15\x4c\x64\xb0\x4c" + - "\x90\x6c\xbe\x7b\x99\x56\xd1\x32\x41\xd1\xf6\x32\xad\xfc\x32\x45\x4e\x12\xbf\x7d\xf4\x5b\xd2\x29\x6e\xa3\xbc\xfc" + - "\x38\x3a\x57\x47\xf7\xd9\xb0\x04\x35\xcf\xe9\x8e\xba\xb2\xb3\xa1\x67\xe2\x58\xa0\xdd\x88\x5e\x76\xde\x3e\x7c\x8b" + - "\x6d\x78\xdd\x83\x0a\x6f\x6e\x54\xf2\xd0\x43\xf4\xf1\x07\xff\xb4\x63\x3a\x21\x81\xe7\x19\x44\x77\x6d\x7a\xd5\x59" + - "\x0f\x63\x83\xb2\xc8\x63\x99\xfe\xc0\x91\xc6\xca\x8e\x7a\xd6\xe9\x7a\x1a\x0d\xf8\x58\xdc\xdc\x0b\x53\xcd\x4c\x4f" + - "\x9d\x72\x19\x4b\x6b\x2a\xf0\x5e\x1f\xd3\x51\x16\x04\x58\xb2\x4e\xdf\x1c\x59\xee\xc9\xcd\xed\x34\xbb\x7a\x65\x65" + - "\x8c\x6e\x8a\xc3\x5d\xb1\x7b\x80\xe9\x86\xfd\x7b\xd8\x94\x3f\x94\x6b\x53\x3d\xd7\xb5\x11\x6e\x28\xdf\xe9\x2c\x07" + - "\x1e\x79\x69\xaa\x3a\xab\x9b\x20\xaf\x23\xba\xee\x62\x92\x5c\x48\xe9\xe7\x7c\x7e\x21\x1f\xb7\x4e\xb3\x92\x82\x5d" + - "\x1c\x25\xf1\xcd\x53\x32\xe2\x15\xe2\x4c\x86\xd9\x34\x39\xe9\x87\xf7\xde\x62\xca\x6e\xbb\xec\x45\x12\x5b\x20\xce" + - "\x4b\xe8\x7a\xec\x24\x52\x43\xd2\xad\x49\x15\xf2\x91\x9c\x81\x81\xdd\x21\xdd\x6b\xf2\x45\x9e\x1b\xa4\xde\xa0\x8b" + - "\x83\x2f\x6a\x7f\x77\x6e\x1e\xc6\xcd\x4d\xf4\x9c\x13\x15\x26\x41\xf7\x83\xb4\x88\x81\xd7\x16\x27\x22\x74\xe7\xa5" + - "\x9d\xcd\x05\xe6\xb9\x9d\xc0\xc0\x9e\xb6\x67\x05\xda\xa8\x6a\xbb\xe6\x66\xf9\x42\x3e\x8a\xc2\xfd\xf3\x81\x6d\xf6" + - "\xa5\x4b\xe4\x6b\xfb\xe5\xfe\xc2\xb3\x42\x79\x22\x81\x49\x68\xe5\x50\xa4\x44\xc3\xc5\x8f\x7a\x26\x3c\x44\x3f\x31" + - "\x87\x6a\x87\x1c\x85\x3b\x98\x7c\x88\xaf\x00\xb2\x12\x62\xf5\xeb\x7a\x25\xb0\x72\xb7\x37\xa4\x7a\xdc\xd9\xe9\x04" + - "\xd2\x3d\xe8\x06\xd2\x3d\x38\x10\xd0\xe4\x1e\x82\xea\xaf\xaf\x7f\x78\x51\x4e\x3a\x20\xa8\x50\x7c\x34\xf5\x64\x6e" + - "\xd6\xea\x24\xfb\xf5\xd7\xdc\x28\xc0\xc4\x82\x54\xf5\xa6\x9a\x96\xd5\x02\xc0\x08\x2a\xa3\xeb\xb2\xa8\xc7\xec\x25" + - "\xf5\x4b\x6d\xdf\x0e\x27\xe5\x62\x34\x33\x8d\xce\xf3\xbd\xcb\x7a\xaf\x86\x0a\x46\x8f\xe8\xb6\xf2\xd3\xae\x8e\x3c" + - "\x51\xcc\x85\xdd\x43\xac\x93\x28\x12\x4c\x66\xfb\x7e\x12\x1f\xdd\x7a\x39\x05\xa4\x22\x62\x73\x64\xe7\x82\x7b\x29" + - "\x86\xc4\xb0\x57\x91\xf3\xb8\xab\x3d\x56\x93\x0b\x26\xa5\xd3\x06\xc3\x0a\xac\x35\xad\xed\xc9\xfc\xcc\x86\xdd\x1b" + - "\xcf\x86\xfc\xeb\xe6\xa6\x3d\x39\x5b\xed\x39\x0e\xfe\x14\xdf\xf8\x39\xdf\x70\xe5\x7f\xea\x94\x6e\x75\xb0\x7d\x9f" + - "\x3a\xb3\x7c\xe3\x07\xd6\x9c\xb8\x3e\x92\x14\xf3\xd8\x36\xe6\x57\xe4\xc7\xca\xd4\xa6\xba\x34\x4e\x2c\x42\x46\xdc" + - "\x12\xbe\x79\x66\x45\x8f\x6b\xa6\x45\x9b\x36\xdf\x40\x25\xf8\x2d\x07\x11\x38\x3e\x33\x9a\x03\xf5\x8d\x80\x70\x8e" + - "\x98\xfb\x80\xa8\xa8\x6d\xa2\x16\x3b\x3b\xc1\x3a\xc9\x96\x42\x88\x13\x10\xfe\x1c\x05\xa7\xfb\xa5\x36\x8d\x50\x36" + - "\xc2\x43\xa1\xa8\x3c\x5f\x65\x79\xca\xe9\x92\x63\x22\x59\x0f\xfc\xe5\x4b\x92\x0b\xab\x3d\x85\xa7\x17\x2b\x10\x09" + - "\xe1\xbc\xd1\xb3\x01\xe8\x03\x06\xce\x4c\x34\x50\x04\x8b\x22\x32\x37\x33\xfb\x70\x6b\xe2\xe6\x2d\xcc\x5d\xe9\x01" + - "\x54\xbc\x80\xb3\x41\xc2\xb9\x45\xc4\xd9\x12\x58\xe4\x21\x7c\x86\xd7\x75\x12\xf9\x03\xaa\xb7\x1f\xc5\x71\x3c\x4b" + - "\x53\xca\xa5\xc9\x90\x0a\xf7\xbc\xdd\x9f\x88\xa2\xbd\x7a\x1d\x41\xec\x54\xe4\x87\x84\xfc\xbf\x1b\x0c\xe9\xf3\xaf" + - "\x24\x67\xa3\xce\xcd\x44\xaf\x6a\xa3\x96\xab\x9a\x73\x06\x7e\x18\x28\x5d\x55\xfa\x3a\xcf\x2e\x4c\x5f\x35\xf3\xaa" + - "\x5c\xd7\x21\xdb\x4c\x4c\x11\x74\x75\x10\x51\xf3\x63\xc6\x92\x3f\x53\xe3\x88\x22\x22\x61\x2a\x2e\x4d\xd5\x00\x12" + - "\x0c\x28\x43\xb3\xa2\x29\x65\x80\xde\x3d\xe9\x75\x40\x6e\x52\xb6\x20\x71\x1f\xf2\x26\x80\x2e\x41\x27\x18\x24\x36" + - "\x58\xf1\x77\xe6\xaa\xc1\xfb\x91\x3f\xea\xea\x88\xef\xc4\x8b\xb7\xaf\x3d\x0e\x7c\xcb\xf1\xc1\x65\x2d\xb1\x2b\xd8" + - "\x9d\xe8\x3b\x6c\xde\xe9\x52\xd2\xec\x32\x91\x8d\x23\x9c\x59\x6d\xaa\x0c\x43\x74\xb5\xe5\x70\x8a\x54\x57\xa9\xaa" + - "\xcc\xd2\x92\x89\xa2\xf1\x79\x98\xb6\xb6\x80\x95\x55\x3d\xc5\x4a\x67\xa1\x72\xf0\x69\x79\x50\x8f\xa7\xfa\xa0\x54" + - "\x68\xb1\x8d\x50\x8f\x3d\x31\x5e\x91\x76\x0a\xcc\x2e\xa0\x48\xb1\x6a\x8d\x95\x83\x87\x7e\xc8\x41\xc2\x67\x5b\x0e" + - "\xea\x67\xad\x4a\x85\x7a\xa0\x9e\x72\x8a\xf6\x81\x4a\x9e\xfe\xe1\xe0\x9b\xa7\xa3\x3f\x3c\xfa\x26\x01\xff\x19\xfc" + - "\xe8\x91\x44\x92\xc1\xf1\x4f\x10\xe3\xba\x2a\x57\xb3\x39\x94\xb2\xcc\x2c\x5f\x4b\x08\x7d\x4f\x8a\x30\xde\x7c\xae" + - "\x0b\xfb\xca\xe1\xdc\x74\xe6\x6a\x11\xab\xe5\x13\x4b\x77\xa2\x44\xfe\x2f\x1e\x13\xdb\x99\x89\xed\xc8\x1b\x38\xe1" + - "\xe1\x7e\xf8\xc9\x2c\xcc\xe2\x9c\x32\xb4\x37\xe5\x72\x2f\x37\x97\x26\x67\xf2\x46\x46\x3e\x1e\x96\xdb\x7d\x5e\x41" + - "\x18\x54\xf6\x5d\x76\x65\x6a\x75\xff\xe0\xd1\xe3\x27\x5f\x74\x0c\xf5\x67\x73\x7e\x91\x35\x03\xf5\xea\xa5\x58\x67" + - "\xbb\x71\x9f\x93\x06\xf2\x48\x25\x49\xa7\xb4\x7b\x2f\xc8\xaa\x41\x6b\x86\xbc\x05\xf7\x09\x08\x24\xf7\xaf\xa3\xd2" + - "\x7b\xdd\x20\x79\x44\x38\x61\xaa\x1c\x34\x5e\xc0\xee\xdd\x7f\xb2\xff\xd5\x97\x6a\x4f\xbd\x9a\x12\x0f\x03\xbe\x83" + - "\xf6\x3a\xcb\x0a\xbc\x46\x9d\xa2\x51\x93\x4a\xb2\xd6\x0b\x82\x30\xa4\xc4\xb5\x5c\x17\xe4\xe1\xa5\xe2\x80\x4d\x5b" + - "\x94\x00\xbc\xaa\x8b\x6b\xc8\xd7\xe2\x49\xb6\xbf\x8a\x04\x7e\x6a\x41\xc0\xe9\x78\x25\xc9\xdb\x6a\xfb\xe8\x48\xed" + - "\x1d\x08\x40\xec\xce\x14\x4d\xce\xb7\xe1\x5f\x61\xd2\xe1\x9e\x58\x22\x40\x7c\x19\x4c\x3b\xed\x0e\xbe\xc8\xbb\x69" + - "\x14\xd6\x15\xb1\x12\x5c\xef\xa7\xf1\x28\x04\x57\xc5\x83\xf0\x6c\x60\xc8\x69\x00\x86\x69\x0b\x45\xe2\x39\xf8\x4c" + - "\x1a\x65\x69\xd8\x0a\xb5\xf2\x62\xb6\x49\x77\xe9\x1d\x1e\x3d\x92\x61\x6b\xaf\x34\x8b\xa5\x03\x2e\xf4\x27\x1f\x11" + - "\xec\xbc\x96\x56\x5c\x1b\x28\xb5\x52\xaa\x30\x49\x2c\xa8\x59\xba\x44\x02\x46\xf5\x4e\x78\x55\x9e\x65\xc1\xf0\x80" + - "\x61\xec\x05\x28\xf0\x22\x66\x47\xf2\x33\x81\x21\x13\xb4\x4e\x17\xe6\xfa\x53\x00\x46\x05\x9b\x12\x31\x24\xbd\x16" + - "\xfb\xd1\x0f\x63\x35\x43\x66\x45\x72\x15\x9b\x10\x8f\xed\xd8\x2f\xcc\xb5\x43\xe9\xf5\x1a\x42\x17\xea\x12\x7a\x27" + - "\xda\xc2\x56\xf4\x4b\xe3\x0c\x79\x13\x3d\x99\x9b\x53\x78\xdf\x5e\xb0\x54\x64\x83\x16\x0b\x13\x2a\x00\x37\x14\x0a" + - "\xc0\xfc\x04\x96\xb1\x2f\x70\x67\xfa\x35\x41\x8b\x29\xcb\x2f\xe6\xb9\xd6\xaa\x9e\x97\x55\x33\x59\x89\x80\xcf\x8e" + - "\xba\x1e\xd4\xaa\xbc\x34\xd5\xdc\xe8\xd4\xd5\x12\x71\x0f\x9f\x90\xf6\x28\xed\x48\x79\x24\x01\xc4\x3a\xe1\xbf\xba" + - "\xe7\x57\x8e\x5e\xe4\xba\xd6\xc5\xb5\x80\xed\xfa\x07\xe9\x9a\xff\xc1\xda\xca\xad\x2d\xaf\xab\xed\xae\x77\xf3\xa1" + - "\xb8\xa5\x99\x55\x6d\x2a\xd1\x86\x6c\x00\xf4\x93\xd4\x80\xd8\x5f\xf0\xd8\x87\x52\x9d\x75\x58\xf8\xbb\xfc\x47\xb7" + - "\x30\x8b\xad\x3f\x73\x10\x9e\x17\xb9\x42\xb0\x62\x15\x7d\x2d\x36\x94\xe5\xc2\x97\x2e\x94\xce\xab\x11\x09\x43\x8e" + - "\xb9\x71\x73\x45\x18\xc2\x4e\x11\x89\x6e\x30\xe0\xd6\xd6\xeb\x6f\xf0\xba\x90\xd1\xf2\x6d\xf5\x48\xc7\xe3\x0d\xcf" + - "\xbf\x0e\x78\x1e\x08\x6d\x0b\xae\xdc\x4b\xd6\x5d\xc9\x55\x23\x81\x8e\xe3\x71\xa1\x8c\x70\x91\x73\xa0\x6c\x82\xa4" + - "\xe1\x15\xd2\x76\x79\x96\xfe\x25\x69\xb9\x00\x93\xab\xc0\x5f\x1e\x44\x04\x30\xf2\xc5\xfc\x0f\x8e\xde\x52\xd4\xc6" + - "\x63\xe2\xb6\x4d\xb9\x04\xda\x29\x69\x3b\x05\x76\x74\x5c\x8f\x52\x80\x97\xd3\x40\x99\x59\xfe\xdf\x39\x0f\x59\x51" + - "\x9b\xaa\xf9\x16\xa0\x08\x1c\x65\xc2\x57\x9e\xcf\xdc\x3c\x37\x88\x61\xf0\x3f\x31\x35\x5d\xe9\x41\xa2\x17\xdd\x9d" + - "\xf7\x8e\x4b\x1d\xfd\x85\x3c\xfd\xff\x77\xeb\xee\xb0\x30\x57\xcd\x49\x86\xb1\xcc\x1b\xbb\xde\x4e\x98\xeb\x3d\xed" + - "\x2e\x48\x4d\xa7\x46\x0f\xd5\xab\xa2\x31\x55\xa1\x73\xf0\x71\x85\xd4\x28\x0f\x47\x2d\x95\x8a\xd3\x5b\xd4\xd2\xb7" + - "\xfa\x58\x39\xbc\x4b\x44\xa8\x11\xbe\x7c\x44\xec\x44\x34\xc3\xdd\xcc\x48\x06\xac\x08\xa2\xf5\xb7\x99\x90\x6d\xd7" + - "\xeb\x9d\x9d\x4e\x9d\x71\x1c\x01\xe3\x58\xac\x5e\xa4\x5f\x8c\x39\x4e\x1f\xa1\xdf\xb5\x2c\xc4\xb1\xf8\xb6\x7f\x07" + - "\x3b\x2e\x28\x6f\xc4\xf8\xde\xa1\x49\x73\x84\x38\xea\x16\x71\x06\x1b\x09\x51\xc0\x76\xb2\xbb\x24\xed\x08\xb8\x6d" + - "\x36\x04\x69\xba\x45\xbe\x6d\x95\xc0\x2f\xef\xf6\x45\xda\xb8\x2e\x4e\xa5\xc2\xf8\x43\x0b\xb3\x28\xab\x6b\x95\x1b" + - "\x4d\x00\x2a\x77\x2c\x9b\xc3\x3e\x08\x35\x34\x24\x66\x86\xec\x84\x50\xd0\x20\x4f\xdf\x29\xb7\xde\x3d\x63\x2d\x93" + - "\xcd\xa7\x1a\x6b\x42\x15\xf9\x51\xa4\x32\x77\xb9\xb7\x68\x48\xe3\xf0\x3d\xf4\xae\x5d\xf5\x51\x47\x73\xbe\xa6\xb0" + - "\x85\x71\xbb\xec\x61\x6b\xa0\xc3\x85\x5e\xb6\xb9\x8e\xd0\x75\x09\x66\x80\x2f\x84\xbb\x47\xdf\xf6\x40\x9d\x37\x8b" + - "\xfc\x3f\xc3\x6e\xc5\x0e\xa2\x6a\x9f\xe1\xcd\x19\x9f\xc4\x2b\x65\x41\x2b\x0b\x63\x0c\x94\xb2\xb8\x47\xbb\x18\xb6" + - "\xbb\x48\x8a\xf0\xa5\xf1\xda\xae\x96\xdc\x7a\x62\x0c\x65\x93\x9a\xe8\x42\x35\x98\x17\xc3\x49\x07\xba\x48\x31\x31" + - "\x20\x20\x17\x72\x25\xe2\x62\x40\xa7\x65\xdf\x3d\x17\x73\xb2\xb3\xa3\xb6\xa5\x73\x28\xc9\xab\x3c\x3f\xce\x24\xe6" + - "\xb4\x76\x2d\x3d\x20\x17\xbd\x5b\x11\xc8\x82\x01\xb3\x0a\x68\xea\x44\x10\x8b\x3b\x55\x79\xee\x64\x36\xd5\xb5\xa3" + - "\x7c\xb7\xa8\xc2\xbd\x36\x1c\x97\x34\x8b\x92\x61\x84\x87\x9c\x94\x31\xa4\xfd\xa6\x2c\x78\x1b\x88\xc9\x5d\xf4\x28" + - "\x94\xb7\x3e\x89\xe6\x6c\xf9\x0e\x07\x1a\xcf\x80\x7f\x96\x12\x18\xfd\xa2\x11\xee\x4b\xb2\xf5\x6a\x4a\x01\x23\xbe" + - "\x22\x54\x0e\x42\xb4\xcb\x95\x95\xb3\x01\x20\x68\xc5\xa9\x40\x74\x9e\x03\x34\x91\x4c\x8d\xf3\x51\x4d\x30\x03\x3b" + - "\x1c\x92\x8f\xdd\x77\x5a\xc4\x5f\xb0\xc8\x81\x0c\xad\xdb\x18\x01\xde\xd4\xef\xe0\xf9\x69\x47\xfc\x9c\x35\xf3\xee" + - "\x9b\x45\x57\x33\x75\xe4\xeb\x60\xb5\xec\x3d\x91\x3a\x06\xfd\x12\x74\x31\x33\xe0\x50\x66\x2b\x04\x74\x0e\x3d\x99" + - "\x3b\x87\x0a\x5e\x7a\x97\x2c\xa9\x30\x6b\xa9\xf9\xfd\xdd\xac\x18\xf6\x2b\x62\xb9\x5c\x6e\x8c\x8d\xbb\x82\xf8\x9a" + - "\x7e\x40\x50\x6c\x5d\x6e\x96\x75\x35\xe3\x73\x22\x6e\xe9\x4d\x8c\x26\xcd\xc3\x77\x65\x35\x31\x2e\x5f\x33\x06\x8a" + - "\x57\x46\xad\x35\xa4\x20\x16\x63\xe5\xb4\x74\xa0\x4e\xc5\xa8\x28\x37\xd6\xbe\x24\xa9\x15\x38\xb1\xf4\x6c\x6f\x68" + - "\xd9\x6e\x6e\xec\x53\x77\x18\x18\xed\x92\x71\x29\x49\xe3\x21\x17\x17\x53\xdd\x75\xb1\x90\x5d\xa1\x03\xac\x32\xe9" + - "\xca\x47\xcf\x15\xd2\x02\xc9\x2a\x75\x35\xab\x07\x10\x4f\x05\xfb\x5b\x86\x52\x7f\x97\xeb\xa6\x31\x05\x5c\xee\x85" + - "\xa9\x1b\x93\xa2\x32\x1d\x8e\x38\xa5\xf4\x41\xb4\x4d\x0e\xe4\x3a\x3d\x8b\xd2\x55\xd8\x2d\xc8\xda\xb7\x01\xe6\x6b" + - "\x11\x36\xc4\xb9\xae\x4f\xf8\xb7\x9d\x17\xc4\x49\xf6\x7c\x90\xb7\xf0\x89\xbb\x84\xd4\x6f\x11\x14\x41\xf6\x06\x3d" + - "\x1b\xd4\x91\xca\xd5\x9e\x3a\x18\xd0\x9d\x85\xe4\x13\x32\xf1\xd8\xad\x4f\x85\x5d\x72\x2d\xaf\xbe\x93\x09\xb7\xfc" + - "\xa1\xa4\x99\xf8\x19\x6e\x94\x07\x8d\x72\xfe\x1c\x6e\x54\x35\x2a\xaa\x89\x1b\x65\x07\x9f\x81\xca\x0a\xe5\x8d\x15" + - "\xb0\x4d\x45\xab\x0c\x2d\xd4\x53\x39\x64\xeb\xa3\xb8\xa9\x4d\xb7\x0f\x11\x32\xe7\xc5\x01\x8d\xe0\x70\x9d\x03\x90" + - "\x49\xa3\x5b\x29\x4e\x2b\xdc\x15\x60\xa2\x00\x4d\x3f\x94\x4c\x6b\x93\x4f\x41\xca\x68\x86\xe6\x9f\xae\xc4\xa1\x60" + - "\xc6\xc5\x40\x3c\x2d\x77\x53\xec\x6e\x2b\x99\x88\x03\x6a\x01\x35\xfc\x14\xd0\x6b\x7a\x2d\x46\x1b\x5e\x05\x14\x24" + - "\xd8\x96\x74\x70\xfb\xad\x48\x47\x1f\x3b\x2a\xac\xca\xb4\xa6\x81\x55\x9b\xeb\x74\xcc\x4b\x2c\x32\xc0\x5d\x13\x12" + - "\x0a\xd8\xb0\xb7\x1b\x73\x30\xf4\x88\xdf\x7b\xdb\x11\x1f\xfb\xe8\xce\x13\x9d\xc4\xec\x45\xed\x5b\x03\x1b\xf5\x1a" + - "\x7b\xd2\xb7\xbb\x51\x59\xb6\xb1\x65\x40\x90\x32\xcc\x20\xf4\xd0\x76\x33\xed\x8f\x9b\x5d\x5f\xd2\xa7\x87\x0c\x9a" + - "\x4c\x7f\xe5\xbc\x50\x5c\x9f\x39\x51\x4b\xae\xeb\x46\x65\x8d\x59\x00\x24\x99\xd1\x29\x63\x1c\x63\xd7\xd9\x0e\x97" + - "\x35\xc0\x87\x99\x22\x55\xab\xa5\xab\x1e\xf3\xf7\x5a\xda\x99\x99\x14\xc0\xa0\x2a\x34\xa3\x43\x9e\x5f\x53\xc1\x31" + - "\xaa\xb3\x06\x6d\x1a\xb5\xea\xdd\xff\x6a\xff\xcb\x7d\x4e\x11\x74\x2b\x33\x03\xd8\xb1\x47\x52\xdd\x7f\x4f\x28\xf2" + - "\x32\xd0\xb3\x3b\x42\x21\xd8\x10\xfa\x2e\xe4\xb9\x91\x20\x01\xce\x9e\xa7\xa4\x82\x29\xfa\x93\x31\x4b\x55\x19\x40" + - "\x22\x9c\x98\x9a\x22\x64\xc0\xd5\x82\x26\xd9\xf6\x35\xd7\x8d\xa9\xc8\x6f\x5d\xda\x8b\x39\xe5\xa4\x5b\x11\xc9\x15" + - "\xdd\x62\xf3\xfc\x77\xad\x9e\xb1\xdd\xd3\xd1\x62\xde\x50\x38\xec\x0e\x81\xb8\x8b\xb5\xe2\xf3\x29\xce\x3a\x79\xea" + - "\x60\x35\x99\x3c\xe5\x82\x82\x74\x8e\x1b\x41\x19\xa8\x43\xa7\xd1\x06\xb5\x34\x3d\x3e\xb2\x91\x71\xd6\x14\x80\xb9" + - "\x4d\xdf\xd1\x1b\x79\x66\xdc\x58\x83\x30\x82\xc8\xc8\xfb\x92\x7c\xef\x85\xf1\xcb\x2d\x28\xb8\x88\xda\x1d\xee\xb0" + - "\x43\x50\x47\xe4\x97\xb5\x95\xd1\xc5\x8f\xb4\xc5\x79\xd3\xae\x73\x03\xce\xbc\xee\x7e\x93\x85\xcc\x7e\x12\x5a\xc8" + - "\xdc\xe5\xb0\xb5\xb5\xdd\x76\x20\xa7\xc5\x0c\xdc\xee\x3b\x55\x28\x80\x0f\x51\xa0\xde\x45\x88\x1f\xdc\x13\x68\x17" + - "\x1d\xa2\x85\xb1\x64\x34\x52\x6f\x81\x4f\xd6\xb9\x7a\xf6\x7f\x9e\xfd\x55\xa5\xa0\x79\x45\xdc\xd6\xf3\x55\xa3\xd6" + - "\x98\x7e\x72\x55\xb8\x19\xcc\xa6\x98\xd1\x17\x1d\x28\x7c\x55\xd2\xcc\xf5\xc1\x5c\xea\xfc\xcf\x55\x1e\x36\xb6\x15" + - "\xbd\x95\x9d\xf2\xc2\x81\xb7\xc4\x6c\x36\xee\xcc\x84\x1a\x08\x27\xd4\xab\x27\x84\x88\x25\x42\xe7\x06\x64\x8d\xbc" + - "\xdb\xe0\xb3\xd1\x04\xe9\x34\x1b\xb1\x75\xc4\x01\x4d\xa1\x44\xf0\xae\x1c\xab\x04\x7f\x22\x54\x14\x6a\xb3\xe1\x31" + - "\xfd\x86\xe7\x52\x39\x39\x56\x09\x2a\x76\xc5\x9b\x67\xa8\x39\x4d\x40\x83\x0a\xcf\x69\x64\xcf\xf2\x7c\xac\x12\x21" + - "\x37\xc4\x98\x53\x05\x18\xe4\xa3\x7c\x16\xce\x94\x73\x8a\xc9\x51\xcf\x42\xa0\xcb\x88\x2d\x65\x55\x01\xf1\x66\xe8" + - "\x93\xee\x7c\xb7\xa0\x7f\x8e\xdc\xca\xaf\x89\xdf\xd3\x70\xe7\x62\x39\x71\xfc\x37\x2b\xc8\x32\xf5\xf4\x08\x2e\xa5" + - "\xb6\xa3\x57\x0d\x19\x91\x21\xff\x81\xad\x36\xe4\xb9\x59\xbb\x22\x00\x57\xb8\x53\xd8\x3a\xf9\x18\x9e\xfa\xe9\x38" + - "\x73\x56\x62\x61\x92\xef\x26\xd6\xa3\x91\x82\x40\x98\xfe\xef\x22\xd1\xa2\x0c\xa6\xda\x44\xe7\x36\xac\xa8\x2b\x61" + - "\x0e\xca\x50\xab\x7a\x7e\xd2\xe8\xc9\x05\x66\x86\x43\xa6\xff\x30\x8c\xb5\x55\xd9\xb4\xb2\x6b\x4b\x71\x5a\x69\x56" + - "\x2f\x73\x7d\xed\x83\x39\x46\x0f\x1f\xde\xfb\x4c\x3d\x54\x3f\x99\xa6\xca\xcc\x25\x32\x01\x7a\xd2\xac\x74\xae\xb8" + - "\x30\x78\xac\x93\x30\x08\x85\xff\x7f\x10\x84\xab\x7e\x3b\x01\x66\xf5\x23\xe5\xcf\x65\x5f\x6e\x4e\x7d\xd0\xf1\x01" + - "\xa2\xa7\x7c\x04\x28\x1e\x07\xbf\xc3\xa0\x93\xea\xe1\x08\x11\xa9\x74\x9e\x03\xfe\x62\x7e\x8d\x22\x97\x95\x3f\xb3" + - "\x82\xdd\xcf\x5f\x60\xaf\x84\x07\x3f\x76\x97\x9e\xf3\x5e\xb6\x4d\x78\x37\x7e\x08\xe5\x85\xbd\x44\x8a\x01\x5e\x72" + - "\x48\xbe\x11\x78\x85\xe1\x68\xfa\x8a\xc5\xf5\x77\x25\x96\x82\xf8\x49\x4a\xe4\x63\x97\x79\x66\x18\x01\xe1\x79\xb9" + - "\x58\xae\x1a\x93\x9e\xd8\x46\xd4\x02\x1c\xa4\xce\xad\x64\x99\x67\xfa\x3c\x87\xc0\x13\x1a\x8e\xed\x6c\x43\xa9\xcc" + - "\xdd\xfc\x6c\x6d\xf9\x55\x21\xcc\xf7\x4d\x75\x83\xeb\x36\x8c\xe5\xce\xb2\x9c\x41\x78\x1f\x74\x4b\x2e\x3e\x91\x79" + - "\x3d\x58\xa4\xac\xe6\xec\xc8\x60\x52\x6f\xcc\x62\x59\x56\xba\xba\x06\xa0\xa1\xde\xa2\xac\x8c\xb2\x5b\x55\x95\xcb" + - "\x66\x91\xfd\x0a\x9c\x4c\x5f\xad\x8a\x26\xcb\x01\x39\x0b\x3c\x72\xd4\xb9\x69\x1a\xc0\xef\x5e\x98\x5a\xe9\xbc\x2c" + - "\x66\x03\x6e\x08\x61\x43\xb2\x06\x64\x6a\x14\x55\x53\x5c\x52\x82\xd2\x9c\xa0\x0b\x8b\x2e\x52\x0e\x2a\xe6\x99\xca" + - "\x0a\xf5\xdd\x77\x28\xf4\xd9\xd1\x0c\x79\x8a\xc6\xee\x1a\xab\x6b\x31\xc4\x81\x4a\xa8\x84\x53\x88\xa1\x04\x87\x48" + - "\xe2\x98\x12\xa1\xb8\xc6\xe0\x77\xe0\x03\x5c\x46\x68\xf6\x36\xc2\x4f\xea\x12\xd4\x3f\x09\x8a\xe1\x09\xcf\x8f\xae" + - "\xd5\xd4\x92\x92\xb5\xbe\xb6\x3c\xdf\xcc\x34\xaa\xca\xd2\xd6\x56\x47\x3d\x15\x7e\xcb\x51\x21\x74\x62\xa9\x7b\x2e" + - "\x26\x85\xce\xdd\xbb\x0a\x2a\x4c\x5d\x12\x55\x19\x68\xc1\x83\x46\xe9\xce\x1e\xc3\xe2\xf6\x73\x48\x47\x90\xce\x92" + - "\x8f\xdd\x0c\x4e\x8e\x08\xc7\xf0\x07\x04\xf9\x30\x66\x71\x06\xe1\xae\x14\x94\xe3\xd4\x7f\x7c\x26\x62\xea\xb6\xb9" + - "\x30\xeb\xe2\xdd\xb7\xf1\xe1\xa4\xaf\xe9\x80\x06\xf9\xca\xc1\x33\x2c\x5b\x2c\x73\x03\xf3\x3c\xd5\x59\x0e\x7c\x9b" + - "\xa6\x4d\x93\x15\x00\xfd\xa7\x0b\x22\x6a\x4e\x1c\x74\xad\x59\x09\xba\x28\x0b\x03\xc1\x25\x61\x9f\xe4\xe6\x07\x1a" + - "\x87\xb1\x97\x7b\x78\xf8\x53\xaa\x52\xa6\x4a\x20\xe1\xac\xc2\xe8\x9f\x1e\xfd\x72\x00\xb4\x3d\x95\x3c\xa5\x67\xf0" + - "\xdf\xf3\xb2\x4a\x4d\x75\xf4\x60\xff\x81\x5a\x67\x69\x33\x87\x5f\x73\x63\xa9\x81\xfd\x39\xfa\x26\x51\xfd\x98\xa6" + - "\x44\x09\x93\x42\x57\xb2\x7c\xad\xaf\x6b\x48\x2b\x63\x94\x06\x7d\x14\xa8\x2c\xeb\x0b\x93\x9b\xa6\x2c\xec\x56\x45" + - "\x87\x41\x38\x3f\x1e\x4c\x1e\x54\x16\xf3\xf2\x02\x30\xca\x2b\xb3\xaa\x71\x24\xb8\xc2\xd8\x63\x14\x85\x49\xbd\x15" + - "\x73\xd6\x61\xb0\x09\x7f\x3b\x84\x8e\xb0\xcf\x2a\xe6\x2c\x2a\x7d\xec\xd3\xef\x5a\x72\x37\xaf\xf2\xa8\x04\x39\x45" + - "\x5c\xf0\x32\x03\x3a\x47\x47\x82\x29\x79\xc7\xae\xb4\xdb\xd8\x9d\xb5\x30\x2a\x37\x38\x83\x10\x38\xb7\xd0\xd5\x2c" + - "\x2b\xec\xf2\x8e\xfe\x8e\xbf\x47\x38\x20\x78\x5b\xac\x16\x45\x59\x2c\xaf\x28\x5b\xcc\x4f\x66\xf6\xf2\x6a\xd9\x53" + - "\xc9\xdf\x7b\x89\xda\x55\xcb\x62\xb5\x50\xbb\x2a\xe9\xf7\x8e\xb7\x97\x57\xfd\x53\xbd\xf7\xeb\x7f\x9d\xed\xfe\x21" + - "\x19\xa8\x24\x63\x2a\x64\xab\x99\x99\x06\x28\x72\xdd\x82\x2e\x8f\x34\x7a\x1d\xc1\xdf\x1c\xe9\x94\x19\x20\xf4\x1d" + - "\x14\x7e\x40\x58\x5a\x87\x0e\x29\x20\x8c\xaa\x5d\x55\xcf\x4f\x4e\x5c\x51\x58\x86\x09\xd5\x22\x8e\x3f\xec\xd8\x81" + - "\x5a\x64\xc5\xcf\xf4\x4b\x5f\xd1\x2f\x06\x03\xe5\x6b\x07\x7a\x09\x7f\xe0\xca\xbb\xda\x8e\x7c\xc5\x18\x29\x82\xa3" + - "\x0e\xa3\x6f\xc2\xcd\xf5\x35\x3e\x99\x99\xe6\x47\xc4\xa4\xbe\xc6\x30\xaf\xac\xc6\x5b\xa0\x30\x26\xb5\x57\x46\x59" + - "\x29\x20\xf8\x0f\xd0\xe8\xfd\xa0\x6f\xef\x87\x57\x2f\xbf\x1e\xa8\xda\x18\x75\xff\xe0\xd1\xe7\x8f\xbf\x64\x52\x14" + - "\x8d\x6e\x8b\x83\x23\xf1\xe9\x30\x6e\xcb\xdd\xf7\x37\x37\xae\x10\xf3\xbb\x7e\x03\x75\xd4\xec\xa8\x0f\x34\x60\x29" + - "\x4f\xd2\x8d\x0b\xfa\x09\x96\x6a\xec\x23\x7d\x59\x07\x8b\x0b\x9d\x8b\x8f\x07\xcf\x60\xf6\xf6\x44\x3d\x55\x5f\xd0" + - "\xe3\x67\x8a\x63\xfc\xc9\x57\x3b\xd1\x6b\x03\x69\xa6\xe6\x7a\x72\xa1\xce\xaf\xd5\x0b\xa3\x0b\xf5\x32\x5d\xeb\x2a" + - "\xad\x13\xfa\x8a\xea\x50\x3d\xdd\xa8\xdc\xe8\xba\xe9\x53\x28\x60\xad\x96\xa6\x9a\x98\xa2\xd1\x33\x8c\xde\xd2\x2a" + - "\xd7\xd5\xcc\x54\x0a\xd2\x3f\x93\xda\xb2\x26\xa9\xcf\x6e\x16\xbb\x1a\x0b\x50\x8a\x48\xf6\x67\x99\x5d\x99\x9c\x13" + - "\xd4\x36\xec\xc0\x37\xb3\x93\x83\xf1\x91\xcf\x4f\x4e\xde\xbe\x56\x69\xa5\xa7\x0d\x30\x06\x2e\x24\x2c\x35\x97\x0c" + - "\x9c\x3d\xa9\xeb\x35\xfc\xb7\x5c\x8c\xee\x57\xa6\x2e\xf3\x4b\x93\xee\x61\x0f\xfc\x4a\xf0\x81\x25\xc9\x19\xc3\x41" + - "\x77\x76\xf8\x9c\xb3\x40\x4d\x0c\x9e\xbc\x16\x02\x37\x6f\xc7\xf8\xfb\xfa\xb7\x70\x80\x47\xc8\x7d\x0d\xe1\x2f\xa4" + - "\x64\x7c\x66\xdc\x3b\x7e\x40\xaf\xe9\x20\xf9\xd7\xf4\x40\x7a\xf7\xae\x1a\x4e\x9e\x6d\xe9\x0c\xb6\xca\x7c\x86\xf6" + - "\xfb\x8e\xf8\x00\x44\x26\xdd\x0a\x5b\x6b\xd5\x1f\xf6\x15\x01\x91\x0e\xc5\x6e\x73\x27\x62\x1d\xf5\xe6\x27\x03\xe1" + - "\x17\xde\x42\x94\xca\x79\x08\xeb\x14\xf3\xd0\xea\x4e\x38\x0f\xad\xce\x89\x79\x90\x01\xdb\x1e\xb0\x36\xca\x66\x72" + - "\x1c\x6f\x7e\xbc\x9b\x2c\xeb\xf0\xd2\xed\xd8\x5f\x5f\x81\xe6\x1a\x27\x4a\x83\x61\x2f\x2b\x1a\x33\x33\x98\xa3\xc3" + - "\xd6\xba\x6b\x0f\x6a\x1c\x22\x2c\xa5\x89\x34\xfd\xa3\x69\xbe\x2f\xcb\x8b\x57\x53\x70\xa6\x4e\x33\xfb\xfc\xbb\x62" + - "\x00\x89\xab\xbf\x63\xfd\x37\xc4\x4a\x4c\x99\x65\xb3\xaf\x06\x6a\x6d\x1e\xe4\x39\x9a\x03\x98\xbd\x44\xdd\x51\xb5" + - "\x2a\x00\x05\xbf\x79\x60\x19\x61\x9d\x3b\xda\x36\xf4\x43\x06\x52\x30\x33\x1d\xf8\xe9\xce\xaf\x9b\xbb\x22\x32\x69" + - "\xd8\x7e\x40\x5e\x36\xc8\xd9\x87\xf4\xb2\x57\x56\xd8\x14\xa8\x5d\x38\xf3\x53\x53\x52\xfa\x3e\x95\xae\xe0\x2f\xce" + - "\x2b\xe9\x35\x38\x24\x8c\xdb\x3a\x09\x61\x2f\xe3\x64\x33\x76\xe6\x81\x9d\x47\x2b\x99\xae\x20\x9b\x7b\x09\x99\xe4" + - "\xe7\x90\xb8\xcd\x92\x08\x3c\x67\x3f\x59\xa6\x67\xc0\x55\xd8\x59\x58\x43\x4a\x6a\x94\xf4\xa8\x42\x72\x37\x05\x49" + - "\x76\xc6\x5b\x53\x20\x30\x04\x46\x7e\x1c\x21\x8c\xee\x50\x55\x06\xf7\x84\x1d\x4a\x5d\xa2\x29\x06\x78\x47\xc2\x25" + - "\xb2\xa7\x9c\xb3\xe5\xa0\x42\xcf\xa4\x48\x70\x86\x54\x23\xcd\x78\x8f\x1b\x57\x47\xb4\xb6\xfd\xdb\xd1\x09\x1d\x7c" + - "\x32\xee\x99\xd8\x91\xc3\xde\xa4\x40\xed\x7e\x2c\x6b\x58\xa9\xbf\xe8\x7c\xa0\xce\xcb\xab\x93\xec\xd7\xac\x98\xfd" + - "\x84\x14\xd1\xfc\x85\x5c\xc5\xd3\x12\x42\x1d\x05\xdf\x1d\x33\x84\x84\x63\x44\xa1\x26\xb2\x60\x24\xb3\x42\x28\x13" + - "\xe9\x52\xd2\xec\xf2\xee\x92\x21\xef\x7e\x89\x97\xce\x26\x18\x0c\x57\x60\x78\xae\x27\x17\xb3\xaa\x5c\x15\xe9\xf3" + - "\x3c\x5b\xaa\x23\x95\x10\x13\xb9\x77\x5e\x5e\x81\x8b\x8f\x2d\xdb\x0a\x80\xde\xf8\x35\x7c\xe2\x2c\x5c\xb9\xd1\x15" + - "\xe8\xe9\x4f\x88\xd7\xd8\xdc\xf0\x51\xbb\x69\xe0\x45\x68\xaa\xe8\xab\x49\x5d\xbf\x33\x57\xe0\x7f\x84\xec\xf9\x78" + - "\xff\x10\x48\xd6\x78\xff\x10\x59\xf3\xf1\xfe\x61\x53\x2e\xc7\xfb\x87\xb9\x99\x36\xe3\xbd\xaf\xbf\xfe\xfa\xeb\xe5" + - "\xd5\x21\x6e\xe3\x3d\xfb\xe6\x60\x79\x75\x98\x28\x48\xda\x94\x2c\x69\x59\xc7\xfa\xbc\x2e\xf3\x55\x63\xa0\xfb\xbe" + - "\xd1\xc0\x61\xd5\x2e\x83\x67\x7a\x5e\xc2\x3e\x04\x79\xb9\x6c\xe6\xe1\x2e\x51\x3b\xed\x3d\x02\x9b\xd8\xc1\x22\xb1" + - "\xf6\xc0\xa8\x5c\x5f\x23\xfd\x47\x59\xb5\x99\x9b\xeb\x07\x2e\x68\xc3\x6e\xf3\xc6\xa7\x28\x02\xe8\xfb\xa6\x54\xb5" + - "\xa6\x53\x58\x1b\x4b\x43\x88\xf2\x83\xe8\x6d\xcf\xa2\xe7\x15\xf1\x46\xf8\x51\xf6\xed\x59\x91\x7e\x1b\xf7\xad\xe7" + - "\x84\xbc\xcb\x78\x9e\x5b\x02\x04\x89\x25\x4f\x1f\x7d\x3d\x70\xc9\x51\x1e\x0d\x1f\x73\xb9\xbf\x98\x22\x2d\xab\xbd" + - "\x65\x65\xa6\xd9\x95\x9d\x85\xbd\x1a\x9a\x82\xf7\xc9\xde\x1a\xe4\x9b\x3d\xff\x7c\x8c\xcb\x68\x9f\x1c\xee\x2d\xca" + - "\x5f\x37\xbc\xa2\x05\xdb\x4a\xba\x5f\x93\x1c\x30\x3e\xcf\xcb\xc9\x45\xb0\xd8\xff\x75\x48\xff\x88\x1a\x60\xdf\xd8" + - "\x6d\xb0\xd4\x69\x6a\x6b\xb2\xbf\x71\x17\x3d\xb1\x4f\x3b\x37\x05\x4c\x8e\x74\x58\x21\x07\x38\x3a\xf3\xed\xf0\x44" + - "\x3c\xe1\xd2\x84\x9e\x66\x97\x27\x2d\x55\x4f\x24\x01\xa4\xd9\xa5\x14\x00\xb6\x62\xea\x83\x67\x08\x0a\x0f\x9b\x72" + - "\x89\xf8\xc6\x07\xff\x85\x7d\xe9\x22\x4c\xf2\x03\xba\xe4\xed\x27\x4f\x96\x7c\xc4\xdc\x08\x02\xa7\xc8\x70\x04\x1e" + - "\x7b\xc5\xed\x03\xd0\xb9\xff\x52\xab\x5f\xea\xb4\x5c\xd0\xed\x09\x92\xaa\xae\xeb\x95\xdd\xa6\x96\x88\xc7\xe3\x43" + - "\xb5\x14\xa5\xab\x71\x39\x55\x51\x95\x1f\xe5\xaa\xd9\x30\x43\x4c\xd1\x22\x60\x16\xa2\x38\x03\xba\x43\x83\x59\xeb" + - "\x82\x0f\xe7\xc8\x13\xbe\x59\xdc\x71\xa3\x73\x39\x31\xc8\x04\x1b\x55\x37\x59\x9e\xab\xb4\x04\xef\x28\xbf\x95\xbd" + - "\x36\x8c\xfc\xd4\xd8\xc7\xa8\x7d\xf0\x97\x95\xd9\xc3\x93\x98\x15\x33\x7f\xf9\xbe\x29\xe1\xfe\x03\x8b\x23\xf0\x17" + - "\x94\xd9\x00\xba\xb4\xb6\xac\x0e\x81\x49\x11\xc6\x82\x49\x07\xaa\x99\x97\xab\xd9\x9c\xea\xf8\xf4\xd3\x1d\xa2\xf6" + - "\xc6\x5b\x8a\xee\x66\xe4\x14\x5a\xdd\xdf\x98\x7f\xb0\x7b\xb3\xc5\x89\xa8\x7f\x7f\x2f\x3f\x06\x9d\xed\x6a\x25\xe8" + - "\x30\x49\x25\xe6\xb5\x67\x54\x36\x2c\x78\x2b\xa7\x13\x93\x2d\x08\x96\xe3\x25\xb0\x54\x1e\xfc\xa3\x38\xd1\x12\x49" + - "\x42\x98\xeb\x97\xf8\xa1\x3d\x0c\x9a\x15\x66\x6f\x57\xd1\xcc\x34\xb5\x67\xf0\x83\xe2\x2e\x0d\x11\xd6\x58\x4e\xfd" + - "\x29\x1b\xaa\xde\xfd\xc7\x8f\x1f\x3f\xee\xbb\x7a\xd0\x04\xa1\xbe\x5d\xcd\xd4\xc1\xe3\xc7\x4f\x1e\xab\xbd\xf6\x69" + - "\x62\x26\x79\x5d\x95\xc5\x8c\x78\x64\xcf\xb4\xed\xf9\x5c\x92\x6e\xbf\x33\x47\xe5\xae\x08\x16\xcc\xc5\x01\x98\x40" + - "\x4e\xd1\x42\xec\x78\xe0\xbd\x1c\x77\xdb\xca\x29\xb2\x85\xed\xbd\x40\x36\x25\xbb\x8c\xae\xcd\xdb\xf9\x96\xd8\x11" + - "\xd9\x8a\xa2\xcf\x4f\x4e\xc6\xe2\xee\x38\x74\x7a\x1e\x1a\xd9\xa1\x42\x22\x7e\xa8\x88\x82\xe3\xf7\xae\x1b\x2d\x66" + - "\x61\xd3\xc5\xf6\xe9\x57\xdb\xdd\x97\x5b\xf7\xf5\x26\x58\x9a\xd6\xfd\x26\xdf\xf1\xf5\x14\x5e\x71\xb2\x44\xd7\x1d" + - "\x37\xde\x3f\x74\x6c\x10\x5f\x66\xfb\x1c\x50\x1c\x4f\x87\x60\xe5\x41\x5a\x0b\xdf\xb2\x00\x98\xb8\xef\xd3\xf6\xbb" + - "\x03\xbc\x35\xc8\xce\xff\x29\xf7\x1e\x0b\xa7\xdb\x4b\x5d\xd5\xe6\xbb\xbc\xd4\xcd\x46\xda\xde\xf3\x9d\xe2\x3b\x30" + - "\xe8\xb4\xaf\xf3\x13\xae\xac\x80\x8a\x38\x49\x59\x46\x78\xdc\xfb\xec\x63\xbf\xc7\x96\x35\xd0\xb6\x90\x6d\xc0\x1e" + - "\xa1\x7f\xae\xb2\xc9\x45\x7e\xad\xea\xb5\x5e\x2e\xd1\xc5\x14\xf2\x10\x3d\x3f\x39\x91\xe9\xd6\x48\xa4\x67\xa5\xe6" + - "\x84\xb2\xfd\x67\x65\x51\x0f\x9d\x71\xd8\xd6\xd1\x91\xe5\x90\x90\x95\xbc\x7f\x14\x7b\xdd\x49\x18\x30\x52\xf1\xd9" + - "\x6e\x97\x00\x5c\xc6\x5e\xbd\x2d\x15\x47\x9e\x3a\xfd\x8d\xa5\x55\x64\xa0\x65\x15\x44\x59\x80\xb8\x8f\xb6\x56\xd0" + - "\x97\x64\x05\xf7\x80\xa9\x75\x99\xa7\xc2\x30\xec\xd5\x82\x52\x7b\xb6\xd5\x7e\xac\x8e\xb8\xa2\xb6\x9a\x8d\x34\x13" + - "\xec\x60\x42\xb2\x18\x8e\x1f\x06\x7b\x73\xa3\x4e\xcf\x04\x5b\x2d\x74\x15\x7e\x44\x77\x75\xbc\xbb\x4f\x79\x87\xda" + - "\x2f\xd8\x0f\x1f\x03\x04\x63\x7b\xa1\xdb\xc5\x86\x3b\x1b\x2e\x02\x54\x7f\x83\xdc\x59\x18\x55\x56\xaa\x6e\x74\xd5" + - "\xd4\xe4\x3e\x0b\xe5\xd0\xc9\x98\xb1\x48\x19\x94\x74\x6f\x62\xf2\x3c\x19\xd8\x4f\xf8\x01\x22\xaf\x26\xd4\x8e\x11" + - "\x10\x4a\x81\x4d\x88\xd0\x93\x6a\xd4\x95\x99\xdc\x6e\xb4\xe1\xa2\xfc\x35\xcb\x73\x0d\x6a\x33\x53\xec\xfd\xf9\x64" + - "\x94\x96\x93\x7a\xf4\xfc\xe4\x64\xe4\xb5\xe7\x15\xfd\xa4\xcd\x36\xfa\x7b\xcf\xf6\xfa\x06\x9a\xef\x1d\x6f\xef\x4d" + - "\x4e\x8d\x3e\xeb\x0f\x19\x3b\xb9\x58\x2d\xea\x65\x9e\x35\x77\x69\xc2\x87\x0f\xfb\x4e\x01\x0e\x1f\x56\x26\x7f\xb3" + - "\x5a\xb4\x3f\x3b\xdd\xdd\x3b\xeb\x1f\x85\x5f\x8b\x0f\xad\x58\x55\xd7\x27\xf3\x72\x6d\xf7\xb0\x72\x3c\xb6\x4a\x1c" + - "\x97\x3d\x50\x97\x59\x4d\xb0\xb2\x63\x95\xcc\xb3\x34\x35\x45\x32\xe0\x09\x1a\xab\x04\x48\x5f\xa2\xe0\xe6\x9f\xd4" + - "\xf5\x1b\x48\xbd\xff\xae\xd2\x45\x6d\x19\x24\x4e\x9f\x93\x83\xfd\xf2\x64\x09\x0e\xd0\x63\x4b\xd0\x28\xab\x76\xd1" + - "\xfc\x8c\x22\xa2\x4a\x9e\xec\xef\x27\x22\x42\xa5\xae\x7f\x04\x9a\x8e\xf0\x34\x2a\x41\x33\x8c\xed\xfe\x5b\xfb\x9f" + - "\xd7\xe5\xaf\xf6\x9f\x45\x9d\x90\x8d\x0c\xd4\x29\xe8\x22\xac\x26\x75\xed\x39\xda\x85\x86\x74\x6b\x80\xb3\xb2\x2c" + - "\x2d\xed\xce\x40\x37\x74\x09\x37\x87\xc2\x9b\xc3\x67\x6c\x94\x46\x6f\x2c\xf2\x63\x55\x2e\x11\x29\x0f\x2d\xdc\xac" + - "\xdb\xfc\x8d\x0f\x88\x0b\x84\xb0\x7b\x07\xf0\xed\x91\xd5\x46\xfd\x4d\x13\xb7\xe4\x70\xe7\xe8\xe4\x74\xa8\x05\xe0" + - "\x5d\xc0\xe4\x23\x3f\x6a\x1b\x88\xfb\x0d\x0d\x12\x75\x9a\xe8\x25\x01\xe9\xd9\xa7\xa7\xfb\x67\xc3\xa6\xfc\xf3\x72" + - "\xe9\x42\x20\x76\xe1\xf9\xb0\xce\xb3\x89\xe9\x1d\xa0\x2a\xa3\xac\xb2\x99\xf8\x08\x9e\x41\x3e\x7e\xbf\x02\x81\x2f" + - "\x63\x47\x5e\xfe\x02\x3f\x17\x5f\xa0\x7f\xc7\x2e\x77\xc8\x03\x36\x75\x0e\x3a\x1e\x75\x5b\x55\xc9\x9d\x3c\x8c\x51" + - "\x1b\x6b\xd3\x20\x0b\x7b\x69\xde\xac\x2c\xe5\x65\x52\x46\x4e\xfe\xf5\xea\xbc\xa9\xf4\xa4\x89\xd1\x6c\x61\x5b\xb9" + - "\x23\x17\x06\x93\x08\xa8\x5c\x2e\xcb\x8a\xd1\x3f\xae\x20\xc6\x9b\x14\xeb\x5e\x71\x9a\x70\x3b\xc9\x40\xa1\x23\x3b" + - "\x20\xf6\x81\x57\x82\xae\xc1\x01\xb3\xae\xbf\x2f\x4b\x8c\xe2\x78\xad\x9b\xf9\x70\xa1\xaf\x7a\x6a\x7f\xc0\x4d\x20" + - "\xb4\xcc\x9e\xea\xf9\x2e\x53\x16\x26\xbb\x6c\x3d\x5f\xec\x11\x86\x92\x24\xcb\x2b\x07\xff\xc8\x81\x1a\xe1\xd4\xe8" + - "\x15\x38\x6b\x82\x02\xf8\x6d\xf5\x3d\x9c\xb3\xd0\x48\x65\xae\x9a\x4a\x0f\x54\x56\x7f\x0b\x1c\xcb\xb7\xe5\xd5\x00" + - "\x17\x26\xc6\xbc\x85\x82\x20\xa5\xf6\x64\x69\x75\xcc\x3a\x9f\x44\x8d\x9d\xae\x28\x61\x10\x49\xb4\x38\xaf\x9d\x1d" + - "\x98\x00\xcf\x1d\xc0\xcd\xc2\xe8\x7a\x55\x11\x0e\x09\xe2\x0b\x50\x9f\x9d\x43\xe7\x13\x1c\xe0\x68\xa4\xde\x36\x73" + - "\x53\xad\x33\x88\x30\xca\x1a\x02\x0f\xb2\xe7\x61\x5e\x56\xd9\xaf\x96\xcf\xc8\x15\x9c\x8e\xaa\xc9\x26\x3a\x17\x1c" + - "\x81\xdf\xa1\x56\xca\x06\xc6\x29\x51\xc7\xea\x40\x8d\xc1\x11\x9e\x26\xd0\x7b\x3f\x49\x4f\xd8\x27\xf6\x9f\xdd\x23" + - "\xf5\x88\xb7\xea\x68\x84\xca\xa5\xf3\xf2\x4a\x2d\xca\xd4\xe4\x56\x50\x9d\xe4\xab\xd4\x10\xa7\x34\xb0\x9c\xba\x4e" + - "\x53\x95\x35\x14\x32\xb5\xd6\x45\xa3\x84\xbb\xba\x9f\xcc\x04\x3f\x49\x44\x28\x58\x6e\x5b\x8b\xdd\x2f\x68\xa5\xec" + - "\x79\xaa\xeb\x97\x00\x0d\x40\xde\xa0\xe8\x45\xcb\x6b\xd6\xf2\xe1\x96\x6b\xc5\x6d\xc0\x08\x58\x4d\x63\xe5\x25\xdb" + - "\xf9\x9a\xd9\x76\xe8\xbe\xd3\x4b\xcb\x11\x48\x38\xa2\x78\x1c\x62\xe5\x9d\xc3\x7b\xae\xf6\xba\x46\x92\x50\x43\xc9" + - "\xa7\x8d\x46\x2a\xa8\x41\xef\x96\xd5\x0a\xd2\x3a\xf2\x9c\x64\x90\xe3\x16\x47\xa4\x0a\x27\x69\xc9\x71\xe0\xcb\xb8" + - "\xe3\xdb\x5d\x0b\x70\x4b\xbf\x79\xa3\xc7\xdd\xb6\xd7\x2a\x9c\xb1\x64\xe3\x00\x22\x9f\xc9\xdb\x87\x42\x73\xe9\xf6" + - "\x91\x94\xa7\x36\xee\x8f\xdf\x35\xab\x9f\xde\x09\x98\x50\xb9\x33\x6c\x87\x6e\x99\x4e\xd7\x8b\x60\x3e\xbb\x7b\xfc" + - "\xef\xcd\x67\x7c\x41\x5c\x82\x0e\xa2\x85\xe8\x7b\x17\xf1\x93\xd7\xf8\x89\x65\x25\x91\x93\x2c\xa7\x53\x2b\xf4\x32" + - "\x4b\x60\xa9\x79\x36\x99\x83\x56\xea\x9f\xab\xec\x52\xe7\x94\x05\x1f\xb5\x4b\xee\x30\x01\x1d\x26\xb2\x09\xbf\x5f" + - "\x89\xf3\x77\xe4\x53\xcb\x23\xb9\xe9\xa0\x49\x68\xc6\x86\xc6\xd1\x84\x37\x96\x8f\x70\x14\xde\x51\x80\x30\x12\x43" + - "\x17\x00\xbc\xbf\x83\x76\x3b\x27\x9f\x74\x38\x89\x0b\xcf\x70\x84\x1f\xba\xe4\x47\x95\x38\x41\x00\xcc\xdc\x0e\xba" + - "\xce\x01\x4e\xd1\x0a\xf8\xcb\xd0\x12\x50\x31\x08\xd8\x38\x9e\x7f\xb1\x52\xe4\xc8\x15\xa6\x9a\x2f\x67\x6a\xcf\xb1" + - "\xd9\xe7\xab\x19\x72\xd7\x92\xcb\xae\xe7\xe5\xfa\xc3\xf9\x6a\x36\x9c\xcc\xb2\xe3\x2c\x3d\xfa\xe2\xc9\xd7\x8f\xbe" + - "\xfa\x9c\x13\x53\x37\xf3\xd7\x3f\xfc\xde\x1a\x9e\x7c\x7d\xf0\xc5\x17\x5f\x31\x37\x66\xd7\xe4\xe9\x91\xda\xb7\x77" + - "\xeb\x65\x5b\x6d\x06\x28\xbe\x79\xae\x20\x68\xa6\x29\xbd\x3a\xa9\x81\x7b\xbe\x70\x7f\x5b\xde\x33\x9b\xaa\xc2\x4c" + - "\x4c\x5d\x6b\xc4\x8c\xc2\xf5\xee\x72\x13\x09\xb6\xb6\xef\xc7\xc6\x6e\x50\x55\x1b\x04\x41\x89\x80\x4a\xdd\x59\x15" + - "\x99\xb3\xd3\xa1\x93\xc0\x50\x9d\x34\xe5\x12\x85\x1d\x2b\x95\xe2\xf2\x0d\xef\x6d\x30\xf0\x5f\xea\xbc\x15\xf0\x74" + - "\x49\x0a\x3f\xdf\xde\xda\x90\xe6\x94\xa1\x98\x31\xdf\x01\x2a\x98\x0b\x35\xd1\xb5\x51\xda\xa7\x82\x85\xd3\xc4\xaa" + - "\xb2\x55\xc1\x0a\x43\x61\x03\x1f\x8d\xa0\x86\x96\x7e\xad\xce\xec\xd9\xcb\xaf\x21\x70\xb4\x76\xcb\x01\x4c\x05\xd7" + - "\xe2\x67\xc7\x31\x47\xe1\x41\x94\xc7\x83\xfc\xfc\x9d\xbe\x7a\xd8\x52\x6f\xf6\xfa\x7e\x31\xba\xa6\x5e\x7a\xd8\xa1" + - "\xfc\x63\x59\x93\x24\x19\x28\xbd\x6a\xca\x01\xc7\xf3\x2e\x35\x49\x97\x40\x78\xfc\xb6\x90\x5a\x98\x4b\xf0\x0b\xb7" + - "\x7c\x5f\xc0\xfc\xb3\x22\x5b\x4f\x2c\x9f\x2b\xb4\x5c\xc8\x82\x80\x6c\x93\xa6\x23\xc7\x38\x66\x56\x24\x34\x97\xf6" + - "\xd6\xc6\x0d\xe6\xe9\x24\xb6\x01\x8a\xad\x4e\xfe\xf0\x1e\xfb\x77\x13\x3e\x28\x4b\x04\x5b\x48\x2e\x21\xcb\xdb\xa7" + - "\x70\x80\x22\x4c\x50\xcc\x3d\x85\x18\x72\x9f\xb6\xfa\xf7\x3e\xdb\x82\x5c\x15\xa8\xc4\x8a\x58\xfb\x79\xb9\xfe\x3e" + - "\x63\x04\x4b\x0c\x7a\xb5\xcf\xa4\x47\x25\xca\xa1\x8c\x24\x86\xf2\xe9\xc0\xad\xba\x40\x36\xc5\x68\x3b\x97\xbd\x81" + - "\x42\xc8\x5c\xcd\xdd\x59\x1c\xe0\x9b\xa7\xca\x61\xeb\xda\xbf\xbd\x1b\xbc\x80\xf8\x20\xd8\x5c\x28\x2f\xd2\x3b\x6d" + - "\xfb\xcd\xe2\x8e\x50\x00\x8a\xf7\xd1\xb1\x9f\x2b\xe3\x2b\x08\x90\xc3\x44\x2a\x96\xa4\xcc\xd3\xc0\x03\x37\xf6\x1f" + - "\x1d\x06\x7e\xbc\xbe\x1f\x62\xd6\x84\x4a\x17\x73\x0b\xe6\x59\x61\xa4\x17\x3a\x70\x04\x1c\x95\xdc\x94\x2a\x37\xba" + - "\x22\xbf\x0a\x81\x21\x88\xb1\x66\x38\xdf\xea\xfc\xda\x1e\xf0\x89\x4e\x4d\xaa\xaa\x95\xa5\x67\x96\xcc\x97\x82\x55" + - "\xdc\x8e\x47\xb8\xb3\xd3\xe5\x50\xea\xb8\x86\xf6\x60\x42\x78\x0b\xee\xc6\x89\x11\x19\x56\x90\xaa\x80\x8c\x01\xc9" + - "\x3e\xca\x4b\x53\x55\xd8\x43\xb8\xd4\x9d\xd2\xa2\x20\xd0\x67\xf0\xcc\x2a\x00\x81\xd4\x6e\xc8\xb9\x31\x30\xe2\xf5" + - "\x5c\x37\xe6\x92\x74\x78\xec\x13\xc9\xa4\x8b\x48\x9a\x9b\x08\x20\x73\xab\xc9\x3c\x70\x1b\x0e\x82\xf4\xa3\x61\x38" + - "\x27\xb6\xac\xfe\x1e\x3a\xd7\x86\x9c\xbb\x6d\x3b\x70\x00\x52\x7b\x47\x0c\x62\x17\x64\x07\x11\x60\x05\xe7\xfe\x66" + - "\x76\x94\x56\xf1\xa8\xd5\xa3\x20\x12\x93\x07\xb0\x1d\xfa\xff\xd2\xc7\xae\xef\x51\x12\x8d\xae\x6e\xd2\x27\xc7\x6a" + - "\xb3\xbf\x79\xe0\x6a\xbe\x81\xf1\xa3\xe5\x87\x45\xf2\xdb\x77\x51\xd6\x4d\xe4\x32\x5e\xd3\x22\xa3\x61\x3e\x2f\xcb" + - "\x25\x7e\xed\x40\xed\xd0\x07\xb6\xa8\x1b\x4b\x30\x2b\x33\xcd\x21\x4d\x39\x45\x9c\x31\xdd\xf8\x5f\x22\x07\x0e\x57" + - "\xde\x1e\x59\x06\x8b\xef\xd8\x42\x6e\x05\x36\xef\x31\x19\xad\xd3\x3a\x4c\x50\xff\xb1\x8a\xb7\x1a\x46\xbf\x8d\xa9" + - "\xfe\x6e\x5d\x0c\x8f\xf0\x70\x63\x46\x00\x02\x73\x76\x6a\x1e\xa7\x8b\xf3\x4e\x4c\x74\x38\x21\x3b\x95\x3f\x66\xf8" + - "\xed\xb9\x99\xeb\xcb\x0c\x98\x48\xcb\x00\x80\x47\x07\x84\x2f\xf0\xef\xa8\x5a\x54\x17\x82\x76\x65\x4c\x6a\xf3\xa5" + - "\x9e\x80\xca\x12\x67\x20\x74\xf8\x62\xb8\xf2\xc8\x87\x75\xab\xdb\xb5\xd5\xc1\xed\xd7\xf3\x72\x95\xa7\x4a\xa3\xcb" + - "\x38\x7a\x0d\x16\xa0\x72\x42\x2e\x04\xdc\xe7\xa9\x61\xfa\x50\xe4\x0d\x09\x78\xbf\x84\x8a\x25\x3e\xf2\x4d\xb8\xe4" + - "\xd1\xf2\x1d\xab\xe4\xc0\x2e\x85\x33\x94\xb4\x92\xaf\xb8\x5c\x72\x64\xe5\x5f\x35\xe5\x42\x83\xf6\x23\xbf\x06\x49" + - "\x0d\x74\x44\xc8\x1d\xd5\x86\x9d\xd4\xae\xf7\x2c\x4f\x98\x1b\xaf\x23\x45\x1d\xc9\xa4\xae\x51\x83\x46\xb3\x96\x4c" + - "\xca\x7c\xb5\x28\x9e\x97\xab\xa2\x49\xc6\x5e\x78\x49\xa6\x59\x9e\xbf\xa5\x01\x04\xcf\x73\x73\xf5\xc7\xaa\x5c\xb7" + - "\x1e\x9e\xcc\xab\xac\xb8\x08\x1f\x3b\xcd\x6f\xf0\xd8\x5e\x46\xdf\xb7\x1f\x97\x1d\xad\x21\xd3\x11\x3e\x59\xce\x75" + - "\x51\x07\xcf\xd6\x59\x5a\xae\xc3\x47\xe8\xbe\x18\x3e\x2a\xcb\x05\x3d\x08\xe6\x95\x36\xb1\x30\x2e\xad\xe7\x65\x6d" + - "\x48\xc7\x7b\x5d\xae\xd4\x3a\xab\xe7\x80\x44\x9b\x5d\x29\x0c\x15\x64\x73\x02\x6e\x55\x64\x61\x1b\xde\xe6\x2c\x20" + - "\x82\xa6\xb4\x5c\xf2\x76\x1d\x8d\xac\xa0\x4d\x8c\xe3\xd4\xb2\x82\x81\x0a\x9b\x26\xb2\xd4\x76\x56\x92\x49\x5d\x03" + - "\xb7\x98\x04\x5d\xfd\xa3\x69\xf8\x8c\xa0\x1b\x52\x78\xf0\x4a\x4b\x01\x5f\xbc\x7d\xad\xde\x20\xc8\x38\xbc\x6e\x9f" + - "\x09\x14\x4a\x48\x75\x2a\x04\xe4\x2d\xbf\xcb\x6c\x03\x24\xb5\x94\x05\x02\x97\x6b\xf4\x77\xf2\x10\x36\x21\xc5\xeb" + - "\xce\x79\xf1\xb8\xfb\xf1\x57\x70\xab\x74\x10\x4a\xe1\xb4\xf8\x31\x84\x59\xa9\x57\x15\xf9\xb6\xac\xcd\x83\xca\xa8" + - "\x75\x59\x5d\xd8\x09\x77\x90\x2a\xa8\x6d\x2c\x28\x9a\xc5\x59\xf1\x10\x78\x14\x48\x12\xf2\xa5\x42\x13\xce\x17\x92" + - "\x5e\x98\x1c\x74\xe7\xa4\xf4\x17\x0c\x6c\x87\x9b\x3e\x2b\xc2\xfd\x75\x06\xab\x7c\xea\xd4\xd7\x48\x61\x7b\xb7\x16" + - "\x38\xda\x64\x76\x70\x65\xfa\x52\xe2\x00\xe7\x06\x3b\x08\x07\x22\xe0\x2c\x03\x97\xa6\xaa\x49\x8f\x0a\x9c\x4a\x9e" + - "\x97\x6b\x93\x5a\x76\xcd\x16\x5b\x15\x5d\x05\x91\x42\xcb\x21\x00\x5d\x75\xb2\x8e\x0b\xcd\x11\xaf\x7c\xe7\x7d\xb7" + - "\x9c\xf3\x06\xae\x89\x27\xdd\x7c\x04\x24\x64\x55\xe8\x84\xcc\x2b\x4e\xd9\xe2\x24\x7e\x87\x50\x5e\x4d\x08\xc1\xbe" + - "\x32\xb9\x06\xa9\x88\x68\x31\x82\x7b\xd4\xaa\xb7\x7b\x64\x4f\xdf\xde\x51\x1f\x13\xef\x04\xa5\xea\xa1\xba\xff\xe5" + - "\xe3\x27\x9f\x7b\xf6\xa6\xe1\x0d\x28\xb1\xa9\x7a\x48\xbc\xc9\xc0\x16\x1a\x09\x62\x7e\x0d\x41\xea\x4d\x73\x7a\x70" + - "\xa6\x76\x01\x98\xe2\x21\xfc\xf9\xc8\xfe\x29\x65\xbc\x36\xaf\x53\xf8\x45\xdd\x92\x18\xe6\xe7\xab\x99\xba\xff\xf5" + - "\x23\x08\xbb\xf0\xf3\x91\xe0\x10\xda\xcc\x70\x74\x18\x40\x6d\x60\x8f\xe6\x1b\xfd\x86\xdd\xdd\x75\x65\xe8\x0c\x0f" + - "\xd5\x89\x31\x63\x75\xff\xcb\x83\x83\x2f\xfc\x2c\x30\x48\x0a\x7e\x8c\x52\x2f\xad\x4f\x88\x59\xb6\xc9\x87\xf8\xd5" + - "\xd4\xdf\x8a\x6b\x5d\xab\xa5\xae\x6b\x00\xa3\x18\xc0\x85\xf4\x60\x79\xf5\x80\xc5\xf5\x1e\x19\x6a\xed\xb6\x65\x74" + - "\x8a\xd0\x94\xdf\xef\x5a\x1e\x1a\x7d\x10\x06\xc2\x37\x57\x70\x8e\xa2\xe5\xd9\x3d\x62\x29\x33\xec\x31\xc1\xc5\x7f" + - "\xf5\xf5\xfe\x57\x03\x06\xd6\x38\x87\x98\x46\xa3\x20\x3a\xd3\xc3\x68\x9c\x5f\x53\x4c\xe5\xb5\xdd\xca\x35\xd8\x34" + - "\x03\xdb\x8e\x0b\xca\x3c\x5f\x35\x10\x92\x09\x1c\xc3\xc2\xe8\x02\xe3\x0f\xc1\xa1\x1a\xae\x37\xd5\x03\x4d\xc0\xa5" + - "\xa9\xae\xed\x80\xcf\x73\x03\x37\xb7\x23\xd8\x7d\x95\xa5\xa6\x40\x4b\x06\x13\x69\x01\x15\xbe\xbd\xc9\x9d\x77\x67" + - "\x47\x02\xdd\xc0\x2c\x81\xc5\x0f\xf8\xbb\xb7\xd3\x9e\x4a\xbc\x93\x6f\x42\xba\xbe\x7d\x01\x89\x12\x19\xec\x93\xac" + - "\x98\x9b\x2a\x6b\xda\xd3\x06\x0b\x0d\x64\x07\x96\xb9\x2a\x2f\xb3\xd4\xa4\x8c\xeb\xa5\x1b\xbe\x44\x4a\x67\xb6\x01" + - "\x84\x38\x77\x3d\x61\x6c\x2a\x87\x3d\x88\x91\x21\x01\xb2\x97\x40\x2f\xa9\x4d\x93\xd8\xf9\x85\x67\xa0\x17\xe9\xf1" + - "\x59\x83\x47\x52\xc6\x08\x2f\xad\xfe\x06\x9a\xd2\x1a\xa1\xc0\x38\xa3\xd1\xc5\xaa\xfa\xee\x91\x02\x03\x08\x9e\x1c" + - "\x65\xb1\x17\x05\x8f\x70\xba\xa1\x4a\x8c\x0b\x87\xb5\xb3\xa3\x92\x99\x1c\x94\xa0\x32\x38\x22\x21\xee\x93\x5e\xf6" + - "\xae\x11\x75\xf8\xd3\x70\xd7\xdf\x86\x93\xcf\x5d\x0e\x7b\x49\xac\x82\x73\xf5\x74\x35\x76\xea\x17\x85\x7d\x7e\x13" + - "\xfb\x40\x56\xc5\xc0\x90\xc8\x2a\xf1\x81\x25\x0e\xbf\xf7\xd2\x3d\xfc\xb7\xee\xfb\xff\x99\x3b\xd9\x5f\xfd\xff\x0f" + - "\xbb\x98\xef\xd8\xce\xb7\x6e\xe5\x5b\x77\x72\xa8\xa1\x6e\xed\x66\x34\xe5\xd0\x66\x8e\xd8\x38\xb7\x4f\x07\x96\x63" + - "\xd0\x32\x02\xbc\xa3\x4f\xe6\x2a\xab\x9b\xda\x93\x1a\xc9\x4c\x44\xe8\x97\x61\x9f\xee\x54\xc0\xbb\x1e\x31\x73\x91" + - "\x20\x5b\x9e\x04\x1a\xff\x16\x07\xc3\x12\x39\x16\x25\x92\x4b\xf7\x42\xec\x10\x13\xf5\xa8\x55\x60\x83\x3e\x1f\xd3" + - "\x4e\x0d\x98\xeb\x01\x79\xa2\xe4\x8b\x36\x9b\xda\x2d\x36\x31\xa9\x82\x00\xc2\x7f\xae\x74\x6e\x69\x6b\x15\xae\xb0" + - "\x65\x05\x6c\xab\x39\xac\x56\xb1\x5a\x98\x2a\x9b\xdc\xeb\x30\x4a\xa3\x5a\x41\x32\xff\x5b\x05\xb8\x17\xb5\x34\xd5" + - "\x87\x92\x5c\xf8\x1a\x20\x1e\xc5\xef\xc7\xcc\xde\xce\xb6\xb1\x9e\x6d\x55\xf5\xd5\x31\xfc\x0b\xde\x0d\x63\x69\x4b" + - "\x88\xed\x0b\xdd\x90\x2e\xa7\x2a\xc1\xb0\x92\x64\xe0\x2c\x67\x67\x12\x67\x25\x93\x1e\x3a\x5b\x9b\xce\xcb\x51\x57" + - "\x2c\x58\xa4\x1a\x88\x64\xa0\x4d\x0a\x02\xcb\x8d\x12\x03\xe3\x54\x4e\x96\x8d\x00\x55\x64\x9a\x2d\x4c\x51\x83\x5f" + - "\x6f\x31\x2d\xc9\xa0\x9e\x15\xe0\x57\x95\x5f\xa3\x1e\xa6\x99\x9b\x85\xab\x6a\x5e\xae\x2d\x5f\x00\xcc\xc8\xc2\x92" + - "\x6d\x04\x56\xb0\xbb\xb7\xb2\x12\x16\xeb\x70\x90\x6c\x23\x1d\x04\x3e\xe3\xdc\x14\x66\x9a\x35\x7c\x66\x49\x47\xe9" + - "\xee\x07\xe1\x8c\x46\x31\x9a\x77\x68\xdd\x1c\x76\xac\x34\x48\x22\xc3\x40\x69\x00\xb6\x84\x37\xa5\x9b\x3b\x74\x29" + - "\x1b\x74\x38\x7c\xbb\xbe\x7c\x92\x61\xd6\x01\xf7\xbb\xd4\x02\x5b\xbf\xe3\x3b\x42\xfc\xc4\x03\x54\x77\x2d\x72\x97" + - "\x94\xeb\x71\x4c\x6a\xe7\xf5\x82\xd9\xe1\x5a\x71\xd6\xe2\x9e\xbc\xc3\x05\x09\xab\xa1\x29\xdb\x6c\x74\x91\x66\x17" + - "\x69\x78\x21\xd3\xcb\x20\x9c\xf2\x7f\xd5\x98\xcb\xd5\x78\x1b\xcc\xd6\x56\x5f\x8d\xd5\x3e\xfc\x8c\x22\xf0\xfa\xad" + - "\x64\xf3\x81\x0f\x76\x74\xb4\x22\x6f\xe6\x30\xc6\x93\x19\xd6\x8e\xd8\x80\x81\x88\x8f\xda\xa4\x9c\xeb\x3e\x79\xff" + - "\x69\x9f\x7c\x5b\x5f\x59\x5d\x28\x0d\xfc\x31\xdc\xc7\x04\xd7\x92\xd9\xa3\x4a\x32\x2c\x1b\x47\xf8\x20\x36\x25\x99" + - "\x51\xf6\xc0\x19\x52\x6e\x8d\x8e\xf3\xf1\x9b\x3f\x64\x63\xcb\x5f\xfb\x0f\xc9\x8b\x72\x6b\x6b\x0b\x2f\xaa\x01\xe5" + - "\x92\x1b\xb0\x9b\x0a\xcc\x56\xe2\x72\x33\x92\x62\xd6\x2d\xd2\x3b\xd0\xf2\xe1\x65\xac\x2b\x83\xce\x67\xe7\xd7\x4a" + - "\x17\xd9\x42\x63\xc0\x3a\xa6\x15\x09\xf4\x7e\x31\x5a\x16\x79\xb1\xab\x04\x51\xb2\xc8\x83\x9d\xfe\x24\xcf\x76\x76" + - "\xd0\x88\x00\xae\x90\x6d\x19\xa8\x7a\x35\x9d\x66\x57\x9b\xe8\x2f\xb9\xea\xef\x72\x31\x47\x8a\xb1\x73\x1b\x31\xb5" + - "\xa3\x04\xec\x5c\xde\xa0\x07\xf6\x40\x44\x2c\x60\xb8\x13\x24\xb0\xc9\x8a\x59\x6e\xc4\x3d\x59\x94\x0d\xa8\x8f\x2b" + - "\x17\x22\xb0\x04\xff\xe1\xa3\x5b\x60\x42\x49\x4b\x3e\x04\x4f\xc1\x5e\xa2\x12\x7b\x5e\x4e\xa9\xe4\x59\x98\xf0\xd4" + - "\x7b\x8d\x49\x48\x3a\xee\xa9\x18\x7c\xcb\xe7\xc5\xcf\x06\x9d\x50\xe8\x98\x43\x8e\x76\x7f\xed\xb1\x03\x20\x3d\x71" + - "\xd9\xe0\x3e\x86\x71\xb7\xdc\x66\x70\xa2\x5d\x38\x6a\x18\xac\x4f\xbd\xea\x47\x91\x5c\xb7\xac\xd9\x10\x61\x62\x5b" + - "\xa4\xaf\xf3\xda\x0e\xf3\xd4\x44\x92\x83\x50\x39\x7e\x22\x7a\x7a\x4b\x55\xd9\x41\xbd\x07\x2a\x27\x43\xf0\xd6\xd6" + - "\x02\xbc\xaf\x43\x34\xf5\xc0\xb4\xe5\xf8\x14\xca\x6c\x26\xb1\x0b\x3c\xad\xec\x72\xb6\xa1\x3b\x2a\x07\xf3\x19\x08" + - "\xda\x11\xea\x67\x80\xaa\x69\x8a\x18\xaa\x70\xa1\x97\xc8\x90\xe0\x3a\x9f\x75\x3a\xeb\xb8\xf7\x2d\xea\x1e\x43\x40" + - "\x3a\xa7\xd5\x65\xe7\x96\xe8\x52\xb6\x85\x09\x7d\x5a\xb0\x18\x7e\x86\xc7\x41\xc1\x96\xf6\x0a\xb7\x59\xa4\x41\x6e" + - "\x21\x6c\x7f\xa3\x0e\x3c\x6e\xf2\x96\xe5\x7d\x36\xe6\x20\xf1\xd6\x7f\x5c\xff\x10\x73\x79\x6b\x9e\xa5\x9b\xd3\xad" + - "\x84\xdf\x8a\xaf\x9a\x72\x36\x0b\xf5\xde\x98\x5e\x5b\xde\x32\x44\x08\xf0\x05\x5d\x9f\x65\x6e\xb4\xf0\x12\x74\x02" + - "\xb2\x2d\x82\xc8\x77\x43\xdb\x66\x8f\x13\x83\x0c\x6d\xf7\x7a\x1b\x41\xe5\xba\xd3\x22\x91\xc7\x26\xdb\x60\x19\x91" + - "\x9b\x37\x0b\x23\x22\xe1\x73\x6a\x8f\xd6\x39\x40\x64\x8c\x0a\x8a\xae\xb4\x62\x6d\x0e\x23\x5c\x86\x77\x6b\x63\xda" + - "\xc1\x30\xf6\xba\x18\x28\x53\x58\x7e\x58\x03\x9a\x01\x76\x8a\xbd\xb6\xcd\x1a\x3f\x1c\x2e\xab\xb2\x29\xed\xfc\x0d" + - "\xb3\x22\x6b\x3e\xa5\x1e\xb4\x21\xd2\xa6\x82\x4a\xd4\x11\x56\x06\x5d\x8b\xaa\xa5\x9b\x02\x6c\xb5\xd5\x6a\xd2\x94" + - "\xd5\x18\x0b\x23\x3c\x63\xd6\xc1\xe5\x6d\x6e\x7c\x80\xbe\x51\x34\xbf\xb8\x2e\xde\x84\x7b\xe8\x1e\xda\x0f\xad\xf0" + - "\x53\x95\x4b\xff\x90\xfa\x7f\xc4\x03\xb9\xb9\x51\x49\xbd\xb6\xd7\x85\x2f\xc3\x11\x31\x2e\x16\xc7\xbf\x82\xa8\x15" + - "\x46\xdf\x2e\x20\x00\x03\x71\x13\x57\x15\x2d\x15\xb6\x52\xd8\xcb\xcd\x14\xa9\x7f\x04\x7d\x3e\xc2\xae\x47\x6a\x0b" + - "\xd6\x81\x42\x87\xcf\xd4\x31\x59\x72\xc1\x4f\xdc\x9d\x80\xc9\xaa\x23\xed\x8f\xa5\x9b\xac\x5f\x70\x53\xbe\x24\xda" + - "\xef\x27\xe1\x2c\x4c\xb5\xe1\x14\x01\x4e\xd6\x27\x6a\x22\x64\xff\x20\x37\x58\x54\xb5\xcb\xb8\x2a\x8b\xba\x8e\x56" + - "\x2b\x19\x25\xcc\x30\x39\x01\x10\xa6\xae\x4d\x3a\xf0\x2d\x7e\x5a\xe7\x7d\xaa\x22\x5a\x95\x61\xba\x42\x00\x61\x6f" + - "\x78\x80\x8f\xca\x1a\x97\x17\x18\x0c\xc7\x25\xd9\xd5\x3e\x55\x72\x0f\x9c\x11\xfb\x4e\x3d\x1c\x6c\xa8\xfc\xa1\x72" + - "\x05\xf6\x07\xea\x60\x43\x31\xc9\x85\xcb\x43\xdd\xd1\x25\xaa\xce\x0b\xcf\x62\x33\xd1\x08\xed\xfe\xd9\x53\x62\xc7" + - "\xf5\xd5\x43\xfa\x7e\x57\x3c\xde\x38\x33\x75\x63\x96\xe1\xac\xc8\x37\x02\x9b\x78\x68\x44\x12\x27\x2b\xfc\x09\xac" + - "\x6f\xe9\x8f\x1e\x6d\x99\xda\x78\x38\x6e\xa1\xd0\x95\x1f\xcb\x49\xd8\xb8\x7f\x5a\x5f\xdd\xeb\xc6\x87\xed\xa2\x29" + - "\x40\xaa\x02\x12\x13\x15\x08\x3f\xc2\xa6\x89\x10\x71\x07\xc6\x9d\xba\x84\x06\xc8\x99\xe4\x4d\x2a\x53\x63\x82\x61" + - "\x4f\xef\xa1\xd0\x10\x31\x16\x1b\xd7\x88\x3a\xe3\x54\x44\x0e\x87\xb8\xb7\xed\x8b\x92\x69\xf4\xe6\x46\xc5\xcf\xa2" + - "\x4a\xc8\x92\xd3\x6f\x69\x8b\x37\x35\xdb\x52\x21\x2f\x35\xe2\xd7\xe8\x82\xb2\x32\x20\x57\x0c\xb8\x3f\xea\x71\x95" + - "\x2a\x80\x47\x34\x8d\xa9\xac\x7c\x61\xc9\x90\x5a\x67\x79\x1e\x3a\x23\x70\x65\xba\xb1\xf2\x94\xe5\xc0\xbd\x2a\x09" + - "\xf4\x52\x2e\x0b\x08\x44\x69\x51\x13\x14\x7c\x0f\x45\x11\xa8\x90\xeb\xa9\xcb\x01\x83\x18\x92\x61\x0b\x5d\xb0\x6a" + - "\x95\x1c\xec\x5b\x7a\x67\xc5\x1f\xf8\x0e\xe2\xbe\xa0\x9d\xe1\x3d\x67\x38\xb4\x1f\x5e\xb5\xbe\xac\x4a\x7b\x9d\xf7" + - "\x0e\x2a\x9d\xf6\xb1\x06\x9c\x2b\x8a\xe0\xa9\x87\x74\xf5\xdb\x25\x8c\xf8\x34\x3f\x9b\x03\x31\x9b\x08\x6e\x7c\xc8" + - "\xed\xbe\x14\xd3\x57\x73\x2a\x12\xcf\x88\xd9\x69\x48\xec\xac\x61\xdb\xa4\xe8\xc3\x01\xec\x0f\x25\xdb\xb1\x4d\x7d" + - "\xb8\xb9\x51\xdc\x1b\xcb\xa5\xe0\xb7\xc7\xa0\x54\x73\x1b\x8d\x63\xf2\xeb\xdb\xb6\x26\x79\x98\xc2\x69\x77\x0a\x6b" + - "\x58\x0e\x3b\x57\xba\x51\x7b\xf0\x9e\xc4\x01\xf4\x05\xac\x09\xa3\x08\x5f\xd1\x86\xc4\x37\x6e\xb5\x2f\x75\x96\x83" + - "\x43\xae\x1d\x1b\xc0\xf4\xe6\x3a\x76\xa7\x00\x2f\x64\x2e\xd8\x62\xc9\xa7\x57\x40\x69\xa2\x5d\x1d\xb1\x44\xdd\xa5" + - "\xdc\x20\x03\x16\x29\x3a\x73\xd4\x6f\x80\x7c\x6d\x1f\xa5\x96\x45\x20\xe8\x85\x3f\xa2\x5d\xaa\xf7\xa8\xc3\x71\x97" + - "\x89\xd1\xde\xb4\x71\xf0\xb7\xa5\xe5\xbb\xf4\x1b\x79\x95\x2e\x76\x6f\x23\x05\x39\xf2\xd5\xb4\x1d\xe8\x3e\xb6\x54" + - "\x3b\x80\x14\x38\x1a\xa9\x1f\x75\x91\x4d\x08\x18\x41\x2f\x97\x55\xa9\x27\xe0\xe2\x52\x3b\x3f\x16\xb0\xaf\x97\x00" + - "\xf5\x38\x29\x8b\xc2\x4c\xec\x36\x25\xc7\x8f\x16\xa9\x1c\xd6\x93\xaa\xcc\xf3\x77\xc0\x44\x75\xbf\xfb\xc1\x4c\x1b" + - "\xa2\xa8\xb7\xed\xd3\x78\xed\x9c\xdf\xc8\xce\x8e\x7c\xdc\x91\xea\xee\x93\xa7\x28\x98\x9c\xe0\xce\xa7\xfe\xe5\x59" + - "\x61\x74\x15\x30\x26\x91\xd4\xba\xf4\xe2\xcd\x1a\x34\x27\x9b\x8b\xee\x0f\x3f\x57\x7b\x10\xbc\x30\x9c\x94\xb5\x7d" + - "\xff\x10\xff\xfa\xf1\x95\xea\xab\x91\x7a\x74\xd8\xd1\x9d\xe9\x55\xfb\x8a\x82\x3b\x8c\x17\xf4\x5b\x7b\x70\x9f\xe3" + - "\xc1\x7d\x7a\x30\xfc\x4a\x81\xec\x0d\x1a\x68\x08\xf4\x11\x35\xe1\x05\xff\x7f\x31\xf7\xee\xdf\x6d\xdb\xd8\xfe\xe8" + - "\xcf\xce\x5a\xfe\x1f\x10\xa6\x37\x95\x62\x59\xb2\xd3\xa6\xd3\x2a\xe3\xf1\x4d\xf3\x98\x66\x6e\xd3\xf4\x34\xe9\x69" + - "\xcf\x72\x7c\xba\x60\x11\xb2\x18\x53\xa4\x86\xa0\xfc\x68\xed\xff\xfd\x2e\xec\x07\xb0\x01\x52\x76\x3a\xe7\xf1\xfd" + - "\xce\x5a\xd3\x58\x24\x88\x37\x36\xf6\xf3\xb3\x7d\x00\xbb\x0c\xbd\x9e\x5f\xfe\x00\xf7\x78\xb1\x34\xcd\x6b\xe0\xb2" + - "\x9a\xf9\xa5\x6b\xcb\x62\x24\xf3\xe1\x14\x65\xa9\x6b\x27\x87\x5c\x3b\x19\x63\xf8\xd9\x84\x8a\x55\x7d\xc1\xc8\x87" + - "\x53\x8a\x47\xbe\x1e\x26\xf1\xcc\x08\xea\xd9\x09\x6a\x5e\x3b\x51\x60\xf2\xcf\xb5\x59\x1b\xd8\x2c\x58\x3d\x2a\xb3" + - "\x8a\xba\x82\x48\xd3\x12\x2c\xf0\x07\xea\x88\x1d\x08\xfd\x53\xcc\x48\x03\xab\x8b\x45\xd0\xa7\xed\x51\x36\x55\x47" + - "\x91\xca\xca\x1d\xb7\xae\x16\xa1\x25\x51\x04\xb9\x72\x40\xc9\x20\xd9\x28\xfa\x82\x54\x0a\x3e\xe7\x28\xee\x26\xe0" + - "\xe2\x47\xb1\x7a\x09\xa7\x25\x76\x21\xa1\x22\xc4\xd2\x63\xc9\x87\x0f\x59\xb1\xf3\x45\xd7\x30\x79\x1b\x87\x2f\x15" + - "\x60\x10\xc9\x54\x78\x5d\xa7\xc0\xa2\x52\x85\xc7\xbb\xc2\x38\x1d\x1f\x11\x8d\x22\xc5\xb2\xb0\x14\x68\xca\xaa\x0f" + - "\x14\x54\x6e\xe9\xc5\xf5\x35\x7e\x8a\x01\x60\x97\x60\x00\xdb\xa1\x19\x11\x69\x14\xa2\x09\xd8\x74\x79\x42\x95\x43" + - "\x3f\x33\x76\xa6\xc1\xcf\x6a\xdf\x6b\x72\x2e\x5f\xb7\xa6\xd1\x2c\x57\x3d\x8e\xf5\x38\xd8\xd9\x87\x0f\xf1\x0f\x9c" + - "\x41\xd4\x76\x14\x6d\x64\xad\x79\xdf\x40\xb6\xba\xaa\x80\xe8\x25\x82\xc4\x3e\xb9\x12\xdd\x8a\x56\x86\x85\xad\x50" + - "\xad\xc4\x47\x09\x36\xe9\x0b\xa3\xd6\xab\x1c\x54\xad\x0b\x43\x5b\x48\x5c\x76\x98\xb1\x84\x33\x5a\xf0\xc6\xc0\x7f" + - "\x01\x73\x21\xca\xa3\x86\xe3\x3c\x37\xe5\x15\x52\xe1\x4b\x54\xe2\x82\x71\x47\xab\xaa\xae\x7e\x37\x4d\x8d\x5d\x72" + - "\x2b\x4d\x47\x5b\xae\x19\x2f\xc2\xf5\xb5\xda\x17\x30\x1d\xd2\xad\xf5\xf5\x1c\x32\xcd\x15\xf5\xda\xaa\x82\x67\x56" + - "\xb9\x9a\x4d\xae\xea\x75\x3b\x52\x79\xbd\x76\x37\x38\x02\x92\x5f\x18\xb0\xc9\x3e\xf2\xc0\xe4\x8f\x42\x55\x3f\x43" + - "\x84\x0f\xb1\x6e\x00\xa2\xe0\xbe\x84\x1f\x1a\x92\x10\xd8\xda\x7d\x8f\xd0\xc9\x7a\x36\x03\xff\x16\xf0\x54\xb5\xc6" + - "\x28\x5c\x69\x6d\xd5\xba\x62\x3c\xcc\x13\x83\x7e\xd8\x72\x23\xe0\xbf\x4e\xd8\x1e\x3f\xc9\xa2\xec\x22\xcf\x72\x70" + - "\x71\x70\x9c\x06\x20\x5a\xf0\x87\x34\x17\xf8\xef\x04\x2b\x60\xcb\xd2\xe6\xbb\x18\x0f\x39\x7e\xb4\xa3\xfc\xdd\xeb" + - "\x57\xe7\x67\x5c\x66\xa8\x6d\xa4\xda\xba\x84\xa9\xab\x4e\x61\xea\x54\xdd\x80\xcf\x15\xda\xe1\x02\x45\xf0\x5f\x3f" + - "\xab\x72\x75\xd2\x18\x7d\xc6\x6e\xa1\x65\x5d\xaf\x1c\x6b\x82\xc3\x2b\xe4\x2c\xb8\x23\x6a\x9a\xb9\x99\xb5\x80\x5d" + - "\x81\x0e\x75\xe7\xe4\xd0\xb1\xd0\xb9\x32\x55\xbd\x3e\x5d\x90\x22\x50\x71\x70\x3e\xd6\xe4\x36\xff\x80\xe7\x4e\xf4" + - "\x44\x4d\x28\xb7\x31\xd8\xf8\x42\x59\xc8\x97\xb5\xbb\x1b\x1f\xb3\x6e\x1c\x2e\x8d\x3e\xdd\xe0\xe1\x20\xe2\x9e\x16" + - "\xfa\x53\xd2\x76\x40\x0f\xfc\xf6\xc4\x3f\xae\xaf\xe5\x46\xdd\x7b\x2a\x99\x1a\x71\xfe\x82\x6f\x1c\x38\x30\xec\x1c" + - "\x4c\x76\x0f\x54\x5b\x9f\x99\x2a\x71\x40\x42\x9f\x90\xbc\x46\x6f\x43\xef\xf7\xe7\xef\x8d\x88\x69\x02\xfd\x0a\xd1" + - "\xdb\x7d\x47\x51\xa3\x6d\xb3\xc3\x43\xc1\x97\xec\xd5\x47\x8f\x1e\xab\x63\x6f\x98\xdc\x09\xcf\x7a\x35\xaf\x2d\x69" + - "\xb4\xdc\x12\x1d\x7b\x5d\x3c\x6c\x05\xea\x96\x55\x0c\x92\x6e\xaf\xaa\xd9\xa2\xa9\xab\x7a\x6d\xcb\x2b\x14\xa6\x20" + - "\xd1\x8b\x7c\x2c\xc1\xa7\xe1\xb3\x57\xee\xba\x26\x75\x8e\x35\xed\xfb\x62\x69\xea\x75\xdb\xd1\x31\xc2\xad\xae\x84" + - "\xfe\x17\x38\x0c\x09\x78\x30\x50\x5c\x86\x4e\x47\x05\xf5\x0e\x3d\xa6\xfe\x44\xfd\xdd\x5d\xa9\x6e\x03\x78\xd1\x0f" + - "\x73\x34\x41\x47\x80\x06\xe8\x2a\xc7\x54\xf8\x7e\xce\x45\x4c\x6e\xf5\xea\x72\x40\xbe\xb7\x14\x7c\x8e\x96\x65\x01" + - "\x94\xbd\x28\x66\x0b\x8f\x43\x81\xe6\x1e\xdd\xb6\x78\x8d\x13\xdc\xfb\x14\x5d\x02\x03\xf2\x0e\x1b\xd6\x31\x16\x9f" + - "\xb0\xb6\x81\xbf\x39\x67\xb8\xeb\x7d\xf0\xc2\xab\x95\x2e\xcb\x60\x7f\x61\x84\x1e\x59\x0b\x12\xa9\x5b\xeb\x7a\x0c" + - "\x2c\xf1\x59\xb1\x82\x48\x06\x05\x2c\xac\xab\xed\x27\x32\x26\x46\x43\x3b\x88\x47\x4a\xd8\x03\x4f\x53\xac\x01\xe5" + - "\xc1\x06\x76\xfb\xa6\x66\x0b\x03\x9c\x0e\x12\xdb\xd1\x53\x3f\x3d\x47\x21\x9e\x7d\x87\xa2\xa1\x1c\x8b\xcb\xef\x44" + - "\x88\x78\x78\x49\x1a\x0e\x09\xc1\xdd\xd7\x34\xd4\x31\x26\x3f\x7c\xae\xd3\x83\x50\xc5\x95\xb0\xf9\xc6\x15\xe9\x04" + - "\xf5\x45\xbc\x14\x99\x09\x90\xda\xfa\xdd\x22\x76\x42\xcb\xca\xdd\xad\x59\x5d\x96\x86\x33\x0b\x12\xb1\x36\x8d\x95" + - "\x5c\xc8\xd1\xb1\x1a\x8e\x31\x6d\xa2\x2c\x90\x3d\x02\x93\xe9\x6d\x51\x80\xa1\xf2\x60\xbf\xf9\xd4\x28\x40\x98\xb2" + - "\x01\xf3\x8b\xa1\x26\x1f\x53\x43\x6a\x32\x3f\xbc\x51\xcc\x42\x26\x18\xd9\x4c\xbe\x2a\xc3\xfe\x6c\x45\x1c\x08\xd0" + - "\x43\x52\x48\x4a\x88\xe6\x39\xe5\x87\x59\x1f\xee\xaa\xb2\xa0\x16\x67\x02\x3d\x79\xa4\x3e\xda\x45\x51\x81\xcb\xa6" + - "\x5b\xd0\xc2\x62\x28\x04\xe4\xb7\x40\xbc\xdd\xd0\x61\x77\xdb\x39\xbe\x9f\x64\x54\x76\xe5\x53\x75\x99\xcf\x8b\xc6" + - "\x8c\x42\x48\x26\x84\x01\x53\x2c\x1a\x1e\xe1\xaa\x58\xca\xd4\x92\x75\x53\x9c\x06\xc3\x5c\xd7\xa7\x1e\x1e\xfb\xe0" + - "\xb4\x8e\xc8\x97\x46\xab\x21\x2e\xaf\x6e\x35\x21\x1a\xf5\x87\x50\xce\x2f\x9d\xc0\x22\x13\x98\x2c\x74\x95\x97\x46" + - "\x81\xa0\x31\xa5\xbc\xb8\xab\xa6\x5e\x16\x16\xae\x34\xb4\x97\xba\xf9\x1a\x43\x11\x5e\xf7\xc4\x1f\xef\xb7\x20\xa8" + - "\x88\xb6\x32\x19\xd9\x8d\x1a\xce\x75\x05\x25\xf3\x4e\x64\x77\xfa\x9a\xef\x42\x9a\x59\xef\x53\x07\x6a\xb8\xb1\x7b" + - "\xf4\x54\x7c\x17\x9e\x4a\x58\xb3\x38\xb4\xe9\x7e\xd2\x44\xb0\x43\x52\x1b\x09\xe0\xe3\x4d\x50\xa6\xc6\x5f\xee\xec" + - "\x10\x33\xe4\x96\x74\x8c\x11\x51\x5d\x7b\xd6\x64\x42\xd7\x30\x26\xc1\xd1\x67\xa0\x6d\x63\xdf\x4d\x76\xec\x03\x80" + - "\x6a\x5c\x83\x06\x6f\xbb\x13\x03\xe8\x64\x26\xe7\x5a\x30\xb0\x06\xab\xe1\x4f\x90\xdb\xb8\xb5\xfd\xa4\xd3\xbb\xbb" + - "\x4f\xe5\x5c\xd0\xba\xc1\xbb\x78\xc5\x7c\x3a\x60\x3f\x3d\xe9\x14\xa7\xf3\x14\xa5\x07\xf7\xfb\x0a\xee\xa9\x09\x01" + - "\x4b\x9e\x9b\x66\x5e\xd6\x17\xa0\x4f\xe5\x5d\xd5\x8d\x7e\xd9\x47\x55\x14\x3b\xb8\x71\xf0\x11\xc8\x07\xec\xeb\xe6" + - "\x9f\x0d\x45\x6c\x4e\xea\xfb\x5f\x63\xde\x20\x5b\x19\x7d\x66\x19\xcd\x1e\xfc\x08\x67\xb5\xbb\x99\xcb\x52\x7d\x11" + - "\x3a\xe5\x48\x35\x24\x35\xb0\x3e\xa3\xd6\xeb\x97\xdf\xec\xee\xef\xb9\xdb\x92\x02\x79\x01\x83\xca\xf1\xa4\x08\x04" + - "\xd7\xf9\x14\x01\x8f\xf8\xf9\xaf\xee\x32\xa4\xcf\xf8\xd9\x7f\x80\x62\xd3\x1a\x8f\x9c\x01\x00\xca\xde\x9b\x12\x8e" + - "\x98\xaf\xd7\xc9\xf4\x18\xb3\xc8\x8f\x46\xc9\xef\x5f\xd3\x07\xff\x21\xdd\x5c\xdf\x99\xe0\xa0\xe3\xa3\xa0\x12\x4f" + - "\x1d\x84\x0f\x12\xcb\x44\xdf\xea\xc0\x94\x81\xdb\x1e\x84\x48\x7b\xcf\x3e\x0f\xed\xb5\xd0\xe7\xe8\x76\x9c\xb7\x8b" + - "\x09\x56\xc3\xbe\x36\x30\xf4\x10\x6c\x79\xab\xa3\x5d\xe8\xf3\x7b\x63\x3b\x49\x58\x12\xd8\x3b\x72\x02\x2c\xaf\x28" + - "\x42\x13\xae\x46\x41\x68\x43\x62\x16\x19\x26\x8a\x6c\xed\x27\xc4\x94\xbb\x7d\x96\x26\x32\x8a\xc2\x88\xd5\x50\x4d" + - "\x45\x8a\x17\x4f\xdb\xe2\x3e\x1c\x1c\xb0\x67\x53\x26\x93\x22\x8a\xe1\x63\x34\x1b\xfb\xa7\xc5\xd1\xdf\x9d\xb8\xef" + - "\xc8\x49\x2a\x89\x49\x85\xd6\xe3\xad\x43\xf5\xc4\x9b\xc3\xd5\x43\xf0\x75\x4f\xef\xa4\x5c\x9d\x4f\xa3\x06\x84\xcf" + - "\x4d\xb2\x23\xbb\x25\xf7\xfb\x4b\xfe\x47\xb7\x24\x8b\x0e\x09\x15\x71\xb7\xd5\x64\x51\xe4\x86\x29\x07\xb2\x25\xc0" + - "\xf5\x08\x4a\x40\x46\x51\x8c\x8d\x58\xa1\xb6\x5a\x58\x74\x10\xd8\x83\x14\x78\x49\xe6\x7c\x1e\x34\xe5\x0a\xe8\x7e" + - "\x4c\x5e\x13\xee\xea\xc6\x3f\x7c\x5c\x10\x2c\x1e\x3e\xa4\x08\x91\x28\x8a\xc8\x31\x6a\x3e\xd8\xdb\xcd\xbe\x01\x75" + - "\x15\x5d\xc0\x32\x1d\xa6\xcf\x4d\xd5\x00\x73\xed\x6f\xf1\xd2\xb1\xd5\xc0\x60\x93\xde\xc3\xb6\x35\xa0\xf9\xc1\x8c" + - "\xd4\x0d\xba\xcf\x3a\xbe\xfb\x02\xd3\x25\x9c\xd6\xe4\x1a\xbd\x6a\xea\x99\x31\x39\x32\x51\x16\x1c\x52\x2f\x7c\x0c" + - "\xef\xaa\x31\xad\x93\xfd\x30\x89\x0a\x76\x51\xdc\x0d\xd2\x07\x0c\xfa\xfa\xf0\x61\xe8\x92\xf8\xdb\x33\x9f\x1b\x22" + - "\x33\x02\xf3\xe2\xd8\x29\xbe\x32\xe2\xec\x99\x51\xfc\x77\x14\xe2\x0b\xfc\x91\x6f\xe2\xe0\xf6\x1e\x04\x13\x44\xe4" + - "\xc2\x83\xfa\xb4\x40\x61\x9e\x55\x57\x10\xb0\x32\xe7\xf4\x1d\x6e\x3e\xad\x5a\x5b\x9c\x5f\x4c\xdf\xca\x5a\x09\x9f" + - "\xa1\x25\x82\xc3\xdc\x4e\xad\xb2\xe1\xa0\x46\x52\x65\x7a\x46\xef\x7b\x2f\x2b\x30\x84\x61\x96\xc2\x01\x34\x12\x36" + - "\x21\x22\x0d\xf0\x40\x23\xc7\x18\x3e\xbd\x6e\xd7\x77\x4a\x84\x99\xe6\x57\x63\x7c\xb2\x09\xf3\xa0\x97\x4f\x4c\xb0" + - "\x15\x88\x55\x1c\xa9\x3f\x6e\x3a\x11\x0b\x90\xde\x8e\x1c\x80\xd8\x1e\x86\x87\x63\x57\x61\xba\x5c\xab\xc6\x6e\x72" + - "\x07\xc3\x31\xbe\x18\x40\x1c\x62\xd6\x98\x73\xd3\x58\x24\xdc\x68\xd0\xc0\xcf\x86\x49\xc7\xc6\x7e\x44\xf7\xc5\x48" + - "\x02\x40\x40\x82\xbb\xc0\x3e\x3f\xc8\x0a\x4b\xe7\xa0\x68\xd8\x40\xf5\x9c\x70\xd1\xc3\x2d\x25\x55\x44\x6e\x43\xc2" + - "\xac\x7e\x4b\x15\x2c\x2a\xf8\x6c\x65\x7e\x66\x39\x85\x7e\x0f\x13\xee\x9d\xe4\x98\xa4\xd1\x8e\xe8\xb5\x97\x49\xed" + - "\x5c\x74\x3c\xba\xfe\x4d\xb7\xd5\xea\xa5\x35\x29\x8c\x06\x58\x8a\xf4\x70\x4d\xd5\x9e\x14\x52\x13\x60\x8c\xfb\xa1" + - "\x11\xb1\x2f\x23\x40\x8c\xa8\xb6\x48\x0f\x26\x59\xd2\x14\x4a\x23\x52\x52\x75\xbf\xd9\x8a\xd5\x69\xe8\xa6\x24\xd0" + - "\xc4\xae\xaf\xc5\x33\x66\x28\x85\xea\xa1\x2f\xa9\x2e\xd3\x61\xca\x1f\xa5\xaa\xba\x5e\x61\x7a\x4a\xda\x0f\xf4\x8f" + - "\xcf\xf4\xac\x34\xf2\x7c\x17\x4d\xd1\xb6\xa6\xea\x90\x0a\x69\x76\x1d\xf4\x71\x26\x9f\xce\x6e\x0c\x63\xbe\x22\xba" + - "\xe5\xf3\x94\xfb\x79\xda\x27\x13\xbb\xe9\x78\x45\xd2\x30\xc9\xc1\x10\x87\xa8\xcb\x97\xd2\xad\x0d\xfc\x8c\x31\xad" + - "\x3e\x05\x16\x90\xbf\x18\x09\xc0\x20\x0d\x78\xf1\xd1\x47\xab\xa5\x95\xb9\x5b\x89\xfc\xad\xd9\x72\x1e\x5d\xe1\xa8" + - "\x1e\x48\xef\xf0\x6a\x53\x28\x1c\x16\xc7\xad\xed\x4d\x92\x51\x8b\x51\xe8\x50\xc2\x0b\x74\xb0\x48\x52\x9f\xd7\x94" + - "\x1b\xf0\x4d\xc0\x0b\xc1\xc8\xf4\x57\x1c\x0a\xee\xc5\xb1\x4b\xa4\x51\x72\x85\xdc\x2d\x29\x02\x73\xb6\xb6\xa8\x8a" + - "\xbe\x58\xcc\x98\x19\x91\xbd\xa7\x7a\xef\x08\x87\x4b\xa4\x6e\x08\x57\xc3\xc5\xe8\x8f\x58\x13\x31\xa5\x58\x2c\x02" + - "\x83\x4d\xfb\x53\xc9\x98\x3a\x44\x6f\x68\xd5\x3f\xd7\x45\x6b\xd4\x67\xe4\xea\x4c\x2e\x50\x17\x75\xd5\xfa\x03\x62" + - "\xd4\x99\xb9\x12\x49\x24\x30\x57\xb7\x77\x4c\xd1\xa5\xad\xd5\x2e\x64\x93\x74\x53\xff\x39\x8c\xfa\x73\xe2\x7c\x4e" + - "\x00\xc8\x92\x84\xb3\x0b\x13\xa0\x54\x19\xe7\x3c\x73\x9d\xca\x04\x3d\xf5\xfb\x2b\x89\xdc\x66\xa2\xd5\xd9\x7f\x81" + - "\xf0\x6c\x5a\x5b\xb9\x0e\x8e\xa7\x8d\x77\x5f\x28\x8e\x9b\xa7\x87\xc8\xc8\xbb\xa8\x77\xef\xc6\x1f\xf7\x6a\xb6\xbc" + - "\xca\x5c\x5e\x07\x68\x81\x18\x25\x28\xe4\xc1\xe7\x8a\x54\x4c\xc0\x3c\xde\xa6\x09\xec\x31\x2f\x93\x3a\x00\xd5\x4b" + - "\x66\x6e\x9a\x46\x7a\x04\xbe\xa0\x27\x83\x21\x4b\x13\x5d\xed\x0b\x28\x42\xaa\xcf\x5b\xc4\xf0\xc5\x0b\x96\x52\xd1" + - "\x4d\x59\x60\xf4\xc9\xba\xe5\x76\x6b\x8b\xd9\xd9\xd8\x7b\xa3\xde\xa0\x8a\xcb\x3d\xec\xd3\xf1\x90\x09\x14\xf9\xe3" + - "\xd4\xdf\x0b\xd4\x5a\xe2\x8e\x44\xb4\x68\x14\x26\xdf\x17\x40\x72\x50\xef\x7f\x7d\x1d\x5b\x14\x46\x5c\xcd\x52\x17" + - "\x15\x52\x84\x08\xbd\xd8\x4f\x18\x5e\x44\x50\xd7\x8e\x78\xea\xfd\x1f\x77\xa3\xe6\x44\x12\x34\xdd\xcc\x16\xba\x98" + - "\xa9\x59\xa3\xed\x02\x30\x0f\x30\xbb\xbd\x2e\x9d\xec\xb5\xb6\x9c\x53\x6d\x1f\xc0\x91\xf7\xc6\x4f\x18\x17\x79\xf0" + - "\x60\xff\xf1\x97\xdf\xfc\x85\xec\x6a\xad\x59\xae\x20\x01\x1f\x77\x74\xd2\xd7\x0b\xf7\x29\x5b\xe6\xc9\xa3\xf4\x00" + - "\x6a\x76\x9f\x73\x80\x40\xb4\x35\xfa\x36\xc7\x18\xae\x5e\x9b\x38\xfb\xf7\x2b\x8c\x55\x47\x63\xbc\xb5\x95\x56\x14" + - "\x74\xc5\xcd\x5a\xfa\xba\xc6\xb6\x24\xde\x7c\xe3\xaa\x6e\x8b\xf9\xd5\x2f\x45\xbb\xe0\x23\x70\x14\xa9\x97\xd9\xcf" + - "\x34\xcc\xc5\x71\xcc\xb2\x70\x03\x7f\x45\x85\x53\xaa\xef\xf2\x11\xe5\xf4\x79\x9f\xd7\x91\xef\x0c\xe5\x89\xdc\xd0" + - "\x9b\xc0\x9a\x6d\xda\x89\x37\x5e\x37\xac\x49\xbb\xef\xab\x26\x2d\xec\x80\x6e\xa4\xd2\x2c\x11\x0e\x75\x14\x6e\x0f" + - "\x0f\x1d\xc6\x59\x87\xfe\xb8\x91\x04\x81\xf7\x99\x93\xb5\x3b\x45\x31\x22\xf9\x8f\xf8\x12\x9d\x3a\x6e\xff\x46\x10" + - "\x92\x10\xa5\xee\x64\xa1\x1f\x7d\xd5\x53\x49\x77\xa2\x32\x6f\xf1\xd3\xa9\xf7\x3d\x27\x05\x00\x1d\x8f\xe9\xad\x27" + - "\x8d\x77\xaa\xff\xda\xef\xdd\x51\x60\x5d\xed\xd4\x27\xfd\x17\x2c\xec\xb4\xe3\xd7\xe2\x58\x47\x01\x83\x11\xdc\x5a" + - "\xa4\xc3\xbd\xcf\xfd\xe0\x37\xa5\x9b\x2d\xe9\x30\x4f\xe4\x7e\x2b\x2e\x31\x4e\x08\x78\x90\x44\x93\x72\xc2\xd7\xbf" + - "\x6f\xf3\x43\x8a\xfd\xc4\x5b\xaf\x6b\xe4\xe0\xdc\x42\x8e\xc0\xc9\x81\x9e\xd6\x6d\xfd\x32\x1d\x66\x7a\x82\x83\x65" + - "\x2f\xd2\x11\x00\x46\x5c\x05\x36\x63\x84\xb8\x6e\x6b\x30\xb5\xea\xb2\x0c\x1e\x1c\x36\x54\x11\xb0\x2c\x2e\x0c\xda" + - "\xfe\xd0\x3a\xa3\x1b\xf2\xbc\x08\xa4\x82\xbb\x75\xb8\x89\x68\x08\x2e\xbc\x9f\x70\xa7\xfe\xcb\x21\x0d\x13\x17\x8d" + - "\xd4\x0a\x9f\x4e\x7c\xee\xa2\x3e\xfb\xdd\xb8\x22\xc8\xad\x00\xc7\x1c\xb5\xbc\x17\xe0\xca\x79\x45\x78\xaf\xa5\xb6" + - "\xad\xf2\xc9\xc2\xe3\x99\x72\x44\xc8\xe3\x4a\xe0\x48\x3b\x2b\xf6\xa9\xb4\x64\xe4\x3f\x0d\x44\x25\xd1\xa6\x88\x9a" + - "\x5c\xab\x7f\xa6\xa2\x78\xdf\xf9\x49\xbf\x11\x37\x2f\x32\x4a\xf2\x1e\x80\x27\x48\x5a\x7b\x84\x8b\xdb\xce\x0b\x0b" + - "\x91\x9f\xba\x6e\xde\xef\xb8\x87\x43\xb9\xc5\xd4\x18\x19\xfd\xe2\xfe\x48\xd3\x14\xd5\x9e\xc4\x37\x49\x2f\x62\xaf" + - "\xcc\x21\xd2\xb1\xd4\x2b\x3f\x4e\x41\x83\x22\x33\xae\x08\x38\xf4\xe2\xc6\x2b\x7f\x72\xd3\xd9\xa1\x00\x05\x36\x38" + - "\xf7\xbc\xa5\xe1\x25\xe4\x4a\x66\xc3\x0b\x9e\x8d\xe0\xb8\x08\x91\x19\x29\xd5\x2f\x66\x67\x9c\x93\x2e\xbd\x52\x5c" + - "\x9d\x53\x31\x7d\xf0\x90\x0c\x83\x49\x87\xe0\x29\xee\x8d\xed\x7b\x5b\xc1\x9a\xa8\xdb\x56\xcf\x16\x3e\xbd\x8e\x65" + - "\x58\x40\x06\xf0\x61\xe3\xb8\xdc\x42\xa7\x0d\xa8\x9d\x92\x16\xf8\x85\x02\x06\x07\x55\x2e\x69\x19\xf7\xb0\xb3\xcf" + - "\xbc\x55\x0d\x3f\x9c\xeb\xa2\xec\x7c\xe8\x1e\xd2\x7b\x66\x5b\x93\x12\x84\x73\x38\x4c\x50\x1e\x9f\x89\x8b\x3a\x99" + - "\xd9\x67\x61\xdb\xa1\x62\x97\x6c\xf0\xe9\xbd\x24\xd2\x2b\x45\x7a\xbf\x9e\x3d\x92\x8a\x26\xfe\x3b\x92\x3f\x9f\x06" + - "\x4e\x00\xb3\xc4\x3c\xca\x58\x4c\x94\x84\x81\x0b\xc0\xbf\x22\x8e\x57\x0a\x94\xde\xce\x8d\x6c\x52\x7c\x83\x78\xba" + - "\x8e\x35\x44\x7c\xdf\x27\x53\x5e\x11\x48\x96\xc8\xb4\x5b\x1d\x77\x86\x83\x0d\x1e\x0e\xfd\xc5\xc7\xeb\xca\x2e\x8a" + - "\x79\x3b\x10\x13\x1b\x8e\xed\x88\xe8\x13\x91\x0b\xb9\x1c\x21\xcd\xd5\xaa\x81\x04\xc5\xd1\x82\x24\xcf\xfa\x7c\x6f" + - "\x37\xb7\x9c\xaa\x1d\xd3\x0f\xf1\xd6\xef\xeb\x6f\x1a\x3e\x6c\x57\x06\x6e\x3b\x11\xb4\xe9\x9e\x04\xbd\xcc\x5c\xba" + - "\x8c\xd4\xab\x16\x15\x23\x26\x07\xc7\x70\x8a\xe6\xc4\x3a\x0e\x0e\x54\x86\x40\x47\x99\x3a\xec\x63\x1d\xb1\xdc\x50" + - "\x51\x44\x0f\x1f\xa5\xa9\x6b\xe3\xfa\x5a\xdd\x9f\x57\x80\x8a\xc1\x41\x7f\xdb\x41\xf7\x1a\xed\x5b\xae\xe6\xe1\x43" + - "\xea\x2b\x08\x8f\x9e\xb5\x0b\xcf\x0c\x31\x9d\x49\xbd\xfc\x97\x00\x39\x93\xd5\xfb\x28\x4c\xff\x4d\x88\xef\xae\x57" + - "\x6d\x10\x77\x0e\x44\x20\x45\x3d\x9f\x53\x74\x08\xcd\x49\x5c\x52\x62\xab\x1d\xc6\xef\xc0\xcb\x2d\x7a\x52\x54\x32" + - "\x42\xc3\x8d\xc6\x86\xf9\xf4\x8f\x8e\xe2\x6a\x8e\x03\xd0\xaf\x2f\xe2\x63\xb8\x3c\x01\x0d\x40\x98\xee\x63\x74\xb9" + - "\xd8\x05\x4e\x27\x24\x0d\x98\x80\xe3\xc4\xee\xdf\xc0\x60\x2f\x8c\x80\x54\x5c\xe0\xd7\xc9\x87\x04\x4c\x43\xbb\x59" + - "\xbc\x81\x6a\x22\xab\xdb\xbf\xb9\x17\x38\xad\xae\x1c\xa6\x79\x73\x7f\xf1\x86\x08\x73\xed\xa9\x6d\x57\x24\xdf\x44" + - "\xd5\xb8\xca\x40\xd7\xe8\x89\x88\xa8\xeb\x09\x9e\x0b\x3d\x8e\xb5\xfe\xe3\xdc\x90\x17\x03\x46\x4a\x8b\x72\x69\xf0" + - "\x3f\x67\x53\x5a\x85\x5c\x6b\xbd\x31\xfa\x73\x9d\x9b\xf7\xf5\xb4\x7b\xe4\xda\x3a\x1c\xbb\x98\x88\x6f\x93\x61\x04" + - "\x0d\x72\x57\xac\xcd\xf6\x66\x73\x3d\x6f\x4d\x13\x70\x51\xc9\x93\xac\xad\x11\x79\x44\x46\x47\xb3\xc3\x12\x3b\xf8" + - "\xa8\x21\x9a\x8e\x3d\x0c\xec\xc8\x89\xff\x64\xe3\x08\x3a\x38\x01\x73\x11\x40\xce\x3c\xce\x1c\x94\x1a\xbb\xf1\x0d" + - "\xc7\x54\x72\xf0\x87\xf2\x38\xc1\x6d\xad\xf8\xf4\xf7\x0d\xd0\xc7\x74\xd0\xa7\x5d\x51\x6b\xe3\xa7\x22\x5e\x15\x02" + - "\xc0\x0e\x54\xbf\x21\x0c\x4d\x75\x5e\x5c\x75\x32\x88\x2f\x0a\x95\x77\xc8\x5e\x68\x83\x44\xc7\x5a\x5e\xce\xbd\xf9" + - "\x56\xdf\xae\xd0\x73\x13\xe0\x60\x67\xf5\x0a\x20\xb3\xa1\x65\x5b\xab\x95\x69\x76\xbd\xab\x04\x91\x18\x54\xc5\x9c" + - "\x18\x55\xd6\xb6\x0d\x02\x16\xb9\x72\x09\x55\x1c\x6e\xbd\x0d\xc2\xb8\x1a\xc2\xae\xd4\x94\x42\xd9\x77\x07\x43\xe2" + - "\x82\xbb\x05\xb8\x38\xcf\x8b\xaa\xb0\xe0\xbd\x42\xe2\x80\x55\xc5\x72\x69\xf2\x42\xb7\x86\xfd\xba\xd1\x7d\x06\xbe" + - "\xbe\xbe\x4e\x3d\xbd\xb0\x2b\x19\xd6\x93\x45\x8a\x4d\x30\x5e\x81\x59\x4e\xe0\x09\x24\xfe\x4e\x72\x1e\xc7\x58\x09" + - "\xa4\x7a\xf7\x0f\xe3\x28\x68\xdf\x0b\x1c\xa0\xa0\x36\xe8\x4a\x86\xbe\x17\x21\xec\x5f\xd6\xe4\x23\xa3\xe1\x35\x1d" + - "\x62\x59\xcf\x28\x2e\x1d\x42\x8b\x12\x29\x18\xdd\x69\x01\x0c\xf2\xdf\xf0\xbb\x44\xca\x42\x64\x8c\x7a\xf5\x6f\x44" + - "\xf1\xc2\xa7\xa9\x2a\x1c\xcb\x05\x84\xc5\x96\xc2\xde\x59\x27\x99\x3e\xc6\xd9\xf4\xcd\x21\xc5\x89\x22\x8a\xf1\xb6" + - "\x01\x77\xdd\xfb\x12\x57\x85\xdb\xe4\x6f\x0f\xc4\x00\xb0\xee\xf0\x5b\x38\x99\x7a\x20\xd4\xae\xb9\x99\x7c\x51\xc2" + - "\x57\xc4\x00\x40\xbb\xb8\x1c\x51\x34\x33\x93\x4d\x57\xe4\xfa\x1a\xae\x81\x11\xe7\xbe\xfc\x13\xc0\x0d\x90\x89\xc2" + - "\xf0\x65\xe2\x61\xa5\x03\x17\x49\x7d\xe0\x80\x5e\xfc\xbd\xa3\xb2\xe0\x33\xc8\xb8\x4c\x20\xb6\x08\xbb\x06\xfe\xa6" + - "\x97\x6e\x9f\x77\x1d\x1b\xfd\x6d\x11\xf4\x7b\x64\x2b\x8a\x34\xfe\xee\xab\x38\xff\x82\x7c\x00\x0b\x2a\x0e\x8a\xdf" + - "\x2b\xe9\x87\xc9\x89\x89\xc4\xef\xc4\xee\x00\xdd\x0d\x55\x7e\x72\x2f\x1e\x3e\x54\x4d\xb3\x66\x6c\x1a\x1e\x8b\x40" + - "\x11\xbb\xb3\x73\x2c\xcd\x7b\xd3\xc3\x76\x6a\x16\x39\xc0\xc8\x36\xcf\xca\xe3\xe3\xdd\xdd\xa7\xc9\xac\x61\xa9\xd0" + - "\x41\x44\x88\x38\x40\x2f\x56\x70\xd6\x23\x64\x5a\xcf\x71\xa4\x5f\x08\xee\xe3\x6a\x65\xe4\x38\xd2\x92\x82\x38\xc5" + - "\xc7\x09\x0e\x1f\x6f\x2f\xa1\x3f\xe5\x2a\x40\xa2\x99\xb1\x8d\x70\x14\x6b\x70\xe2\xd0\x0d\x94\xb2\x31\x03\xed\x65" + - "\xcb\x56\x08\xac\x9b\xe2\xad\x41\x9d\x03\xce\xee\x17\x1a\x72\x81\x21\xb6\x20\xd7\x40\x3b\x34\x38\xa2\x81\xcf\xe6" + - "\x8c\x74\x66\x45\x13\x9c\x3a\xbd\x0c\xcc\xe9\xb3\xa0\x24\x8d\x84\xab\x3b\x59\xb7\x98\xed\x1a\x5b\xbf\x52\x17\x06" + - "\x54\x74\x30\xfe\xb0\xa3\x79\xfc\x8e\x07\xef\x28\x90\xfa\xd9\x20\x58\x98\x1e\xdc\x13\x80\x1b\x03\xb2\x9e\x52\xd0" + - "\x0e\x0c\x4c\x1f\xdd\x08\xa0\xd4\x4c\x32\x7a\x21\x07\x6e\x21\x15\xb8\x4a\x77\x1f\x69\x2a\xc2\x0b\x8f\x5b\x3d\x22" + - "\x1d\x99\x22\x2d\xb0\x37\x87\xf6\x14\x42\xfa\xe2\x4b\xde\x4a\x61\xbc\x9c\x8b\x8d\x1e\xe2\xbf\xb1\xca\x92\x57\x0e" + - "\xdd\x5c\xc4\x75\x3d\x2f\xf5\xa9\x02\x33\x7b\x71\xee\x98\x0c\xd7\x17\xbc\x39\x74\xab\xc3\x4d\x4a\x4a\x4b\x5f\x0d" + - "\xdc\x9f\x61\x17\xce\x8b\x86\x38\x8d\xd8\x43\x37\x2c\xea\x48\xa4\x27\xde\x80\x2b\x11\x11\xb3\xf0\x4c\xf0\xd7\xa3" + - "\x88\x01\x10\x27\xa4\xe4\x00\x78\xc7\xc4\x52\xc2\x25\xc9\xa1\x00\x5c\x01\x8e\xc5\xc3\x36\xfe\x8f\x50\x96\xdb\x09" + - "\xc9\xa7\xd1\x91\x88\xc9\xf9\xf3\xd4\x22\x9e\x8b\xe0\x15\x4b\x64\xc3\xc9\x30\xd8\xab\xbb\x27\xe5\xee\xfc\x29\x34" + - "\x2f\x50\x61\x74\x45\xc4\x4f\x78\x23\x85\xf1\xf7\xbe\xef\x8a\x52\x3d\xe3\x43\x61\x68\x3e\x4f\x36\xb1\x64\x77\xc4" + - "\xde\x8d\xdd\x33\xfb\x91\x49\xc9\x19\x72\x44\x9e\x83\x23\x76\x7b\xbc\x05\xa0\x14\x2c\xb1\xd6\xbe\x92\xd2\x7a\x25" + - "\xfd\x18\x3a\x0f\x6f\xd3\x85\xa4\x82\x07\x43\x55\x91\xfe\x23\x5c\x53\x1d\xbd\x88\x47\xb9\x42\x8e\x15\xba\xc4\xd9" + - "\xc1\xf1\xc4\x78\x38\xaf\x98\x6f\x65\x71\x8a\x63\xbb\xd0\x69\x06\xb7\xde\x5d\x32\x55\x84\x32\xe9\x03\xcb\x38\xa1" + - "\x32\xa6\x8a\x99\xad\x6d\x5b\x2f\xc5\xfe\xeb\x82\x16\xda\xb2\xc8\xcd\x8b\xfa\xa2\x9a\x52\x27\x70\xfa\x81\x84\xc2" + - "\xbb\x9f\x57\xfe\x0d\x2c\x48\x78\xf3\x9e\x20\xc1\xe8\x2d\x2d\x20\xbc\x77\x52\xf0\xeb\x6a\xaa\x84\x9c\x48\x0e\xa1" + - "\x37\xfc\xfa\xed\xba\x8d\xdf\xe3\x72\xfb\xf7\x5c\xbb\x2c\x42\x4d\xa8\x9b\x04\x3e\x11\xe7\x4d\x7a\x03\xfd\x77\xac" + - "\x7c\xbc\x44\xc1\xed\xe9\x93\x16\x25\xba\x23\x20\x99\xda\x53\x09\x1f\xd0\xef\x8a\x00\x86\x46\xf7\x45\x12\xc2\xd7" + - "\x7f\xf3\x90\x19\xa4\x27\xe8\xb0\x9b\x8d\x37\xa5\xac\x81\x78\xc0\x1b\x4f\x7b\x43\x5c\x1c\x67\xa2\xb0\x68\xd0\x83" + - "\x52\x0b\x8d\xe9\x10\xd9\x0f\x07\x92\x85\xa1\x87\x62\xee\xaf\xff\xfb\x68\x40\x18\x46\x94\x18\x10\x75\xa8\x91\xc0" + - "\x11\x24\x54\x75\x77\x37\xd0\xd4\xd4\x07\x36\x1a\x40\x82\xb6\x08\x70\x0c\xf5\x6a\xc0\x04\xa6\x37\x58\x33\x81\x82" + - "\x18\xf3\xb8\x05\x23\x23\x3a\x17\x4d\x34\xdb\x59\xf1\xfd\x53\xee\x13\x8f\xb3\xa7\x33\xba\x69\xa9\x37\x82\xcd\x4f" + - "\xea\x14\x1d\x4e\xfb\x56\x54\xad\x69\x10\xe7\x7a\xff\x8b\xe4\x1d\x7b\x2d\x26\x5b\x47\xcc\xd2\xeb\x3c\x5a\xdb\xd7" + - "\x39\xc2\x4d\xbe\xa6\x4a\x25\x44\x0c\x9a\x74\x7a\x1a\xde\xd4\x33\x92\x70\x93\xc6\x41\x6e\x0c\xf5\xfb\x5e\xb8\x4a" + - "\x42\x1f\x1c\x01\xed\x59\x08\x52\x82\x12\x8a\x49\x59\x5f\x4c\xd5\x57\x7b\x7b\x48\x06\x6c\x3b\x55\x8f\xf1\xc7\x64" + - "\xa2\x5e\x50\x80\x07\x7c\x11\x81\x48\x7d\xb9\xb7\xc7\x15\x13\x92\x87\x35\x39\xdc\x4f\x94\xd0\x6c\x55\xae\x4f\x0b" + - "\xc8\xb7\xf7\xbc\x2c\xaa\x56\x7d\x67\xca\xb9\x63\xde\xd0\xcb\x7d\x65\x9a\x65\x61\x6d\x51\x57\x63\xf8\x7c\xd1\xb6" + - "\xab\xe9\x64\x72\x52\x16\x55\x6e\x8b\xd3\x4a\x97\x60\x1b\x9a\xc0\x45\x39\x5e\x2d\x56\x93\xc7\x7b\x7b\xdf\x4c\xf6" + - "\xfe\x32\xf9\xf8\x4f\x37\x8c\xdd\xdc\x94\xfa\x6a\x22\x55\x82\xf0\xa4\xb3\xbd\x46\x92\x03\x69\x0b\xe9\xb0\x38\xbf" + - "\xec\xd5\x03\x43\xa1\x63\x16\x8f\xd4\x14\xfe\x81\x79\xed\x65\xa7\x83\xa6\x32\x15\xd3\x23\x7a\x69\x2e\xdb\x51\xac" + - "\xbf\x60\xd2\x53\xaf\x09\x9d\x94\x03\xa1\xa9\x30\xb4\x8e\x47\x53\x70\x8a\x3d\xca\x32\xd8\x0b\xfe\x63\xae\x32\x68" + - "\x37\x90\x0f\xe0\xb5\x4a\xf9\x7c\xe4\xf2\x57\xd0\x89\xbc\x9e\xc1\xa5\x49\x28\x22\x2f\x51\x1f\x3a\x50\x19\x14\xe0" + - "\x4c\x99\xe8\xfd\x75\x5b\x71\x2c\xc1\xe5\xc9\xca\x01\xcf\xdc\x25\x6d\xaa\xfc\xf9\xa2\x28\xf3\xc1\xe6\x0a\xd0\x06" + - "\x99\x85\x24\x05\xd0\x81\x31\x67\x95\x81\x08\x9e\x28\xdd\xaf\x47\x06\x2a\xde\xbe\x53\x4f\xc6\xfb\x23\x8f\xfe\xfc" + - "\xe5\xf8\x72\x14\x43\x41\x87\x94\x3f\x32\x69\x22\xd7\x39\x69\x74\x5e\xd4\xa4\x92\x1d\x64\x99\x93\x12\x1c\xf3\x88" + - "\xe0\xcd\x4f\x55\xe6\xfa\xe5\x48\x0c\xe0\x41\x0d\xdd\x09\xe2\xfc\x26\xae\x86\xb7\x90\x9c\x10\x7a\x1b\x20\x4c\xb3" + - "\xd0\xd1\x37\x80\xfc\x00\xce\xfb\x8c\x18\x46\xc9\x2b\x97\xfa\x0c\x5d\x94\x61\xec\x34\x5f\xe4\xb8\x03\xba\xc4\x04" + - "\x00\x69\xa4\x5e\xbf\xdc\xdf\x13\xed\xd7\xab\xf6\x1d\x7c\x64\xd8\x02\x60\xe9\x67\x68\x3d\x0e\xbd\x03\xc6\x78\xc5" + - "\x7c\xb2\x2d\x72\x48\x4f\xe8\x44\x25\xf6\xf1\xf3\x69\x78\x96\xba\x39\x43\x74\x31\x2e\x81\x35\x0e\x08\xd4\xda\xbd" + - "\x87\x11\x2d\x65\x19\x98\x1e\x5c\x78\x5f\x71\x70\x05\x11\x1d\x7f\x11\xde\xde\x07\x43\x0c\xfd\xf6\x3d\xf7\x39\x9a" + - "\x74\x45\xdb\x75\xa9\x8b\xaa\xd5\x85\xeb\x7a\x6b\x69\xbd\x50\x71\x7f\x62\x66\xf5\x92\x30\x15\xdc\x62\xde\x32\x77" + - "\x9f\xbc\xf3\x9f\xfa\x4d\xc8\x1e\xb8\x19\x66\x9a\x89\x77\x26\xb4\x97\xc9\xc1\xc1\x93\x7f\xa7\x6f\xa2\x1a\x0e\xb8" + - "\x8e\x9b\xe1\x80\xd1\x4d\xdd\x69\xac\xea\x1c\x04\xe1\x91\x72\x6c\x2e\xfc\xb5\x7d\x0f\xa2\xda\xbf\xc3\xf0\x5f\x61" + - "\xcd\x5e\x35\xe3\xf0\x62\xb3\x8d\xc4\x95\xf9\x57\x80\x8c\xa9\x32\xf7\xf9\x9f\x82\xcb\x05\xa2\xe8\x98\x94\x67\x3d" + - "\x0d\xf7\x31\x7d\xfd\x1a\x08\x6a\x3e\x54\xc5\xfd\x92\x38\xbe\x1b\x84\x9c\xcd\x83\xdf\x88\xc9\xec\xa1\x45\x47\x90" + - "\x74\x0d\xba\x50\x61\xbc\x6b\x1c\xff\x1a\x82\x94\xd0\x57\xf6\xd4\xb4\x13\x6b\x5a\x19\x9b\x4a\xf9\xe6\x46\x3e\xd9" + - "\x1c\xa0\xbd\xf8\x00\xd4\x0d\xa9\xe7\xaa\x38\xe5\x5c\x15\xa7\x9a\x0b\x3f\x1f\x27\xee\x2f\x49\xc4\xcf\x2b\x01\x51" + - "\x08\x36\x0d\xf0\x84\x12\xbd\xd3\x8d\x01\xb6\x92\x36\xa9\xe0\x25\x49\xd6\x82\xe1\x9e\x9a\xf6\x99\xef\xb1\x6b\xd6" + - "\xb6\x4d\x37\x74\x2c\x86\x8f\x77\xcd\xf5\x4e\x71\xd2\xc5\x67\x65\x99\x76\xa8\xac\x2f\x4c\x33\xd3\xd6\x50\x91\xbf" + - "\x37\xfa\x24\xe4\x26\x47\xb4\xbf\x62\xae\xea\x0a\xe3\xee\x7c\x4e\x76\xec\x38\x4e\x0e\x22\xc3\x5c\x5f\x0b\x53\xf4" + - "\xaf\x6f\xbe\x7f\x51\xcf\x3a\x99\x6b\x29\x78\x01\x80\xb0\xdb\xfa\x7b\xd7\x36\x04\x2f\x0c\x45\xa4\x7a\x38\x69\x70" + - "\xc8\x92\x1c\x36\x28\xa8\x0f\xa2\xc3\x08\x5e\xd3\x63\x77\x6e\x49\x25\x4c\x1b\xfe\xd0\x9f\x65\x35\xf5\x07\xbc\xc7" + - "\x6e\xba\x31\xc7\x5c\xd0\x1f\x05\xea\x11\x85\xe4\xf7\x1d\x96\x04\xf4\x5a\xaa\xc1\x93\x78\x03\x7b\x6b\xa2\xa7\x6e" + - "\xea\x2a\xac\xf3\xd3\xf2\x3c\xf5\x68\xdf\x11\x38\x41\x6c\xaf\x98\x24\xed\x08\x34\xca\x08\x10\x3c\xd2\x80\xf5\x8f" + - "\xe4\x93\x53\x56\xc9\x21\x44\x33\xd9\xe9\x7c\xd4\x77\xac\x8d\xa9\x6c\x51\xe5\xb0\x37\xfa\xe7\x1a\x92\xac\x57\xbb" + - "\x90\x04\x08\x68\x40\xd8\xf0\x8c\x47\x0d\xc8\x9a\x17\x46\xb8\x12\xb4\x75\x98\xd1\xa4\x3f\x5e\x29\x42\xd8\x3f\x61" + - "\xe6\xa7\x7e\xae\x52\x5f\x9a\x7e\x3a\x2c\x16\x53\x52\xbf\x20\xd6\xff\xe0\x73\x7a\x88\x34\x06\xae\xff\x3f\x40\x3e" + - "\x51\xce\xb1\xc7\x39\xdc\x70\xe3\x0f\x54\x53\xd5\xed\xc5\xa2\x68\xc3\x24\xc0\xf2\x84\x0f\x39\x4f\x4b\x02\x25\xc0" + - "\x73\xcf\x98\x50\x03\x3a\x9e\xfe\xc3\xa3\x62\x67\xe7\x58\x58\x24\xb8\x8f\x61\x2d\xd0\xa9\xf1\x52\x26\x99\x72\x7f" + - "\x49\x1b\xee\xb7\xa8\x36\x92\xeb\x70\x6a\x5a\x76\xaa\x56\xad\xbb\xfb\x81\x58\x0f\x1e\xec\xef\x7d\xfd\x97\xbd\xa1" + - "\xd0\xf5\x7d\xca\x29\x0f\x7a\x3e\x8a\xea\x87\x80\x17\xbb\xaa\x2b\x48\x1e\x2c\x63\xfb\x41\x53\x4f\x85\x11\xec\xd1" + - "\x8f\xe8\x38\xb1\x9c\x78\xd7\x56\x98\xb8\xb0\x9e\xe2\xe0\x74\xd3\x4e\xe3\xe2\x7b\xb2\x45\x3e\x42\x8e\xba\x73\xa2" + - "\xe1\xcd\x89\x66\xd2\xf8\x9b\x1e\x56\x26\xce\xdd\x87\x5c\x4f\xc0\xcf\xf3\x9a\x11\x8c\x8c\xf3\xb1\x94\xcc\x4c\x75" + - "\x26\xca\x27\x9d\x05\x3e\x0a\x2c\xfe\xc8\x86\x9f\xac\xdb\xd6\xfd\x04\xbe\x2e\xb8\x4a\x34\xc6\x1a\x84\x75\x65\x94" + - "\xa3\x4a\xbd\x7e\xf9\xd5\xee\x37\xa1\x56\xcc\x1b\x8f\x6f\x31\xa1\x21\xb0\xf9\x45\xa5\xdc\x15\x83\x0d\x15\x16\x20" + - "\x1e\xb0\x76\x2c\x9a\xaf\x21\xa6\x18\xd8\x40\x8f\xc0\xc5\x19\xe1\x98\x0f\x10\xb4\xa8\x97\x96\x65\xae\xf6\x2c\xbe" + - "\xfa\x04\xf9\x96\xf6\xc1\x50\x1f\x9e\xa9\xc4\x2a\xd8\x43\xfd\x3a\xa9\x95\xa5\x5a\xf2\x3b\x9f\xb4\xfa\xa4\xb3\xd7" + - "\xb7\xef\xf9\x3b\xa8\x17\xc0\xb4\x87\xc0\x0b\x1b\x53\x58\xee\xd8\xc8\x04\x53\xbd\x84\x88\xaf\xee\xe9\x02\xbe\x83" + - "\x50\x34\xc2\x8e\xbf\xfb\xa6\x4a\x68\xee\xc6\xeb\x42\x7e\x20\x58\x4a\x3a\xf7\xac\x4e\x91\x1a\xd8\x4d\xe7\xd8\xd6" + - "\xeb\x66\xe6\xc9\xd8\xe4\xc3\xc5\xce\xe4\x54\x0d\x6f\xd7\x84\x9f\x42\x56\x4d\xa2\x52\xc8\x82\xf7\xa4\xb8\xf3\x77" + - "\xc4\xd3\x70\x24\xe3\xb2\x07\x1b\x98\x53\xe0\x5d\x24\x79\x86\x54\xc0\x0b\xe6\xf5\xf9\x78\x46\xc5\x80\xb7\x82\x4c" + - "\xf1\x20\x28\xcd\x8b\xca\x11\x63\x00\xed\x4b\x52\x04\xc1\xf4\x7b\xc8\x1b\x1f\xb2\xe6\x53\x2d\xe2\xe8\x90\x19\x62" + - "\xb9\xa3\xdb\xf9\xa7\xfe\x62\xe8\x0c\xca\x67\x79\xc4\x2b\x13\xeb\xeb\x1f\xe1\xfd\xf8\x5e\xeb\x32\x65\x7c\xc1\x91" + - "\x46\x6b\x53\x93\x62\x6e\xe4\x7e\xa0\x9e\x08\x65\x71\x90\xb6\x9a\x79\x3d\x5b\x83\xb0\xc9\x60\xb1\x40\xa5\xae\x51" + - "\x6c\xbd\x76\x4c\xbc\x6e\x8c\xbe\x46\x4a\x34\xfc\x6c\x52\x6c\x16\xb3\x1c\x09\xff\x2f\x88\x59\xe8\x9d\xf5\xaf\x88" + - "\x59\x3f\xf6\x34\xfc\xe9\x62\x16\x47\xf0\x2d\x0a\x7b\x74\xc7\x6d\x9a\x02\x7f\x6c\x14\xba\xe8\x7b\xce\xcf\x3e\xaf" + - "\x9b\x6c\xaa\xb2\x45\xbb\x2c\x5f\xd5\x0d\x7a\x90\x64\xb3\x52\x5b\x0b\x69\xc2\xdd\x1f\x3f\x50\x4c\xa8\xf7\x01\x8e" + - "\x87\x74\xab\xd4\x86\x07\x03\x45\xb7\xaa\x6e\x2f\x97\xe5\xbf\x20\xbd\x89\x50\xac\xff\x73\xd2\x1b\xf6\xde\x09\x26" + - "\x9f\x26\xcf\x48\x2e\x8b\xbe\x15\x94\xe0\x55\x71\x89\xcb\x46\xfd\xd7\xb3\x05\x4e\x93\x14\x81\xee\xe4\x9f\xba\xe2" + - "\x90\xc8\x5a\xd1\x4d\x01\x79\x67\xb2\xec\x34\x27\xc7\x7f\x93\xf4\x71\xe8\x79\x60\xa6\x16\xf8\x59\x1a\xb5\xed\x27" + - "\x2d\xe5\xeb\xe3\x4e\xfd\xeb\x82\x44\xb7\x23\xb2\x1b\x5d\x67\x77\x9a\x4b\xe6\xd1\xf4\x09\x64\xfd\x67\x3e\xad\x27" + - "\xeb\x63\x47\xd0\x82\xfd\xbd\xd0\x36\xe2\x41\xf4\x09\x68\xcf\x09\x2a\x29\xd0\x39\xe2\x59\x53\xf0\x02\x4e\x71\xbf" + - "\x68\xcc\xdc\x83\x8b\xc2\x13\xee\x91\x87\x10\xdd\xdd\x4f\xd9\xcd\xde\x04\x7c\xaf\x5f\x7e\xb3\x83\x4f\x48\x0f\x59" + - "\x19\x6b\xc9\x46\xcf\x6a\xce\xa2\xa2\x1f\xa7\x4d\xbd\x5e\x71\x46\xeb\xa2\xd2\xb3\xd9\xba\xd1\xad\xd9\xbe\x17\xf3" + - "\xa0\x52\xc9\x19\x19\x8e\x04\x50\x7b\x50\x82\xc2\x2c\xdd\x36\x81\x10\x49\x81\x2a\x58\xa2\x12\x01\x92\xfd\x69\x90" + - "\xb9\xa9\x08\x02\x5e\x9b\xaa\xed\x03\x6e\xdf\xea\xbc\xf2\x3d\x81\xd9\x93\x11\xcd\x42\xfa\x8b\xdc\x9e\x6f\x3a\x66" + - "\xfa\xed\x7b\x5b\x19\xcf\x3f\x90\xcd\xac\x31\x3a\x7f\x5b\x95\x57\xf8\x6b\xa9\x2f\xbf\x87\x9b\x01\x7f\xce\x4c\x59" + - "\xbe\x5b\xe9\x19\x24\x58\xe4\x07\x3f\x12\x98\x26\x7e\x5e\x5f\xbc\x5b\xe9\x8a\xde\xd6\x65\xf8\xb1\xb6\xe6\x8d\x5e" + - "\xe1\xdf\x10\x22\xf7\x2d\x64\xd0\xe3\x92\x95\x13\x61\x5f\xe6\x45\xeb\xf6\x50\xb6\x7d\xef\xb8\x93\x36\x33\x25\x24" + - "\x70\xe5\xc4\xd7\xf8\x31\x81\x2a\xf6\xde\xc4\x70\x0d\xb8\x5b\xf8\xe8\x43\xfb\xa1\xf9\x50\x7d\x98\x1f\x4f\x4e\x6f" + - "\x51\x6a\xe6\xf9\x73\xf7\xc5\xc6\x2c\x7c\xe0\xad\xe0\x4a\x18\xcb\xd1\x65\xb3\x75\x33\x72\xcf\x7e\xff\x7d\xa4\x3e" + - "\x8e\xd4\xbc\xa8\x74\x09\x12\x8d\x8f\xd3\x9d\x61\x00\xc7\xe6\x14\x7b\x2c\xfa\x74\xa4\xe3\x32\xa0\xb0\x47\x41\x37" + - "\x9b\x5c\xeb\x53\x18\x8b\xcd\x17\xb5\xfa\x98\xaa\x79\x7c\xc6\x2c\x9e\x04\xaa\x2e\xf2\x1a\xfa\x48\x59\x6e\xfc\xf5" + - "\x1a\x12\xf7\xdf\x74\x55\x4f\x3c\x76\x71\x7d\xbc\x5f\x80\x41\xe0\x23\xf3\x86\x8c\x79\x05\xf2\x05\x32\xbf\xb3\x7a" + - "\xb9\x6a\x8c\xb5\xc5\x49\x51\x16\xed\x95\x1a\x58\x63\xc8\x40\x0d\xfd\x42\x11\x9a\x56\x01\xe0\x50\x71\xd8\xd7\xd7" + - "\xa0\xe3\xe9\xd1\x1b\xc4\xf8\xe2\xb7\x27\xa5\xa3\x24\x58\xc8\xb9\x14\x1e\xed\x61\xb6\x6e\x3a\x28\x9c\x02\xb2\x10" + - "\x5e\x84\x49\x61\x5a\x37\x50\x99\xca\xd4\x4e\xfa\x7a\x07\x1e\x0f\xc7\x8d\x59\x95\x7a\x66\x06\xb4\x4f\x47\xf8\xd8" + - "\xd3\xc4\x4c\x21\xa0\xc5\x56\xf0\x1a\x47\x0f\xdf\x75\x23\xe4\xbd\x8f\x01\x2b\x53\x28\x3b\x60\x43\x82\x4f\x31\x4c" + - "\xd3\xd1\xc7\x58\xd7\x11\x6a\x12\xb9\xf1\xa1\xab\xf8\x21\xf5\x50\xfd\x55\xa6\xc7\xa7\x69\xd8\x39\x90\x85\xb8\x65" + - "\x2f\x5e\x7a\xdd\x02\x44\xc2\x56\xe5\x95\xd2\xd6\x16\xa7\x15\x42\xf9\xcd\xe7\x86\xad\x53\x1a\x64\x8a\x75\x55\x19" + - "\x93\x9b\x5c\x35\xa6\xca\x8d\x3b\x0f\x63\xfa\x3c\x9c\x24\xe1\x34\xd1\x14\x4b\x9a\x80\x48\x04\x4e\x26\x18\x1c\x17" + - "\xc3\xe7\xa9\x70\x1c\x0a\xca\x62\x9b\xbc\x67\xfb\x5c\xa1\x3b\xec\xf2\xff\x1c\xd9\xe8\xf0\xeb\x98\x83\x38\x38\x31" + - "\xfd\x5f\x4f\x50\xc4\x0c\xfd\xcb\x34\x65\x03\x45\xf9\x5f\xa6\x02\x40\xc0\x0a\xab\x9c\xa8\x6f\xac\xa5\x8c\x12\x40" + - "\xc3\xee\x22\x60\x4c\x55\x87\xff\x07\xe9\xc9\xff\x20\x39\x09\x3a\x9b\x47\xba\x2c\x1f\xa9\xa2\xb2\xad\xae\x66\x9c" + - "\x48\x23\x54\x75\x27\xc9\xf9\xdb\x41\x0f\xcd\x81\xec\xf5\x61\x7c\x9d\xef\x68\xa8\xff\x4b\xc4\x08\x77\xda\x61\x0f" + - "\x51\x52\x53\xb4\xcc\xff\x5f\x41\x99\xd0\xd3\xae\x9f\x32\x8d\x10\xbd\xef\xdf\x83\xea\x10\x9c\x47\x82\x3f\x0a\x13" + - "\x96\x9e\x58\x16\xff\x65\xec\x38\xc9\x91\x1d\x07\x7d\x51\x2e\x32\x67\xa8\xfb\x94\xd2\x86\x26\xbc\x86\xf2\x19\x44" + - "\xbb\x34\xa3\xc7\xb4\xf5\x5f\x23\x58\xc5\x46\x82\x25\x26\x2e\x22\x58\x48\xaf\x8a\x94\x5e\x85\xb9\x1c\xca\x69\xed" + - "\x63\x8b\x3e\x31\x0d\xea\xe6\x79\x04\xbf\x5d\xc4\x4c\x2c\xaa\xbc\x38\x2f\xf2\xb5\x2e\xf1\x58\x82\x30\x48\xe7\xcd" + - "\x5f\x38\x3f\x88\x44\xea\x32\x7b\xf4\x96\x35\xe5\xdc\xdf\xab\x89\xcf\xfd\x96\xff\xd4\x9b\x65\xee\xa4\xa7\x11\xad" + - "\xf0\x7b\x38\x54\x74\x04\x04\xf6\x38\x51\xd4\x83\x83\x8b\x32\x80\x19\xe0\x3f\x3b\x2d\xce\x4d\x35\x52\x76\xa5\x67" + - "\x46\x59\xb3\xd2\x0d\x40\x44\x95\x05\xc7\xe0\x11\x66\x88\x29\xe7\x4e\x42\xa5\x75\x8a\xae\x0f\x11\x2d\xe3\x4a\x45" + - "\xbb\x49\x14\xf4\x07\x2b\xc6\xd1\xc0\x8f\xc2\xde\xec\xfb\x62\x3b\x32\xa4\xb8\x8b\x01\x57\xe5\x62\x51\x97\x46\x2c" + - "\x08\x6e\x02\x99\x7e\x8d\xd7\x36\x32\x7d\xd3\x75\xbe\x21\xe3\xae\x48\x4e\x29\x87\x29\x26\x12\xe1\x08\xc3\xcb\x62" + - "\xae\xac\xe1\xe9\x0a\xf1\x15\x56\x44\x08\xfe\xf6\x9b\x2f\xfe\xdb\x6f\x59\xf7\x12\xee\x81\x41\x41\x94\x5a\x9f\x02" + - "\x7e\x01\x69\x10\xc3\x58\x43\x8a\x96\x06\x01\x7b\x4d\xae\x32\x50\xd2\x67\x01\xf0\xaa\x5d\x78\x7f\x53\xa8\x4c\x4c" + - "\x18\xd4\x31\x28\x18\x0a\xf7\x42\x5b\x05\x08\x0f\xae\x18\x42\xc0\x59\x7d\x6e\x72\x55\xb4\xc3\xb1\xaf\xef\xad\x87" + - "\xa5\x39\x01\x3b\x0b\x78\x29\x5c\x2c\x74\x6b\xce\x4d\x43\xd9\x51\x30\xc7\x4f\x79\x45\xdf\x0f\xc0\xe9\xe7\x0a\x40" + - "\xc2\x05\x14\xd7\x5c\x97\xa5\xaf\x81\x01\x72\x64\xd6\x47\xcc\xa0\x0e\x8e\xf2\xae\x5e\x98\xf3\x9c\x7a\x92\xcc\xde" + - "\x41\x3a\x9d\x11\x6a\x30\xc5\x46\x62\x02\xab\xfe\xf8\xcd\x78\x75\xf0\xb4\xf1\xd5\x92\xc4\xf3\x6c\xdf\xdb\xe2\x63" + - "\x10\xc5\x2c\x13\xa4\x5a\x87\x09\xa5\x0e\xe2\x25\xea\x4b\xe1\x3d\xda\x61\x18\x3b\xec\x62\xc2\x3a\xc5\x8c\x93\xdf" + - "\xa7\x47\xc5\x71\x1f\x63\x83\x6d\x72\x81\x84\x83\x09\x0c\x8c\xe0\x5f\x86\x81\x5b\x90\x5b\x3f\xe6\x12\x98\xac\x36" + - "\x6b\xf3\x74\xd3\xe5\xe8\xed\x9f\x37\x7d\x8a\x02\x2a\x74\xa0\x26\x1f\x9a\xdb\x34\x04\xe7\xba\xbc\x95\xcb\x17\xce" + - "\x3e\x2a\xdc\x4b\x38\x97\x92\xa9\xdc\x8b\x12\xf2\xde\xef\x30\xf9\xd1\x84\xc6\x0a\xba\x44\x71\x7a\xae\x4b\xd2\x9b" + - "\xa2\x66\xcd\x4d\xb8\x34\x16\x25\xef\x59\x3d\x97\x6a\x51\x62\x9e\xf0\x5f\xd0\x59\x66\x30\x17\xd9\x2d\x2e\x1c\x89" + - "\xed\x24\x49\xdd\x9e\x5a\x42\xe3\x95\x45\xce\x03\x1d\x16\xc4\xb5\x78\x18\x28\x20\x59\x94\x96\xb5\x6d\x41\xc7\x5e" + - "\x57\x7c\x6c\x67\xda\x7a\x3e\xb4\x31\x6d\xd8\x65\x58\xf9\x48\x65\x59\x60\x92\x43\x4d\xf0\x19\xe5\xe8\xf4\x89\x6f" + - "\xaa\x75\x59\x22\x12\x83\x23\x76\x88\x18\x11\xaa\x0e\xde\x14\x78\xb4\xfd\x48\xe3\x84\x48\x11\x23\xe3\x37\x89\x8c" + - "\x8d\xef\x30\x34\x4f\xef\xe2\x1f\x04\x3b\x43\xa6\xe5\x38\xd1\x2e\xe6\x26\xa6\x03\x79\x3f\xf2\x90\x90\xbd\xf2\x3d" + - "\xa5\x74\xec\xbe\x73\xbe\x30\x1a\xad\xbb\x62\x5c\x31\x4a\x98\x09\xb7\x92\x83\x61\x7f\xd6\x4e\x51\x49\x27\x04\xed" + - "\x7d\x63\x74\x2b\x26\xba\xa0\x1c\xb4\x59\xf6\x94\xf3\xc2\xd2\xc4\x03\x38\x22\x2e\x72\xe8\x33\x54\x9d\x7a\x32\x61" + - "\x7b\x59\xd6\xe7\xb2\x14\xb8\xdd\x18\x06\x24\xfa\x78\x67\xd3\xd7\x3d\x48\xb2\x92\x01\xc1\x86\x25\x6a\xd4\xb9\x2e" + - "\x47\x9b\x28\x48\x62\x9d\x4f\xb7\x53\x70\x65\xe2\xf3\x93\x04\xf0\x6d\x24\x0d\xa8\x37\xdd\x4c\x1a\xfc\xf6\xb8\x8d" + - "\x34\x20\x03\x60\x4d\x4b\xae\x46\x36\x1c\xf2\x11\x5c\x9e\xfe\xe6\x44\xd7\x23\x86\xbb\x08\x6b\x83\x29\x58\xc0\xf8" + - "\x34\x88\x4d\x34\x70\xbf\x25\x49\xb0\x47\x38\x57\x9e\xb0\xc0\xf2\xf4\xd0\x15\xe8\x7c\xc7\xe1\xa1\x37\xd9\x7f\xd7" + - "\xaa\xc8\x73\x40\xb6\x11\xb4\x21\x7c\x92\xa1\x24\x78\x70\x6c\x72\xdd\xf2\x3d\xef\xf8\x9d\xa5\xe6\x69\xd8\x27\x82" + - "\x04\x09\x83\xc7\xfe\xde\xee\xfe\xfe\x8e\x90\x62\x57\x08\x5e\x67\x2e\x5b\xd5\x2e\x9a\xfa\xc2\x2a\x73\x39\x33\xe4" + - "\x73\x3d\x78\xb0\xff\xe5\x57\x5f\x7f\x35\x52\x0f\xf6\xbf\xfc\xfa\xc9\xd7\x43\x96\xea\xa5\xa4\xca\x3f\xcc\x65\x1b" + - "\x7c\x18\xe5\xa4\x09\x9f\xfc\x3f\x33\x13\x4e\xaa\xc4\xde\xb1\x1c\xc1\x9e\xe0\x44\xda\x23\x44\xc8\x80\x0f\x40\xbe" + - "\x18\xc2\xb0\xe1\xbf\xaf\xbc\xa9\x55\x88\x44\x50\x72\x17\x00\xb4\xaf\xaf\x7d\x5c\xa5\x97\x6c\x28\xb3\xf5\x01\xb8" + - "\x75\x1e\xe2\x34\x07\xc4\x48\x48\xa3\xe9\x5f\xe2\xc7\x3b\x00\x0b\xce\x88\x93\x02\xf0\x96\x78\x21\xdf\x84\x5f\x2e" + - "\xa8\x84\xd7\x6b\x4b\xd6\x25\xa2\x84\xdd\x6a\x7d\x5f\xd7\x2b\x58\xa6\xf5\xe9\xc2\x23\x2b\x7a\x73\x52\x00\x46\x4b" + - "\x34\x52\x4b\x7d\x99\x68\xa4\x68\x2e\xd1\x0d\xdf\x7d\xc4\x7a\xa9\xb0\x33\xc0\x5d\x49\xe5\xb5\x81\xb8\x75\xca\xc5" + - "\xe9\xdb\x42\x97\xa4\x79\xdd\x2c\xd1\xd7\x49\x0d\x1e\x3c\x7e\xf2\x64\x7f\x28\x45\xaa\x01\xef\x2e\xff\x95\x9b\x60" + - "\x98\x76\x06\x22\xf0\x1e\x59\xd0\xe4\x0b\x30\x77\x07\x5c\x1d\x58\x6d\x9f\x22\xc6\x3b\xe8\x3b\xb9\xa0\x52\x5a\x3c" + - "\x20\xeb\x9c\xaf\x6b\xa0\xfa\x5c\xf7\x0f\xc1\x75\x1f\x20\x6c\xf9\x11\xaf\x53\xe4\x4a\x3c\x80\x8c\x32\x50\x80\xe9" + - "\x04\xd1\x7f\xd1\xdd\x81\xaf\x4c\xd8\xd3\x7c\xbd\xc2\x20\x1e\x9c\xcc\x3a\xe5\x47\x10\x48\x02\x5d\x47\xa7\xb3\xe0" + - "\x49\x8b\x13\xf2\x77\x83\x31\x10\x84\xbc\x33\x23\x9a\xed\xd6\x36\x84\x46\x70\xf9\xf3\x48\xb9\xcd\xcd\xf1\xcd\xf9" + - "\x34\xaa\xf8\x17\xce\xcb\x57\x19\x48\x97\xae\xb4\xbb\x6f\xa0\x62\xb7\xfd\x28\xb6\x82\x3f\x40\xc4\xa4\x2a\x52\x30" + - "\xf5\x39\x7e\x49\x0d\x19\xc6\x92\x94\x6d\xb1\xfb\x8e\x02\x35\x3c\x5a\x1f\x36\x16\x75\x9b\x03\xea\x12\x87\xb4\x9b" + - "\x2e\x63\xe7\xdb\x64\x4c\x49\xce\xd5\xfb\x29\xee\x82\x84\x69\x56\xd4\xd5\x3b\xc7\x52\xff\x19\xf2\xe2\xe9\x80\xbf" + - "\x7d\xcf\x4c\x0c\xf7\x2e\xcf\x78\x7c\xfa\x3b\x5a\x8d\x62\x77\xf7\x13\xce\xa2\x38\x49\xe9\x41\x0a\xcc\x5d\x45\x9d" + - "\xa0\x12\x44\x38\xa9\xb7\x28\xd9\x44\x1a\x0c\x3f\xfc\x18\xf2\xb4\x33\xd5\x4e\x82\xad\x9b\x99\x93\x83\xeb\x0b\x4b" + - "\xdc\xd1\x89\x01\xa8\xf4\x59\x5d\x59\xf4\x18\x2e\xaf\xd0\x85\xae\xaa\xab\x5d\xd0\xe9\x84\x44\xc9\xe8\xbb\x28\xa4" + - "\x80\xfb\xa1\xe9\xd0\x9f\x2e\xb5\x56\x07\x8a\xcd\xf7\x09\x90\x68\xb4\xec\xdb\x7d\x96\xfd\x9f\x74\x5e\xd4\x16\x9c" + - "\x49\x38\x5c\x0a\x5d\x68\x5b\xd3\x4c\x2c\xf9\x8b\x25\x51\xe6\xe8\x1b\x3a\x12\x41\x5b\x6a\xa3\xe5\x38\x66\x71\xc0" + - "\x58\xfc\x07\xde\x6e\x77\xee\xbd\x4f\x4a\x14\x10\x12\x87\xa2\xfe\xd6\xf5\xa8\x77\xb5\xe9\x8c\xbb\x52\x74\xbe\x43" + - "\x7b\x28\xcc\xa6\xd3\xe4\x63\x54\xef\xa7\xe1\x60\x71\xb0\x6a\x3a\xc4\x31\x26\xe3\xde\x70\x59\x4b\xe6\xe2\x17\x73" + - "\x72\x56\xb4\xfc\x38\xcb\x30\x3d\xb6\x1b\x8f\xc9\x41\x83\x6f\x74\xae\xea\x39\x06\xa8\x15\x73\xa5\xfd\x46\x71\x84" + - "\x28\x06\x17\x93\x6e\x23\x11\x69\x26\x26\x48\x50\xe5\x43\xac\x70\x9a\x7a\xbe\xde\xf4\x49\xe7\x60\x58\x10\xe1\x20" + - "\xe8\xec\xe1\xfd\x41\x77\x11\x3d\xa5\x9a\x95\x6b\x0b\x94\x35\x75\x77\x50\x83\xec\xa4\x5c\xbb\x8b\x6f\xb6\xb6\xf8" + - "\xdf\xa2\xc2\x7f\xeb\x75\xab\xca\x5a\xe7\xee\x3e\x2c\x7e\x37\x0a\xd3\xf1\xab\x75\x05\x0f\x67\x65\x31\x3b\x53\xf9" + - "\x49\x89\x7f\x64\x6a\x07\x9c\x23\xea\xb5\x35\x79\x7d\x51\x29\xf8\x6b\xbd\xc2\x7f\x41\x9b\x05\x7f\x41\xba\x26\xfc" + - "\x6b\xdd\xe2\x1f\xa6\x6a\xf9\x59\x69\xdc\x69\xa4\xba\x28\xa1\x1c\x85\xe5\xd9\xf5\xc9\xb2\x68\xd5\x99\xb9\x82\xea" + - "\xcf\xcc\x15\x18\x91\xdc\x1f\xeb\x95\x32\x4d\x53\x37\x0a\x5c\x26\x2e\xdb\xa5\xa9\xd6\xd9\x50\x20\x79\x6e\x74\x2a" + - "\xc5\x38\x35\x0a\xf2\x32\xe7\xa6\x6a\xd5\x49\x01\xae\xe3\x77\xc6\xd7\xe7\xba\xd5\x02\x5c\xd2\xbb\x19\x76\xdd\x07" + - "\xf7\x24\xca\x57\x70\x52\xc4\x40\x04\x51\x8d\x00\x4d\x68\x9b\xe2\xf4\xd4\x34\xd2\xd5\xbc\x1b\x77\x1f\x6b\x5e\x16" + - "\x6e\x66\xe5\x99\x9d\x57\x6f\xcf\x4d\xe3\xea\x7e\xbb\x6e\xfb\x5c\x13\xc3\xe4\x73\x61\x35\x1c\x87\x65\x18\xd0\x97" + - "\xd7\xd7\xfe\xad\xd0\xa8\xb9\x69\x4a\x11\x72\xec\x68\xd3\xac\xf8\xa1\x53\xb1\x74\xec\x1e\x7a\x67\x5d\x6d\xa8\x78" + - "\x43\x95\xf3\x79\x52\xa7\xac\x6d\xfb\x1e\x38\x5a\x9e\x26\x90\x7c\xac\xd2\x1b\xfd\xc9\x4e\x87\xef\x7a\x3b\xfe\x49" + - "\x4d\x85\x46\x26\x13\x85\xcb\x8b\x7a\xfc\xa1\x02\xf6\x36\xf9\x40\x1d\xb9\x4f\x8e\x11\x8b\x77\xd3\x0e\x43\xf5\xe1" + - "\xa1\x98\x91\x50\x4b\xf6\xe8\x51\x16\xac\x46\x72\xba\xbc\x62\xf3\xfa\x1a\x4a\x89\xf1\x08\x12\x83\xd1\x91\xd5\xcc" + - "\xf4\xa1\x2f\x80\x66\x10\x82\xc3\xd5\x81\x1a\x4c\x3e\x1c\x4e\x02\x65\x92\x74\x34\x8a\x05\x76\xbc\x5a\xdd\x9c\xe9" + - "\xa6\x5e\x57\xb9\x9a\xeb\xa2\x84\xe0\x58\x56\x54\xec\xce\xb4\x45\xed\x06\x86\x6e\xfa\xdd\xbe\xd2\x8d\x35\xff\x78" + - "\xf7\xf6\x87\xce\x29\xa4\x19\xa5\xe9\x71\x45\xb0\x30\xbd\xf5\xa1\x4d\x22\x76\xfe\x79\x53\x5b\xbb\x4b\x8c\x80\xba" + - "\x5c\x96\xca\x7d\x01\xc7\x5e\x36\xf7\xeb\x9b\xef\x37\xb5\xe6\xc6\x7e\xb9\x2c\x47\xaa\x5d\xae\xc2\x4d\x04\x05\x82" + - "\xeb\x01\xfc\xec\x43\xb5\x4b\xbc\xd1\x6e\x3a\x41\xd5\xaf\x5f\x7e\xb3\x7d\x6f\xab\x6d\xae\xc8\x43\x11\xb2\x57\x54" + - "\xe6\x42\xbd\x78\xfb\xe6\x47\xd7\xb5\x86\xc2\xe6\xd0\x75\xb5\x5d\xae\xb0\xc7\xaf\x9a\x7a\xf9\x0e\xda\x62\x0a\x95" + - "\x39\x8a\x38\xb9\x5c\x96\x24\x67\xdf\xa8\x19\xe4\x19\x19\x28\x7f\x95\x63\x1d\x71\xd6\xef\xed\x00\x4b\xe1\x5e\x5f" + - "\x5f\xbb\xd1\xba\x9b\x8b\x02\x75\xed\xb7\x57\xef\xf5\x29\x8a\x01\x19\x34\xdd\x00\x0d\xee\x66\x48\xe5\xdb\xc6\xbd" + - "\x1d\xa8\xec\x75\x05\x89\x84\xd5\xaf\x6f\xbe\x9f\x82\xb6\x1b\x27\x95\x61\x2d\x68\x66\x2e\x97\xa5\x58\xb1\x73\xdd" + - "\x10\x3a\x02\x05\x0d\xab\xb2\x9e\x71\xb4\x88\xfe\xa8\x2f\xbf\xaf\x67\x3f\xea\xa6\x05\xde\x96\x7e\x33\x46\xb7\xab" + - "\x73\xa1\x01\x5b\x6a\xf2\x60\xfc\xe8\xb3\x89\x2b\xd3\xb4\xe0\xf5\x36\x38\x3a\x7c\x78\x3c\xfc\xed\xe0\xe8\x3f\x1f" + - "\x1e\x3f\xc2\x17\x0b\xa3\x73\xc4\x21\x99\xfc\xe7\x60\xfc\xe8\x70\x38\x3d\x52\x1f\xda\xe3\x47\x83\xa3\xff\xfc\xd0" + - "\x7c\xa8\x8e\x1f\x0d\x3f\x9b\x2c\x4f\x09\xac\xe1\xc1\x5f\xbe\x7a\xf2\xc5\x48\x3d\xf8\x7a\xff\xf1\x13\xf8\xe7\xc9" + - "\xe3\x29\x74\xad\x54\xab\xa6\x6e\xeb\x59\x5d\xaa\xdc\xb4\x98\xf2\xd9\xd5\x0e\xef\x7e\xe4\x57\xe4\xfd\xae\x4f\xea" + - "\x75\x7b\xad\x57\x2b\xf7\xff\x5d\xdb\xd6\x8d\x3e\x35\xd7\xe3\x9d\x5d\xa0\xee\xee\xda\xbe\x9e\x17\xa5\xb9\x6e\x8c" + - "\xbd\xbe\x28\xf2\x53\xd3\x0e\xa7\x34\x8c\xaa\x7e\x8e\x5e\x82\x5c\xd7\xdf\x5f\xbe\xbf\xfe\xee\xe5\xb3\x17\x43\x2a" + - "\xb0\x92\x6d\x7d\x98\x7c\x98\xe0\xe3\x75\x43\xad\x1f\x7d\xb8\x18\xef\xec\x1e\xef\x4c\x87\x83\xc3\xa9\x7b\x3f\x38" + - "\x9c\x1e\xfd\xe7\x87\xc9\xe1\x83\xe3\x47\xff\xef\xf5\x70\x80\x7f\x4f\x8f\x1f\xb9\xf7\xd3\xc1\x87\x7c\x67\x78\x3d" + - "\xbc\x1e\x4e\x70\x62\x27\x8f\x54\xc0\x6c\xde\xbe\xb7\xa5\x1e\xa9\xfd\xa1\x7a\xbf\x30\x57\x20\xdf\xae\xad\x99\xaf" + - "\x4b\xcc\xab\xda\x36\x75\xbe\x9e\x19\x86\xeb\x71\x8b\xfe\x1e\x28\x1c\x7a\x7f\x7c\xd4\x97\x93\x8f\xb6\xae\x56\xe3" + - "\x8f\xde\x5f\xd5\x5c\xea\xe5\xaa\x84\x80\x7f\xf5\x48\x3d\x86\x8a\x2d\x26\x69\xc0\x0c\xc0\x53\x7c\xa3\x94\xda\x55" + - "\xdf\xbe\x7c\xf5\xf6\xa7\x97\x4a\xdb\x33\xc0\x69\x72\x35\xa8\xb6\xd1\x95\x75\xe7\x49\x94\x7b\xf6\xea\xfd\xcb\x9f" + - "\x30\x37\xbd\xb2\xa6\x29\x74\x59\xfc\x8e\xf8\x99\x03\x3b\x86\xad\x08\xa9\xcd\x82\x45\x0b\xa0\xd6\x67\xc6\xda\x17" + - "\xf4\xd2\xc9\x18\xd4\xa7\x2f\x86\x8e\xfd\x80\x87\x0b\xe3\xc7\x84\xef\xbe\x1c\x62\x02\x26\x77\xd8\x74\x59\x2a\x7b" + - "\xb5\x3c\xa9\x4b\xc0\x20\x27\x97\x5b\xc7\x29\x61\xd9\x27\x43\x65\x2e\xcd\x6c\x0d\xfd\x00\x1c\x3c\x44\x40\xc1\x1c" + - "\xdf\x3c\x0a\xdf\x00\x88\x03\xef\xbf\x7b\xf9\x83\xe2\xfc\x90\x0a\x78\xa2\xb6\x86\xea\x8b\xb9\x42\x37\x0d\xa8\x7c" + - "\x22\xd1\xbd\x2d\x67\xd4\xc6\xc5\x7b\xcf\x55\x5b\x66\x7b\xc2\x2a\x6e\x1c\xd8\xe3\x3f\x31\xb0\x2f\x86\x74\xcf\xfc" + - "\xd9\x81\x9d\xd6\x9b\x47\xd3\x86\x5e\x8b\xd1\x70\x10\x0e\xc5\x0f\xec\xae\x9a\xba\xac\x4f\xd5\x6c\xa1\x1b\x65\xcd" + - "\x3f\xd7\xc6\x5d\x62\x83\x07\xfb\x7b\x7b\xdf\x7c\x3d\x7c\xaa\x96\x80\x0a\xb1\x5a\x19\x6d\x8d\x02\xb8\x14\xc8\xc8" + - "\x76\xae\x73\x13\x1c\x94\x90\xbe\x94\x25\xee\xd4\x03\x95\x3d\x9a\x64\x9c\x43\x3e\x7b\x94\x79\x29\xed\xc1\xd7\xfb" + - "\x5f\x7c\x3d\x52\xaf\x5f\xaa\xa5\xbe\x42\xad\x23\x6e\x60\xd2\x3b\x52\x34\x38\x44\xa0\xc0\x25\x33\x99\x28\xad\xe6" + - "\x85\x29\x73\x8c\xfe\xb9\x28\xaa\xbc\xbe\x18\x33\x55\x03\xf7\x1b\xc6\x47\xc8\xeb\xa5\x2e\x2a\x30\x26\x03\x16\x11" + - "\xc8\xa0\x7c\x33\x48\x62\xa7\x0e\x3c\x59\x04\x97\x72\x47\x40\x71\x99\x02\xad\x9f\x4c\xd4\xcf\x16\x0d\xcb\xe0\x75" + - "\x1e\x22\x2c\x6a\x00\x7a\x78\xc6\xc6\x6b\xca\x2f\x5b\xb8\x59\x7b\xfd\x12\xd7\x6e\x59\xe7\xc5\xfc\x4a\x15\x2d\xba" + - "\x20\x84\x2e\x76\xa9\xb1\xcf\xd6\xb3\x09\xe5\x41\xd3\x75\x24\xcb\xa3\x23\x3c\x59\x12\xd2\x9a\x3a\x05\xd9\x79\x1b" + - "\xbc\xdd\x4f\xa3\x5b\xc1\xd1\x9b\x1a\x32\xaf\xd8\xed\x7b\xf2\x7e\x50\x07\xca\xd1\x3e\xca\x71\x1b\x55\x19\x2b\xf5" + - "\xa5\xf7\x06\x61\xed\xa8\x6c\x56\x57\xb6\x6d\xd6\x8e\x6b\xca\x80\xc4\x70\xa8\xfa\x47\x7d\xe9\xe9\x20\xec\x23\xf1" + - "\xe2\x7d\x20\x42\x3e\xe2\x4b\xe7\xf9\xfb\x3a\x50\xce\xb7\x4d\x38\x88\x03\x85\x4d\x38\xa6\x48\x88\x28\x7c\x42\x5e" + - "\x46\x9e\x75\xa8\x7f\xd0\x25\xb4\x49\xf1\x96\x96\x0e\x4e\xb8\x4b\x63\xfe\x25\xae\x05\x25\xa3\xa0\xa6\x93\x16\x9f" + - "\x9e\x36\x7b\x11\x7a\xa1\x86\x83\x9e\xe2\x28\xb1\xf7\x54\xe3\x4e\x52\x26\xad\x7c\x80\x91\x4b\xe5\x3a\x36\xf6\x70" + - "\x57\xf4\x35\x12\x2f\xdc\x5d\x7e\x38\x9b\xfc\xa2\x68\x16\x64\x20\x4f\xdd\xa0\xe3\x8d\x27\x4e\x84\x6b\xd8\xed\x02" + - "\x7c\xe2\xfd\x7b\x7c\xf9\xd0\xdb\x4e\x2c\xf5\x64\xe2\x2e\x4e\x48\x9f\x50\xcc\x55\xe3\xc8\x93\x25\x4c\x08\x01\x85" + - "\xeb\x3e\x3d\xda\x43\x54\xb1\x6c\x47\x58\xdc\xb6\x7a\xda\x18\x5b\x44\x18\xdb\x27\x5f\x88\x47\xde\xcf\x6e\xe0\x77" + - "\xd4\x51\x18\x8c\x13\x66\xfb\x9f\xc3\x74\x0d\x43\xea\x06\x9c\x1a\xa9\xb4\x0f\x2e\x25\x88\x2d\x44\xaa\xad\xd8\x49" + - "\xe8\x5f\x6b\x15\x95\xa6\xbe\xc9\xad\x9e\xe0\x5b\x71\xee\xe1\x58\x16\x95\x5d\xd1\x0d\x13\x42\x2a\xeb\x46\x89\x4b" + - "\xcf\x1d\x8f\x70\x6b\x88\x83\x48\xdf\xde\x79\x14\x7d\xc6\xaf\x91\x4a\xf2\x78\x8d\xd4\xc7\x7f\xfe\xfa\xdd\x4f\xfe" + - "\x04\x21\xb8\x13\xd4\x8a\xf1\x30\x6c\x2d\x32\x8e\x31\xf1\x95\x83\x47\x6e\x38\xe9\x98\x7e\xc0\x5f\x6b\x0c\x6e\x97" + - "\x74\x33\xec\x0a\xe9\x52\x21\x20\x87\xb6\xb6\x7c\xd3\xc9\xa4\x7b\xc5\x68\xa4\xfb\xb9\x65\x29\xa4\xca\xe4\xb7\x51" + - "\x98\xcc\xb7\xcd\x2b\xed\x08\xe0\x55\x64\x4e\xe7\xaf\xc5\xf4\x41\x2e\x93\xf4\xa3\xc1\xdd\xf3\x28\x62\x80\x12\x3a" + - "\x14\x55\x9e\xb8\x73\xdf\xef\x4c\xb0\x7b\xd8\x33\x1b\xb2\x92\xe3\x70\xa2\x7c\x3a\x35\x3e\xb1\x61\xff\xf7\x7d\xc9" + - "\x7b\xb3\xb3\x30\x7d\x85\x7a\x52\xdb\x09\x03\x79\xa7\xe3\xa9\xea\xf4\xfe\x40\x09\x2d\xf9\x2d\x0d\xc9\xf4\xc6\xec" + - "\x4f\x2a\xf6\xc6\xcd\xb6\x40\x4e\xf3\x1d\xef\x0c\x1c\x72\xb4\x22\x0d\x91\xf3\x07\xb9\x73\xdc\xa4\xfa\x2f\xdd\x93" + - "\xa1\x38\x8c\xcf\x3c\xaa\x03\x6a\xa5\x90\x09\xff\xa8\x2f\x83\x19\x0f\xdc\xdb\x74\xab\x5a\x7d\x66\xac\xca\xe6\xa5" + - "\x6e\x33\x6f\x16\x1b\x54\x75\x4b\x39\xd7\x73\x63\x56\x54\x0b\x20\x5a\x61\x5c\xa5\xb1\xea\xc1\x37\x5f\x7f\xfd\x17" + - "\x79\x91\x7e\xd4\x97\x2f\x39\x75\x93\x6e\x4e\x4d\x3b\x52\xb6\x99\x09\x19\xfd\xcc\x5c\x8d\xa0\x3e\x38\x86\xae\xc5" + - "\xb7\xde\x2a\x22\x6e\x69\x42\x44\xb0\x63\x59\xe2\xfa\x5a\xfd\x71\x23\x71\x26\x81\x27\xae\x44\x0b\xe4\x69\xd9\xcc" + - "\x8e\xe0\xdd\xa6\x5c\xef\x03\x25\xaa\xe5\xa2\x87\xd4\x63\x35\x05\x04\x6b\xb3\x72\xed\x0d\xe0\x0f\x47\x36\xc0\x7a" + - "\xc6\x65\x0f\x44\x1b\x12\x3a\x92\xe1\xaf\xcd\x2a\x95\xb6\xa3\x2c\x86\x3c\x35\x58\xb0\xb3\x19\xf0\xb5\x5f\xca\x47" + - "\xa4\x10\xb5\x0a\x91\x34\xac\x01\x9e\x42\xe3\x74\xf3\x6d\x35\xdd\xbe\xa7\x1e\xa9\x5d\x35\x2f\xaa\x1c\xc5\x84\xa6" + - "\x38\x5d\x08\x5e\x7e\x40\x59\x19\x1c\xdb\x8a\xe9\xfb\x28\xa2\x6d\xb7\x65\x56\xdf\x5c\x12\x9d\xe4\x8f\x86\x54\x29" + - "\x3b\x50\xf8\x14\xb6\x1e\xd1\x83\xbb\xe4\x0a\x4e\x92\x9d\x80\xdd\xfe\x89\x3b\x3d\x50\x4c\x55\x46\x62\x24\x92\x50" + - "\xcf\x5a\xc6\x8c\x06\x67\xf2\x17\xcc\x81\x20\xcc\xf4\x0b\xc9\x90\x50\xdf\xdd\xb6\xb1\x63\xfe\x81\x89\x7b\x04\x7b" + - "\x22\xce\x91\xc7\x51\x23\xbf\x7f\xbd\x6e\xeb\x58\xd0\x39\x05\xb8\x12\x31\x25\xc4\x60\x90\xbc\xb9\x7d\xcf\xf3\x14" + - "\xc9\xe1\x04\xe2\xf7\xc8\xf3\x03\x81\x66\x21\xc5\x12\x99\xdb\x66\xed\x06\xa7\x10\x40\x13\xb4\xe3\x65\xb1\x44\x8f" + - "\xa7\xeb\x6b\x9c\xa9\xf1\xa9\x69\x79\x02\xbf\x03\x55\xc8\x20\x23\x15\xc3\xae\x2b\x98\xa5\xc8\xa5\x12\x28\x0e\x1d" + - "\x5b\x73\xa3\xc1\x4d\x14\x64\x3c\xad\xce\x2a\x27\x9a\xca\x71\xf2\xb6\x9d\x79\x5a\x87\xa7\x8b\xe7\xc0\x4f\x75\x64" + - "\x69\xe2\xa7\x84\x5f\x0e\xb4\x28\x7d\x46\x71\xb6\xb3\x36\x4d\xb1\x9e\x90\x74\x09\xfe\xbe\x75\xd2\x18\x7d\xd6\xb5" + - "\xc1\x45\xa8\x85\xb5\x23\xd3\x94\x24\x12\x0c\x86\xda\xef\x28\x6f\xbb\xee\x6c\x66\x7f\x3c\xe3\xd5\x2b\xaa\x74\x37" + - "\x52\xf8\xc4\x8b\x3e\xc6\x91\x33\x66\x4b\xee\x0a\x9c\xc0\xae\xd8\xd9\xab\x38\x29\x03\x53\x6a\xbb\xd3\xd9\x69\x4c" + - "\xe8\x2a\x45\xb7\xae\xaf\x71\x63\xbb\x2a\x01\xcf\x96\x61\xe2\xbd\x92\x0e\x0b\xef\x1d\xcb\x7b\x33\xed\x78\x48\xc3" + - "\xd1\x99\x57\x6a\x36\x3a\x5a\xb2\x22\xf9\x58\x56\xe4\x17\x05\x58\xcf\x46\x7d\x74\x92\xfb\xda\x12\x16\xbc\xaa\x2b" + - "\xd3\x37\x83\xf1\xef\xeb\xeb\xf8\x48\x47\x4a\xd7\xd7\xb0\xac\x73\xd0\x47\x6b\xb9\x7a\xe8\x56\xa0\xf3\x3c\xe2\xfb" + - "\xd9\xf5\xb9\x2c\x6c\x1b\x69\x27\x20\xcb\x50\xae\xbc\xf5\x60\x33\xe9\xc2\xa9\x88\xbb\x28\x2f\x94\xf8\x8d\xbb\x53" + - "\x3a\xd7\xf3\x1f\xb1\x68\x24\xd8\xf5\xb8\xd6\x1e\x64\x0e\xda\x0e\x47\x49\xd1\xe3\xa7\x22\x9f\xf6\xe4\x91\x7a\xbe" + - "\xd0\x78\x18\xcf\x4d\x63\xe1\x3e\x44\xa9\x1f\x48\x3d\xde\x01\xc8\x58\x2f\x8c\x67\xe6\x22\xf2\xac\x9e\x95\xd6\x1d" + - "\x1c\x82\x0d\xe2\x57\xbf\xfe\xfa\x2b\xaa\x3e\x10\xf4\x61\x61\x88\xf3\xe3\x90\xa8\x3e\xca\xfe\x1c\xf7\x25\x50\x74" + - "\xae\xc7\xd3\xf6\xc2\xbe\x5b\x23\xbc\x67\xb8\xf6\x5d\xb7\x1f\x8f\x38\x0f\xc5\x08\x7e\x83\xae\x1e\x58\xd9\x73\x26" + - "\xe9\xb4\xd9\x03\x9f\x4e\xd6\x09\x26\x5e\x9c\x04\x29\xd0\x78\x46\x33\xba\x30\xe8\x69\xd2\xd6\x42\x2d\x32\x47\x1b" + - "\x24\x4d\xd8\x2d\x97\x03\x09\x6b\xc3\x00\xb6\x09\xea\x11\x25\xba\xb4\xd4\x2b\xec\x85\x07\xe9\xcb\x21\x41\x7c\x0f" + - "\x55\xd9\x0f\x3b\x02\x8f\xbe\xab\x06\x18\x15\x71\xa0\x03\xe9\x17\x67\xdc\xfd\xdd\x13\x2f\x1e\x13\x02\xa8\xed\x38" + - "\xa1\xfb\x34\xb3\x92\x56\x89\xeb\x87\x06\x45\xde\xa8\x6d\x8d\x92\x34\xaa\xe1\x5a\xc7\x22\x8a\x53\x26\x22\xdf\xa0" + - "\xc6\x58\x17\x61\xc7\xbc\xde\xaf\x60\xcf\x1c\xf9\x72\xe1\x14\xc0\x3e\x38\xba\xb5\x28\xa2\xe3\xe0\xdb\x14\x17\x71" + - "\xb5\x2a\xaf\xfc\x09\xc7\x24\xad\xee\x5c\xaf\x9a\xfa\xbc\xc8\x25\xe8\xb7\xdb\x39\xc0\x02\xfb\x0d\xf7\xf0\x21\xad" + - "\x2a\x7d\x16\xc2\xaa\xe8\x72\x38\x88\xde\x0f\xc4\xe6\x0d\xbb\x21\x8e\xdc\x82\x46\x0e\xb8\xeb\xf0\xe6\xce\xb9\xf6" + - "\x81\x8a\xf1\x04\x62\x3c\x79\x63\x3e\xb7\x18\xdb\x77\xe1\x76\xb6\xe3\x42\x6a\x37\x3e\x2e\x1e\xf4\x1b\x16\xbc\x5e" + - "\x1c\xa3\x22\xae\x5d\x6e\x5b\xf2\x1c\x48\xb2\x43\xb7\x5c\x9f\x85\x17\x2c\xaf\xbb\x9f\x05\x98\x4d\x73\xde\xdb\x14" + - "\xea\xae\x20\xd6\x90\xd2\xa1\x52\xbd\x1d\x49\x09\xaa\xb8\x4f\xfd\x78\xf8\x30\xfc\xee\x0c\x9c\x40\xce\xcc\x19\xf8" + - "\xd4\x35\x66\xd6\x86\x93\x45\x7d\x77\x7b\xfa\x40\xc9\x6d\x0e\xd5\xf1\x7d\x17\x76\xce\xf5\x75\x54\x2a\x7b\x14\xbf" + - "\x7f\x1a\x87\xff\x54\x75\x45\x57\xc9\x08\x24\x3b\xa5\xd5\x4a\x17\x8d\x74\x1a\x82\xa6\x83\x2a\x27\x9c\xd8\xc7\xca" + - "\xd3\xdb\x70\x60\xb7\x83\xf3\xd9\xeb\x39\x15\xab\xd7\xed\x6a\xdd\xda\x68\xa2\xb6\xd8\x48\x08\x45\xc8\xf7\x21\x89" + - "\xfa\x44\xa1\x7a\xb9\x42\x8a\x71\xd0\x3f\x73\xbe\x2d\x98\x0f\xd2\xe8\x73\xaf\x80\xde\xe9\xd9\xcc\xac\x5a\x70\x81" + - "\x01\x03\x2d\x7d\x75\xd7\x94\x42\xc3\x7b\x70\x16\x19\xc9\x73\x2b\x21\x47\x34\xb9\xa1\xa4\xef\xba\xe7\x01\xcf\x23" + - "\x97\x3d\xda\x6d\xb9\x71\xbb\xcc\xfc\x73\x5d\x9c\xeb\x12\x14\xfd\xa1\xd6\x50\x36\x54\x91\x66\x7b\xdc\x3c\x02\x9c" + - "\x70\xe1\x47\x9a\x68\xc0\x46\xee\xda\x32\x94\x34\x09\x90\xe5\x49\xea\x91\x14\x8e\xfe\x27\xf7\x72\x4f\x1b\xb0\x95" + - "\xfb\x7a\xe5\x8f\x19\xcf\xcb\x53\xf1\xb6\x8f\xbb\xe5\x15\x1e\x8a\x82\x37\xe1\x4f\xc1\x98\x45\x6f\x44\x50\x70\xea" + - "\x38\x87\x34\xd2\x77\x1a\x22\xc4\x20\x49\x42\x25\x67\x5d\x82\x37\xc2\x5c\xc6\x23\xda\xf6\x9e\xb8\x3f\x57\xa5\xa3" + - "\x9e\x60\x12\x46\x24\x5a\x5d\xba\x6b\x0e\xb6\xd7\xc9\xfa\xe4\xa4\x34\x23\x32\x53\xc7\x1c\xd5\x72\xfb\x5e\xb2\x94" + - "\x8e\x02\x1f\xa9\x0c\x3d\xbd\x33\xc9\x9a\x46\x54\xd8\x95\x0d\xd4\x77\x73\x64\xa3\xb7\xb8\x7f\x6a\x05\x7d\xf6\xf4" + - "\x2d\xa1\xbd\xf9\x03\x23\x5e\xa7\xb1\x91\x7c\x84\x63\x9f\xe2\x18\x0e\x95\x51\x53\x95\xfd\x50\x0b\xe6\x01\x49\xa1" + - "\x3b\x0d\xfe\x10\xb5\x75\x44\x7a\x6e\xfa\xa2\xb9\xb7\x7a\xd1\x0a\x83\xa8\x1f\xba\x63\xf1\x0a\xcb\xd0\x9b\x65\x1a" + - "\x86\xd6\x41\xc5\xf1\x3e\x46\x7c\xab\xaf\x2b\x72\x95\x56\x8b\xba\xcc\x19\x48\x12\xe3\x42\xc0\x8e\x84\x79\x91\xfe" + - "\xb9\x36\x4d\x01\x12\x09\x3e\x98\x82\x42\x1f\x2b\xf9\x5e\xdb\x76\xf7\x8d\x63\x9c\x0a\x93\x2b\x34\xba\xab\x99\x9e" + - "\x2d\x50\x9e\x82\xf4\x63\xc4\x64\x6e\xdf\xdb\x2a\xb5\x6d\xb9\xf0\x94\x58\x35\xd3\xea\xd3\xa9\x37\xff\x49\x1d\x0e" + - "\xf9\xe4\xaf\x9b\x72\xaa\x12\x67\x00\xc6\xe3\xcc\xfe\xfe\xf2\x3d\x06\xf3\x15\xd6\xbd\x2e\xa7\x2a\xb6\xcd\x93\x24" + - "\x29\x6d\x47\x74\xa6\xe0\xab\xd3\xb2\x3e\x71\x1f\xf9\x6c\x7e\xc2\x46\x2c\x9e\x6a\x7b\x55\xcd\xc4\x6f\x92\x57\xdf" + - "\x63\x1f\xf4\x6a\x55\x16\xd8\xb5\xc9\xe5\xee\xc5\xc5\xc5\xee\xbc\x6e\x96\xbb\xeb\xc6\x1d\xa6\x3a\x37\xf9\x53\xb0" + - "\x5e\x5a\xd3\x1e\xfc\xfc\xfe\xd5\xee\xd7\xd8\xe1\xc9\xa3\x6d\xca\x7a\x51\xaf\xdb\x29\xd9\x48\x70\x09\xc1\x03\x4a" + - "\x72\x9d\xe2\xd1\xda\x9a\xa6\xd2\x4b\xf9\x68\xa5\xad\xbd\xa8\x9b\x5c\x3c\x82\x15\x10\xbf\xf1\x58\x4d\x51\x77\x89" + - "\x4f\x1a\x9d\x17\x68\x75\x92\x8f\xc9\x6d\x82\x17\x67\xcb\x71\xf0\x30\x03\x70\x57\xf0\x92\x6c\x65\x8f\xb2\xa9\x62" + - "\x83\x2a\x5a\x77\x5a\x73\xd9\x4e\xc9\x4b\x65\x55\xea\xa2\xa2\x20\xcb\x45\xbb\x2c\xf9\xb9\xfb\x9b\x1e\x5f\xc2\xd3" + - "\x68\xea\xc0\x0b\x87\x9d\x5c\xb0\xd4\x47\x5b\x57\x49\x31\xf7\x88\xca\x7d\xd4\xe7\xda\xce\x9a\x62\xd5\x02\xe2\x03" + - "\x3b\x5c\xb3\x36\x81\x3b\x0b\x4d\xb9\x4a\x27\xb2\x47\xd0\x99\x89\x6c\x06\xaa\x9e\xc8\x9a\x62\x3e\x34\xaa\x2f\xf3" + - "\x62\xd0\x9b\xef\xb3\x68\x06\xf8\xc5\x7b\x73\xd9\xc6\xc3\xe0\x37\xff\x78\xf7\xf6\x87\xa8\xc7\x93\x89\x02\xaf\x84" + - "\xf8\xb6\x9b\x4c\xd4\xff\x67\xae\xac\x0f\x0d\x57\x88\xb4\xa9\x06\x4e\x3a\x61\xab\x7d\xf6\x28\x1b\x92\xd9\xd0\xb6" + - "\x45\x85\x66\x53\xf4\x39\x23\xd9\xc7\x16\xd5\x69\x69\x30\xcc\x3c\x16\x97\xa6\x9e\x9a\x0b\x66\x8f\x03\x86\x41\x3c" + - "\x36\x97\x2d\xad\x37\xfc\x9d\x4d\x15\x3a\x25\x8d\x44\x18\x1b\x04\xe8\xd4\xca\x4d\xa7\x1a\xc0\x2d\x71\xa0\xaa\x1a" + - "\xcd\x20\xee\x20\x40\x97\xf0\x4a\x81\x5d\x00\x25\x33\x7f\x9a\xb8\x9e\x97\xe7\xba\x5c\x43\x66\x5f\x57\x06\x22\xae" + - "\xdd\xb4\x09\x0c\x12\x51\x85\x7b\x93\xf9\x3c\xd3\xde\xa5\x4c\x54\x07\xce\x55\xbe\xae\xcb\x65\x29\xbe\xbe\x84\xf6" + - "\x13\x07\xb1\x64\x3d\x5e\xd5\x4d\x1c\xe8\x61\x17\xf5\xba\xcc\x29\x4f\x6e\xa4\xd8\x9e\xd2\x27\x57\xf5\x1a\xf8\x2c" + - "\x9d\xe7\xee\xef\x46\x81\xc2\x0c\xfd\x64\xb8\x2a\xc4\x81\x9a\xd3\x17\x6e\xdd\xc0\xa5\x00\x3e\x45\xd1\xd1\x31\x9e" + - "\x9d\x06\xa9\x7c\xd4\x6c\xf0\xb8\x41\xcd\x39\x4c\xb1\xd0\x4f\xf3\x76\x05\xfa\x19\xd2\x95\x92\x6f\x2d\x3e\xda\x8e" + - "\x01\xf5\xbc\x00\xeb\x66\x7f\xbe\x2e\x4b\x35\x2f\x4d\x7e\x0a\x39\x2d\x90\x26\x2b\xcc\xab\x8e\x86\x79\xd4\x37\xe3" + - "\x77\xb0\xd9\x4e\x6a\xb7\xe3\x04\x09\x87\x11\xfa\x6f\x51\x5b\x30\xf6\xda\x1a\xd2\x9b\x17\x56\xd5\xcb\xa2\x6d\x4d" + - "\x3e\x52\x17\x4d\xd1\x82\x74\xee\xf8\x53\xa9\xcf\x0f\x77\xc3\x3a\xce\x89\xcb\xd6\x02\x6e\x24\xf6\xcc\xf3\x8f\x0f" + - "\xc3\xd6\xf8\x76\x5d\xe0\x6d\xa7\xd3\x61\x41\x09\x69\x8b\xe8\xb3\x4b\xf4\x58\x1b\x20\x03\x5a\xe8\xc0\x54\xec\x6a" + - "\xf8\x18\x1a\x13\xe5\x3b\xed\xf4\xd4\xc9\xda\xfe\xc8\x0d\x36\xf2\x50\x98\xde\xee\x7f\x20\xec\xa6\x43\xf6\xa7\xf3" + - "\xef\xef\xf8\x56\xda\x30\xfd\xd6\x78\xa3\x8b\x4a\x2d\x4d\xbb\xa8\x73\xaa\x4e\x2e\xc4\xba\x29\xbd\x75\x35\x12\x5d" + - "\x5f\xcf\xdd\x3b\x70\xc7\xaa\x68\x9e\x47\xca\x16\xcb\x75\xe9\xb6\xfb\xaa\x31\xbb\xfb\xe3\x27\x0a\x52\x17\xb5\xeb" + - "\xc6\x6c\x27\xde\x0b\xe0\xe2\x26\x33\xfa\x33\x73\x16\xa2\x62\xd6\x0d\xc5\x42\xa2\x3b\x5c\x27\x63\x70\x38\xd2\xb3" + - "\x90\xb5\x05\x2d\x54\xbe\x4b\xdb\xf7\x64\x8d\x75\xd7\x72\x84\xc0\x31\x3c\x2f\x23\x5e\xe0\x9f\x7f\xfa\x1e\xf6\x7e" + - "\xbd\x76\xa4\xb3\x2d\x76\x91\xf9\x01\xc7\x34\x3c\x6f\xee\xf7\xcf\x3f\x7d\xef\xbf\x60\xb5\x3c\x71\x4b\x36\x52\x34" + - "\xa0\xae\xde\x7a\x2a\xdb\x7d\xe5\xeb\xe1\x74\x45\x18\xc6\x8d\x37\x10\x3e\x7a\xef\xd3\xb2\x6d\x79\x1f\x59\xf2\x3e" + - "\xf2\x5e\x8c\xea\x5c\x53\xd3\x2b\x76\xb8\x24\x78\x0f\xd0\xf4\x3b\xe9\x06\x99\x23\x74\xa7\x47\xee\x9e\xac\x7a\x85" + - "\x5d\xb9\xeb\x87\xfc\x1c\xe6\x45\x63\xfe\x0e\x45\x43\x2d\x10\x0e\x78\xae\x9b\x42\x9f\x50\xd7\x0a\xd1\x1f\xa0\x73" + - "\x8e\xd5\x04\xc5\xa5\x9f\x6c\x71\x06\xbb\x56\xbd\xf5\x0a\x13\x8d\xfb\x1d\x16\xea\xe3\x04\xb4\x1c\x36\x40\xd3\x8e" + - "\x4f\x9f\xe3\xb3\x60\xee\xb9\x04\x4f\xf8\xd0\x55\x2e\xe0\xd8\xd5\x78\xc4\x85\x55\x69\x2d\xc5\x5c\x15\x2d\x7a\x16" + - "\xbe\x78\xfb\x06\xd0\x6c\x95\xf7\x1f\x52\xb3\xba\x2c\xbd\x8f\x28\x33\x97\x2f\x5d\x65\x7d\xbd\x00\x00\xac\xa4\x81" + - "\x10\xba\x7e\x7d\xdd\x79\x87\xf9\xbb\xd4\x90\xa3\x33\x39\x9c\x2e\xed\xa4\x0f\xf2\x67\xc6\xdf\xf5\xc0\x8f\xf7\x85" + - "\x99\x9b\xa6\x31\x39\x2e\x7e\x4e\xbf\xc2\x7c\xf3\xfb\xc1\x90\xef\x0b\x4c\xf4\xfb\xa2\x53\xd2\x4f\xfc\x20\x03\xcf" + - "\xf2\xa5\x59\xd6\xcd\x55\x16\x56\xe6\x5d\xab\xdb\xb5\xdd\xcd\xc1\x41\xc6\x89\x3a\x3e\x57\x30\x2e\x32\xbc\x7e\xee" + - "\xe6\xd0\xcd\x8b\xf8\x09\xc7\xce\x57\x43\x1b\x5f\x0d\x5a\x76\x48\xb5\x00\x2c\x0c\x79\x50\x54\xed\x05\x56\x92\x33" + - "\xbe\xf3\x9e\xbf\x5c\x47\xfc\x82\xf1\x7e\x44\x0b\xef\xbd\xf2\x1a\xa4\x2a\xdf\x3b\x13\x9c\x97\x44\x4a\x37\x7d\x52" + - "\x37\xad\x5a\x1a\x6b\xf5\x29\x97\x6d\x9e\x9d\xa0\xaf\x44\x36\xd3\xd5\xcc\x94\x26\xcf\xfc\x77\xaf\xf4\x99\x51\x97" + - "\x0b\x54\x1e\x61\x33\x07\xc1\x37\x40\xe7\x57\xef\x50\x94\xdb\x1b\x09\x49\x1d\x2e\x29\xcb\x34\x42\x2d\xb4\x5d\x00" + - "\x7c\x68\x64\xa9\xc0\x80\xe5\xd8\xce\x27\x69\xf2\x99\xb9\x12\xb2\xac\x23\x60\xe0\x56\x15\x45\xf0\xd1\x38\x23\x70" + - "\x65\xaf\xe3\x4a\x68\x4f\x22\x18\xc7\xef\x0e\x90\x54\xd2\x5b\xef\x46\x05\x2d\xaa\x03\xc5\x1e\xd9\xe4\xb3\xd7\x4b" + - "\xf0\xd4\x70\x18\x2b\x4d\x92\x52\x47\xd8\xff\xa3\xfd\xe3\x1e\x65\x37\xbe\x52\x8f\xa5\x5e\xa5\xa3\x13\xd9\xf2\xdd" + - "\x49\x6b\x3e\x33\x57\x3d\x80\x00\xd1\xc7\xc4\x53\x50\x15\x3e\xca\x8b\x22\xaf\xe5\xd4\xde\xc8\xa5\xfc\x49\x5f\x48" + - "\xf4\x06\xb7\x64\xcf\xca\x32\x5e\x35\x89\x68\xd3\x01\x49\x90\x4b\x74\xb8\x61\xe6\xa6\x01\x12\x37\x69\xfe\xb9\xbb" + - "\x80\xd0\x74\x83\x4b\x80\x6f\xac\xdb\x38\xe2\x5c\xdc\x81\xbe\x4e\xfb\xa7\xbc\x23\xf9\x8f\x4f\x7c\x01\x5d\x16\x6b" + - "\x49\xdf\xf5\x1c\xc5\x23\xaa\xf4\xf8\xae\xd7\x11\xac\x76\xe7\x58\xa7\x58\xd5\x1b\x16\x8f\xb1\xe3\xd2\x59\x7a\x7b" + - "\x6e\x9a\xa6\xc8\x85\xb3\x44\x6c\xd3\x97\x53\x57\x53\xd9\x37\x64\x75\xdf\x94\x61\x7c\xf3\x6c\x08\x8b\x7d\x64\x6b" + - "\xfd\xd4\xde\xde\x41\x59\x05\x69\x95\x7d\x5b\xea\x55\xb2\x9c\x33\x0f\xd6\x4c\x5d\x8d\x8b\x48\x0a\xf1\xd7\x98\x3e" + - "\x78\x7d\x77\x0e\xc6\xe9\xe4\x3b\x64\x02\xf4\xef\x57\xbb\x6c\x75\xad\xcc\x45\x48\x40\x0b\x41\xf2\x17\xe0\x62\xad" + - "\x5b\xc7\x02\x5a\xd3\x9c\x1b\x0b\xd9\x02\xeb\xca\x08\x5d\x6f\x18\xc8\x11\xb6\xe5\xd6\xf7\x48\x75\x1f\x8f\x5c\x17" + - "\x7c\x99\x5e\x12\x90\xa8\x08\x91\x3d\x37\xb3\x35\x31\x23\x7a\xb5\x6a\xea\x55\x03\x4a\xdf\x64\x3a\x99\x6e\x8f\x75" + - "\x79\xa1\xaf\xec\x00\xdb\xc2\x47\xd8\x95\x48\x4b\x7b\xf3\xe7\x16\xf3\x39\xdc\x18\xd2\x1e\x8b\xaf\xe0\x9e\x89\xa2" + - "\xd0\xa0\xa9\xf7\x78\xc7\xcb\x65\x04\x3e\xea\x3d\x31\x18\xa1\x90\xe3\x73\xe8\x66\x8a\x16\xb9\xed\xfa\xa8\x6d\x05" + - "\x6f\xfc\x31\xb4\x3b\x10\x95\xa6\x51\xef\x5b\x79\x5d\x99\x81\xda\x1b\xf5\x95\xe9\x19\x2c\xfc\x73\x13\x92\x07\x3c" + - "\x43\x38\xfd\x5c\x72\x22\xfc\x63\xbc\x6a\xea\x65\x61\xcd\x80\xfd\x08\xc7\xcc\x80\x80\xf2\x36\xe6\x45\xc6\x3a\x47" + - "\x26\x9f\x96\x82\xac\x79\x07\xb4\x34\xae\x9b\xe2\x35\xc6\x96\xf2\xcb\xb9\x2e\xca\xd0\x25\x72\xee\x81\x00\xa3\xd9" + - "\x42\x37\x7a\x06\xea\xf1\x07\x7f\x79\xf2\xc5\xfe\x14\xa5\x58\xa4\xb3\xae\x7b\xb5\xd7\x68\xb8\xc1\xe4\x79\x08\x12" + - "\x22\x75\x3a\x9b\x1c\xd5\x40\x08\x61\x4b\x70\xab\x42\xef\x12\x55\xb4\xfc\x3d\x05\xad\xce\x75\x69\xaf\x50\x50\xaa" + - "\x08\x3c\x23\x96\xb8\x31\xe4\xe1\x8b\x69\x88\x71\x9f\x5d\xa1\xd4\xed\x4e\x8d\x17\x9f\xb8\xda\x5f\x8c\xd2\xa5\xad" + - "\xc1\xc1\xc2\x55\xe7\x6a\x06\xa1\xc4\x90\x59\x54\x9f\xeb\xa2\x64\xf6\xdc\x8e\x51\x74\x1a\x28\x10\xe4\xd0\x89\x84" + - "\xfe\x88\xfc\xf7\x87\x14\x86\x27\x30\x58\xdd\x9c\x8d\xe0\x21\xac\xb3\x78\xc3\xd3\x32\xea\xd1\xbf\xee\xa8\x6c\x32" + - "\xc9\xbc\x3f\x32\xe4\xb5\x2b\xb4\x25\xf9\x92\x21\x22\xda\x1a\x09\xaa\xb6\x6a\x65\x1a\xd5\x16\xb3\x33\xd3\xaa\x07" + - "\xfb\x8f\xf7\xf6\xbe\xc4\x7e\x13\x94\x27\xbb\x3f\xd2\xe7\xd7\xd7\xfe\x09\x27\x9d\x95\xef\xf0\x69\x68\xfa\xe5\x65" + - "\xeb\x56\x5c\xb8\x07\x30\x08\xa3\xb0\xf5\xa7\xe8\xcc\xc2\xf0\x8b\x7e\xda\x80\xa8\xf9\x09\x3e\xec\x6e\xae\x8e\xc5" + - "\xb8\xd5\x4c\x4a\x68\xec\x92\x51\x80\x8f\x02\xe0\xc8\xa3\x8e\x28\xb8\x2c\xf1\xbc\x4e\x17\xb5\x6d\xa7\x70\x90\x97" + - "\x85\x85\xd6\xb6\x83\xbd\x1d\x6a\x7d\x81\x95\xa6\x40\x51\xab\x6e\x10\x05\xac\x77\x1a\x3d\x81\x27\x38\xa9\x4b\xdd" + - "\xbf\x3f\xc0\xa0\x0c\x0f\x3b\x42\xbf\x71\x69\xef\x1f\x1c\xf4\x2c\xf8\xf5\x35\x97\x79\xdc\x5b\xe6\xb1\xb4\x27\xfa" + - "\xfa\xbe\xc0\x2f\xa3\xfa\x41\x1b\x00\x69\x8f\x33\x75\xa8\xb2\xaf\xf7\x32\x35\x55\xd9\x97\x5f\x7e\x81\x50\x25\xf7" + - "\x0f\x0e\x98\xa6\xa5\x8a\x7f\x5f\x5b\xb7\x7b\x77\x54\x8a\x7b\x3b\x4d\xc5\xc8\x3a\x53\x8c\x37\x9b\x47\xf9\xc6\xb5" + - "\xe0\xf9\x68\x45\xa0\x18\xb8\x1a\xc8\x50\x34\xc2\x93\xad\xe7\x5c\xa2\x37\x38\x83\xde\x1d\x08\xb5\xa5\xf6\x9b\x70" + - "\xe4\x76\x74\x50\xe8\x77\x53\x46\x82\xd9\x6f\x25\x43\xfc\xb6\xee\x70\x99\x0f\x85\x47\xca\x0a\xb7\xf9\xe0\xdd\xbd" + - "\xed\xd5\x3b\xbc\x65\x2f\xb4\x45\xe1\x08\x61\x15\x8a\x1c\x37\x2b\x55\x34\x52\x90\x86\x19\x30\x2f\xc3\xa4\xf4\x48" + - "\x1f\x9c\x16\xd3\xb5\x94\x0c\xe4\x17\x03\x1a\xd6\x79\xd1\x98\x54\x3d\x61\x55\xed\x16\x00\x34\x17\xda\x9e\x81\x0d" + - "\x72\xfb\x5e\xa4\x9e\x00\x31\x13\x3f\x0b\xfd\xff\x05\xb8\x79\x0c\x34\x74\x4c\x8a\x35\xad\xaa\xfd\x98\x42\xae\x1a" + - "\x59\xcf\xc3\x87\x5e\x3b\x01\x16\xb1\x9d\x1d\x42\x2b\xf7\x9e\x2c\x42\xf2\xf6\x20\x00\x19\xa8\x32\x5a\xdd\xb4\x59" + - "\xba\x40\x3f\xaf\x56\xe8\x1b\xe4\x53\xb9\x45\xd4\x0d\xff\x18\xb7\x35\x94\xf3\xfc\x36\x7d\xfc\xc2\x91\xf4\x65\x51" + - "\x19\x11\x83\x02\x61\x66\xc4\xc0\x62\x55\x0b\x6d\x43\x8c\xe9\xfd\x10\x71\x4a\x16\x32\x6a\x4b\x54\xfb\x4e\x13\x72" + - "\xe9\xcf\x3f\x7d\x2f\xdc\xa5\x3e\x07\x3d\xd0\x95\xf7\x0c\x75\x25\x5e\xcf\xbd\x0d\x70\xf7\x5d\x51\xcd\x58\x5f\xad" + - "\xab\x7c\x52\x37\xee\xf5\x0f\x75\x65\x76\xdf\xc0\x54\x93\x91\xb0\xd4\xee\x22\x42\x55\x09\xeb\xc8\x60\xa8\xa8\xcd" + - "\xa3\x1a\xde\xd4\x4d\x50\xd9\x81\xa6\x8b\xc3\x42\x79\x81\xb0\x17\x55\x2d\x47\x4b\x5c\xb7\x1c\xf3\x50\xda\x3a\x5e" + - "\x53\x48\x77\x61\xc3\x35\x38\xa2\x20\x18\x7c\xd3\xd6\xee\x1e\x84\xf2\xf2\xf0\x7a\x7e\x49\xf4\x98\x48\xa7\xda\x71" + - "\x7f\x62\x18\x3d\xfb\xaf\x72\xa1\xa1\x23\x29\x0f\x81\xa2\x1c\x66\x70\x87\x72\x7d\x01\x70\xfd\xc1\x37\x5f\x7d\xfd" + - "\x78\xca\x88\xb1\xf0\xd6\xd6\xc8\x20\x17\xed\xe7\x16\x68\xcb\xda\xc2\xc9\x02\x73\xbd\xdb\x5a\x6b\xf0\xd4\x6b\x1b" + - "\x82\x2c\xa2\x6c\x54\x58\x77\x07\x6f\xd0\x31\x2a\x42\x43\x59\x54\xc8\x6d\x44\xea\x04\xbe\x3a\xa0\x44\x37\x63\x9d" + - "\xe7\x13\x9a\xd6\xf6\x8c\x31\x02\xe9\x62\x74\x5b\x37\xc7\x9e\x24\x7e\xfe\xdb\xe7\x81\x0b\x01\x9d\x79\x48\x41\x4d" + - "\xdf\x72\x85\x82\x8f\x68\xed\x48\x65\x9f\xed\xff\x76\x90\xa9\x1d\x44\x31\x00\xc4\xb0\xa9\x6c\x4f\xc4\x32\xe5\x39" + - "\x1a\x51\x08\xd9\x96\xe3\x9a\xc2\x9a\xed\xfc\x89\x85\xca\xa2\x56\xbb\xa8\xab\x94\xae\xb2\xf7\x14\xdc\xb6\xff\x47" + - "\xa0\x4b\xac\x54\x31\xf7\xd6\xf3\x65\x9d\x9b\xb1\xb8\x2e\xc4\xab\x3e\xac\x1e\x69\x4c\x3f\x0a\x43\x10\x9e\x13\xc4" + - "\x15\x27\x82\xfe\x40\x65\x9d\x9e\x66\xa3\xbb\x6b\xed\xb8\x00\x33\x91\x6b\xf5\xe9\x9f\x6f\x3f\x4c\x48\x68\xbb\x5b" + - "\xd3\xad\xf3\x0d\x5e\xb9\xb3\x56\x4e\x28\x9f\xea\x13\xe3\xc8\x84\x95\xe4\x40\x5e\xbf\x82\x2e\xc0\x6f\x61\xcf\x47" + - "\xe4\x7a\xd8\xf5\x82\x89\x94\x05\x22\x6f\xc5\xbe\xd1\x45\x7e\xf6\xa3\xa4\xfa\x94\xf2\xf3\x60\x9e\xa1\x81\x9d\xa9" + - "\x23\x3b\xa3\x83\x60\xdc\x8c\x14\x4a\xfa\x6e\x50\x75\x95\xc6\x72\x6f\xea\x09\xf4\x32\xc3\x8a\x49\x1b\xd9\x89\x0f" + - "\x82\xe1\x93\x71\xff\x48\x7a\xb6\xa2\x7f\xf8\x21\x1f\xfb\xcd\x45\x76\xd4\x40\x75\xaa\x65\xef\xbe\x43\x4c\x59\xb0" + - "\xe3\x7d\x05\xdc\x89\x7a\xaa\xfe\x79\xb0\x37\xde\xdb\x87\x63\x26\x12\x37\x88\x56\x20\x4a\xc9\x3d\x15\xf7\x11\xba" + - "\xf0\x83\xb7\x0a\x69\x1c\x03\xca\x1c\x2a\x23\x0a\xf4\x95\x5d\x24\xca\xca\x4d\x0b\x55\x8c\x42\x61\x40\x36\xeb\x4b" + - "\xb5\x5d\x5f\xb0\x09\x97\x4a\x4e\x96\xc5\xd2\xa0\x81\x1d\x42\x5f\x74\x53\x5e\x21\xd7\x23\xb6\xda\x89\x99\xd7\x8d" + - "\x79\xe7\xae\x13\x50\xf3\xcb\x27\x84\x26\x9b\x68\xed\xbd\x17\xb4\x25\x60\x3f\xbf\x07\x63\x16\x49\x44\xb6\xa2\xca" + - "\x99\xd8\x4e\x27\xeb\x06\x42\xeb\x9d\xad\x3a\x0c\x15\x49\xf7\xe9\x48\xe1\x29\x20\x25\xb8\x9b\x46\x95\x75\x75\x6a" + - "\x1c\x47\x84\xda\xec\xd2\x67\x74\x95\x9a\x6e\xf8\x26\x13\x9c\x60\x65\x5b\x5d\x96\x41\x79\xe2\xf6\x6a\x24\xe4\x8b" + - "\x65\xfa\x43\x91\xb4\x3e\x55\xfb\xde\x8b\x6a\x7f\xe4\x45\xfc\xa9\xda\x57\x37\xa9\x67\x70\xa1\x8e\x07\x6a\xc3\x5a" + - "\x01\x22\xa1\x00\x8a\x08\x0a\x0d\x40\xb6\xbc\x95\xd9\x0d\xe6\xce\xbb\x99\x5d\x76\x6d\x00\x2b\xa0\x13\xca\xf4\xba" + - "\xad\x77\xe3\x0d\x70\xbf\xab\x61\x41\x95\xc9\xee\xfe\x08\xfc\xc3\x7c\xe3\x59\x5f\xd2\x56\x5c\xa8\x60\x1a\x50\x07" + - "\x6a\x5f\xb8\xe5\xc2\xb6\x92\xdc\x6f\x20\xc9\x92\x49\xf5\x64\xb8\x6b\x87\x0a\xb8\x54\xc8\x93\x9a\x2a\xcf\x46\xea" + - "\x28\x6c\xc1\x84\xdc\x4f\x26\xea\x3d\x9a\x16\x25\x97\x00\x5e\x51\x48\x41\xd8\x16\xf9\x37\x89\x56\x2e\xad\x91\x8e" + - "\xb3\x33\x2d\x55\xd2\xcd\x06\xe1\xf5\x6b\xb0\x39\x33\xfa\x32\xf3\xa1\xc3\x23\xd1\x46\x82\x05\x2c\x3c\xfd\xac\x98" + - "\xac\x58\xa5\x65\xc1\xca\x1e\x2b\x8c\x47\x78\x66\x3c\x6e\x73\x8f\xfb\x1f\x84\x77\xd7\x2b\x7d\xea\xea\x0d\x28\x10" + - "\x9a\x5c\x1e\xe5\xd9\xc3\x0f\x36\xea\x4b\xc3\xf2\x1b\xc9\xf4\xbd\x2b\x96\x2b\x48\x28\x8b\x58\x13\x35\x33\x31\x34" + - "\xec\x58\x63\x89\x65\xfa\x73\x19\x33\x8d\x64\x0d\xab\x3b\x69\xa0\x35\x30\xe7\xa6\x21\x87\x9e\xc2\xfa\x9e\xfa\xa0" + - "\x0c\xec\x17\xea\x0c\x47\xaa\xd2\x4e\x9a\x79\xe7\x35\x88\x22\xde\x6e\xa4\x52\xb2\x0a\x11\xd2\xec\x41\x3f\xe2\xe3" + - "\x4c\x67\x59\x86\x77\x2c\x89\x9d\x18\x6d\x0b\xdd\x34\x69\x2b\xd3\x16\xa5\xf7\x39\x60\xc3\x80\x7d\x4f\xec\xba\x3e" + - "\x6b\x55\x1f\xae\x37\x29\xc9\x81\xff\xcc\x72\x00\xd1\xad\xea\x0b\xbc\x04\x69\x9b\x3c\x96\x8d\x95\x46\x37\xde\xa4" + - "\x8e\x66\x5e\x48\x3e\x6f\x43\xdb\xd1\x7e\x0e\x92\x80\xfb\x92\x37\x76\x52\xa6\xd3\xa5\x17\xa6\x31\x90\x8c\x67\x66" + - "\x84\x16\x76\x0e\x10\x05\xee\x1e\x39\xd5\xcd\x89\x3e\x35\xa9\x25\x79\x32\x51\x83\xaa\x56\x4b\x0d\x79\x97\x16\xf5" + - "\x05\x10\x68\x11\x73\x43\x3a\x42\x40\xf7\x20\xe0\x96\x21\x9d\x8e\x40\x04\xa5\x5f\x44\x98\xe4\x99\x08\xe9\xb9\xdb" + - "\x25\x41\x1d\xf8\x7d\xc0\x89\x1a\x02\x59\x6a\x55\xa0\x59\x9b\x08\x19\xa9\xcb\x01\x4d\x4f\x7d\x29\x61\x84\x53\x49" + - "\x96\x36\xd4\x7c\x4d\x62\x98\x0f\xd6\x08\x95\x1c\xa8\xc7\x7b\x7b\x40\x81\xf0\xc1\x5f\xd5\x17\x7b\x7b\x7c\x67\xae" + - "\x2d\x26\x94\xdd\xfb\x52\xb4\xf0\x77\x23\xc2\x19\x1c\xd3\x12\x96\xb7\x1b\x5f\x27\xfd\x86\x3f\x3d\x2e\xb5\xb3\xe8" + - "\xac\x25\x0a\x2b\x78\xe1\xa4\xba\x01\xc8\x76\x17\xfa\xaa\x2f\xa2\x0a\x7d\xa9\x2f\x34\xb8\xff\xb5\xc3\x68\x41\xa8" + - "\x37\x9f\x1a\x4b\x95\xc0\x9a\xfb\x59\xe5\x7c\xd8\xa8\x61\x9d\x2d\x74\x51\x45\x20\xe6\x49\x38\x56\xa0\x59\xff\xdd" + - "\xe2\xce\x6d\x02\xcf\xd6\x16\x53\x0f\xaf\xb8\xef\x89\x6c\x8d\xbc\x90\xb3\xd8\x14\xb9\xec\x56\xb9\x75\x97\xac\x73" + - "\xe0\xbf\x4a\x2d\x1f\x9f\xd2\x1b\x27\xc6\x7c\x7a\x27\x3a\x42\xcf\xc6\xc6\xa5\x23\x3f\xdc\x3c\x52\xe5\x21\xe8\x23" + - "\x6d\xfc\xc7\x7b\x5f\x06\x5d\x37\xea\x37\xbf\x7b\xf9\xec\x85\x84\x1f\x89\x48\x71\x56\xd5\x54\x5f\xf6\x34\x6d\xa9" + - "\xf5\x7d\x8a\x6e\xa6\xb4\xc9\x2f\xf6\xbe\xbc\xa5\xf6\x96\xeb\xc8\x92\x60\x1b\xd6\x6c\xa3\x2a\xb3\x34\xed\xe7\xd6" + - "\x67\x40\x20\xdc\xd6\xf4\x2e\x8c\xea\xe6\xdd\x0f\xb6\x38\x6f\xcf\x0c\xd6\x20\xff\x3e\xe8\x45\xb6\xb6\xd8\x1a\xe4" + - "\x5f\xc2\x03\xbf\x6a\x82\xda\xdc\x97\x6f\xe8\xda\x8d\x7a\x83\x8a\x49\x43\x46\x04\xac\x18\xdc\xfe\x43\x2f\x7d\xc1" + - "\x16\x41\x89\x9b\xa5\x2e\x01\x8b\x35\x8c\x03\x8d\x4c\x30\x97\xe0\x3a\x5f\x57\xc8\x55\x92\x0d\x92\xfb\x6b\xe5\x5d" + - "\x99\xae\xfb\xf5\x35\x1a\x9b\x3b\x56\xc2\x78\x2d\x30\x78\xa1\xe3\x06\x02\x14\x34\x4a\x4a\xc7\x6b\x1b\x52\xe5\xa5" + - "\xb1\x09\x92\xfa\x83\x80\xcd\x92\xeb\x9c\xbc\x5e\xa4\x5b\x57\x64\x31\xe5\xa1\x3c\xed\xbc\xa2\x6e\x0e\x3a\xdc\x41" + - "\x20\xed\x34\xbc\x9d\xe4\x0a\xc2\x35\x9b\xbc\x74\xe3\xdb\x48\xc9\xb6\x84\xdf\xd3\xb8\x31\xb6\x2e\xcf\xcd\x2f\x45" + - "\xbb\xe8\x91\xc9\x8e\x02\x5b\x63\x05\x57\x84\x97\xee\x71\x7f\xce\x0f\x51\xb5\x1b\xf8\xc6\x9a\x99\xd9\x16\xf5\xe2" + - "\x1a\x1f\xf7\xdc\x21\x77\x18\xfc\xe5\xec\x3d\xaf\x73\xcf\xd2\x81\x37\x15\x5b\x71\xa4\xbb\x55\x87\x17\xf8\xd7\xc4" + - "\x87\x30\xb3\x87\x24\x4a\x50\x34\x8a\x13\xed\xc1\xc1\x15\xc3\x64\x68\xf3\x84\x41\x8f\xa2\x4f\xf9\xa8\x4e\x6f\x99" + - "\x81\xe7\x24\x18\xc2\xef\x8e\x21\xd8\xf5\xfc\xd3\x67\x9a\x1a\xf8\xaf\xca\x4d\xdc\xa5\x0d\xb2\x93\xb0\xee\xba\x03" + - "\x41\x12\xdb\xb3\x7f\x3c\xfb\x55\xcd\x30\xf6\x46\x1c\xe0\xfb\x03\xb5\xbb\x1b\x19\x15\xa2\xfc\x6e\xb7\x19\x14\xea" + - "\x55\xd6\x8f\xb1\xb4\x7d\xaf\x6b\x4c\x21\xcf\x83\x53\xd3\xfe\xe3\xdd\xdb\x1f\x3a\x0e\xbc\x48\x82\xbd\xa3\x46\xec" + - "\x4c\x4d\x9d\x80\x64\x48\x3d\xa5\x47\x2a\x03\xbf\xfc\xc8\x63\xf9\xd4\xb4\xef\x20\x44\xa3\xd3\xd4\xa7\x36\x22\x92" + - "\xaf\x88\x96\x28\xee\x23\x45\xba\x8d\x60\x91\x8e\x30\xad\xd3\x48\x65\xab\xda\xb6\x31\x7a\xba\x2a\x46\x6c\x6b\x96" + - "\x40\xea\x47\xfc\x30\x06\x89\xee\x1d\xad\x74\xf5\x99\x4c\x14\x44\xed\x05\x54\x5f\xaf\x8e\xe4\x27\x98\xe7\x0d\x1d" + - "\xdd\xb7\x6f\x81\x30\x23\x43\x03\xaf\xbd\xc8\x55\x29\x9d\x42\x71\xc1\xfd\x1c\x62\x48\x71\x00\x6a\xdb\xe4\x06\x1d" + - "\x4f\xb2\xdb\x3f\x03\x11\x25\xe0\x86\xe9\x1b\x9d\xd2\x54\xc4\xe0\x6d\x53\x04\x5a\xf1\xcf\x30\xaf\x1b\x69\x17\x59" + - "\xa3\xc3\xdd\xda\x0e\xa9\x69\x9e\x4a\x34\x7c\x72\x00\xd1\xea\x64\x5d\xcd\x16\xaa\x9e\xfb\xa9\xc6\xbb\xcf\x1b\x7a" + - "\x28\xc1\x15\x9c\x19\x34\xf4\x75\x97\x38\x58\xd5\x46\x2a\x9c\x88\x51\xe7\x88\x4a\x7a\x14\x13\xab\x91\x50\x83\x74" + - "\x36\x89\x58\x65\x01\x24\xde\x32\x20\x97\xc4\xe9\xbe\x0d\x77\x5a\xc0\x32\xcb\x0c\xee\x54\xe5\x6f\xe6\x5c\x97\x3f" + - "\x83\x69\x25\xda\x74\x31\x24\x72\x67\xd5\xa2\x45\x4b\x23\xe2\xc2\x8a\xf1\x61\x91\xb1\x6c\x21\xe4\x8b\x63\xe0\xc2" + - "\x13\x8e\xc2\xf4\x31\x22\x37\x12\x76\xb9\x17\xb5\xfc\xa2\xd1\xab\x67\x65\x94\x33\x0e\x02\x82\x04\xbe\x99\x2b\x72" + - "\x07\x7a\x1f\x7d\x92\x18\x82\xff\x5c\x52\x53\xea\x09\x56\x16\xe5\x33\xbd\x2d\x85\x3b\x66\x40\xf6\x90\x1c\x7c\xe9" + - "\xbc\x0f\x59\x20\x21\x62\xc0\x55\x8e\x26\x5a\x8c\xcd\x40\xf4\x6b\x28\x0d\xaf\x42\x8e\x13\xd7\xfa\x28\x54\x3b\xae" + - "\x2f\x2a\xd3\x78\xd8\xe3\xe1\xd8\xfc\x73\xe0\x58\xad\xf1\xac\x04\x0d\x0c\x46\xd7\x76\x52\x99\xe1\xb7\x21\x2f\x4b" + - "\x18\xb5\x6b\x6e\x8c\x31\xcb\xdf\x82\x6a\x39\x1a\x43\x7c\x7b\x42\xd9\xa5\x5e\xf5\xe8\xdd\xdc\xc2\x88\x7c\x7d\x9d" + - "\x7c\x20\x90\xba\x00\x20\x57\x08\xf2\xf3\xf9\xa2\x28\xf3\x24\x4d\x06\x27\x26\xe9\x94\x7b\x9a\x08\x2e\x22\x79\x02" + - "\xaf\xc4\x18\xad\xae\xbc\x7c\x3d\xb4\x2a\xc9\xf6\xeb\x06\xf3\xba\xaa\x62\x87\x55\xb9\xd7\xfe\xa7\x37\x17\x34\xfe" + - "\xe9\xdb\xeb\xee\x54\xb8\x04\xfe\xb7\x31\x4d\xad\x84\xac\x32\xe5\xdc\xa3\x56\x0d\xe2\xfd\xc2\x8f\xd3\xd4\x8a\xfe" + - "\xfb\xf8\x68\x84\xdd\x16\xb3\xaf\x98\x13\x96\x16\xc5\x17\xec\xcd\xc6\xe9\xea\xbb\xed\xc4\xdf\x95\xf3\x2f\xea\xc6" + - "\x27\xad\xc7\xa6\xb3\x2e\x5a\x3a\xec\x5b\x99\xa9\x1c\x49\x34\x86\x75\x95\x8c\xa2\x87\x86\xe3\xf9\x1b\x0c\x6f\x4b" + - "\x65\xdc\x4d\xaa\x44\x09\x4e\x4f\xea\xfc\x2a\x93\xbc\x5c\x27\x6b\x3c\x98\xb9\x91\x79\xc5\x64\xaa\xee\xe8\xb8\xd3" + - "\x6e\x93\xa9\x1f\xbb\x35\xe9\x40\xfb\xfb\xf0\xee\x55\x33\x26\xeb\xc6\x78\x51\xe4\x39\xa4\xc0\xef\xcd\x8e\x22\x01" + - "\xea\xdf\xae\x4c\xa3\xd5\x5f\x0f\xd4\xfe\xe3\xf1\xfe\x63\x7c\x89\xcf\x1a\x83\x01\x60\xf5\x7c\x6e\x4d\xfb\x4b\x91" + - "\xb7\x0b\x34\x79\xe1\x83\xef\x4c\x71\xba\x68\xad\x02\x04\x80\x76\xa1\x2b\xf5\xbb\x69\x6a\x55\x57\xca\xd6\xcb\x40" + - "\x35\xc3\xed\x85\xb9\x8b\x42\x65\xae\x51\x50\xde\x89\x17\x58\x29\xbc\xa1\x1b\xa7\x6f\x74\xe7\x85\x05\xb0\xac\x0d" + - "\xc3\x63\xbc\xc5\xcd\x13\xc3\xc5\xc5\xad\xb6\xcd\x79\x10\x1e\xef\xa9\x03\x35\xf9\x7f\x1e\xef\x4d\x20\xfe\xaa\x39" + - "\x69\x34\x38\x1d\x1e\xa8\xc9\x87\xa3\x0f\xc7\x84\xc7\xfe\xfc\xa7\xef\x5f\x61\x16\xd5\xc3\x0f\x15\x95\xc4\xcc\x26" + - "\xad\x69\xd8\x5d\x10\x90\xdc\xf1\xe9\xf5\xc9\xba\x6d\xeb\xea\xba\x58\xea\x53\x40\x80\x37\x2d\x80\xc1\x0f\x3f\x9b" + - "\x14\xf2\x63\x8d\xe3\x82\x2f\x01\x96\xe3\x1a\xa1\x1f\xaf\x9d\xf8\xa1\x1b\xa3\xaf\xcf\xcc\xd5\xa9\xa9\x86\x93\x02" + - "\x3a\xee\x15\xf9\x27\xeb\xa2\xcc\x7f\xd4\x8d\x5e\xb2\xf3\xd6\xe5\xc8\x89\xde\x23\x25\x1c\xc3\x46\xe0\x1c\x11\xd0" + - "\x95\xc8\x9d\x9e\xa1\x88\xd2\x24\x40\xf5\xc9\xc7\xb0\x71\x41\xc6\x47\x9c\x75\x43\x49\xb9\x8a\xd6\x2c\x41\x83\x17" + - "\xb1\x64\xd0\x68\xc4\x42\x9d\xc7\xfe\x0b\xd2\x53\xed\xfa\x5a\xf1\x0c\x93\x2f\x06\xf6\x5d\xc5\x20\xbb\x98\x2b\x13" + - "\xc0\x87\x42\xd3\x18\x24\x6c\x67\xba\xd4\x0d\x29\x12\x75\x9e\x87\xd1\x9f\x6f\x22\x71\x93\x89\x7a\xed\xbe\x27\xf4" + - "\x1a\xac\x41\x0d\xb0\xe6\x9a\x35\x16\xc3\x91\xc2\xf8\x7d\x70\x51\xa9\xd6\x4b\xd3\x14\x33\xcc\x0f\x47\xad\xf5\xcc" + - "\xb9\xda\x51\xd9\x51\x06\x46\x71\xce\xb7\x19\x47\x2f\x1e\xaa\x82\xcd\xde\x3b\x2a\x3b\xce\x46\xea\xbc\x6f\x89\x52" + - "\x92\x1b\x90\xe3\xbc\x81\xd1\xcf\x61\xf0\x46\x73\x4d\xf2\xb2\xf5\xc5\x4c\x46\x6b\xc8\x91\xbc\xbc\x88\x68\x9c\x85" + - "\x20\x8a\xa2\xa2\x4a\x70\xc2\x6e\x1b\x67\x45\x69\x8d\xdd\x48\xea\x93\x8f\x1c\x85\xb1\x71\x4c\x37\x72\x2c\xdd\x4e" + - "\xd1\x5a\xf8\x4e\x45\x0b\x0a\x7d\x8a\xd0\xcd\xa2\x3d\xc9\xb9\xe2\x9c\x38\x51\x37\xcb\xc0\xb8\x81\x6f\x1f\xfa\xf5" + - "\xc1\x37\x67\xe6\x6a\x42\x79\xc8\x30\xd0\x58\x61\x64\x1d\x3b\x6c\x4a\x17\xcb\x88\xc8\xe8\x68\x58\xe2\x20\x51\x0f" + - "\x5d\x8f\xdd\xc1\xa7\x24\x8c\x6e\xd4\x07\x71\x38\x56\x1a\x55\x83\x0a\x50\x9f\x97\x4c\xfb\xd2\x23\x55\x54\xe7\xf5" + - "\x99\xdb\x7c\x12\x3b\x25\xf6\x96\x8a\x13\xeb\xf5\xe5\xd3\x55\x87\xf8\xd7\x60\x08\xf0\xa4\xb7\xa4\x5b\x65\x2d\xd1" + - "\x91\xf2\x1c\x84\x93\x6f\xf0\x08\xfc\xfc\xd3\x6b\x27\x49\xd5\x15\x80\xbe\x63\x58\xd9\x8e\xca\xc0\x35\xaa\xaf\x84" + - "\xac\xf2\xc6\xe3\x88\xbd\x43\x13\xbd\x9f\xbf\xb6\x46\xbe\x37\x40\xb0\xc3\x45\x34\xfe\x62\xfc\x18\x13\xba\x15\x35" + - "\x1c\xec\x0e\xd5\xe8\xc5\xc2\x8c\x0a\xf4\x46\x69\x0b\xb7\x4d\x19\x5a\x2e\x3e\x4c\xf1\x04\xfd\x9e\x82\xfc\xea\x98" + - "\xe9\xbd\xa8\x46\x4a\x5b\xbb\x5e\x1a\xf6\xce\xa3\xd8\xe6\xfe\xdd\x37\xde\x44\x5d\x35\xba\x83\x0f\x94\xe6\xc8\xce" + - "\x87\x0f\xfd\xa5\x55\xd8\x1f\x4b\x5d\x54\x6f\xe1\x8c\x62\xd9\x7e\x4a\xdc\x22\xd2\xca\x52\x5e\xb8\x31\x3d\xd6\x9d" + - "\x9c\x71\x74\xac\x30\x19\x2e\x84\x7a\x89\xd4\xb2\x82\x47\xea\x1e\xd4\xd7\xf3\xf8\x5c\x13\x81\x74\x9d\xc8\xea\x32" + - "\xcf\xc0\x9c\x35\x80\x74\xf7\xfa\x8a\x56\xd2\x11\xd4\x92\x62\xa7\x26\x13\x95\x17\x90\xd8\x7e\x14\x8c\xdd\x5c\x0b" + - "\x9c\x37\xab\x1a\x33\x5b\x37\xb6\x38\x37\xe5\x95\xa0\x4b\x44\x76\x20\x72\xe8\x16\xba\x34\x52\xfa\x88\xcb\xde\x4a" + - "\x84\xc2\x32\xff\x14\x70\x1e\x1b\x63\xd7\x65\x8b\xae\x63\x22\xa5\x48\xe0\x29\xec\xf8\x63\x5d\x54\x03\xf0\x11\x94" + - "\x31\x10\x8f\xf7\x46\x88\xec\xee\x39\x8a\x5e\x29\x99\x6b\x35\x1b\xf9\xcd\xd8\xbb\x1b\x96\xc5\x7f\x84\xfb\x66\x28" + - "\x92\x55\xc5\xaf\x6e\x67\x62\x7b\xe5\x3f\x8c\x3e\x82\x99\x59\x35\xf5\xea\xbb\xba\x46\xd7\x81\x8c\x77\x13\xa0\x15" + - "\x51\x42\x04\x47\x46\xf3\xbc\xbb\xdb\xbc\x10\x49\x42\x0a\x8f\xa1\xa9\x57\x9e\x0b\x0e\xf5\x11\x9d\x11\x4c\x21\x7c" + - "\x76\xd8\x93\xbe\xd2\xbf\xe4\xc4\x57\xb4\x35\xdd\x7f\x89\xa3\xeb\x97\xa6\x58\x67\xc6\xd9\xa0\x85\x89\xe0\x67\x6b" + - "\xd4\xb8\xb0\x03\x95\x4d\x65\x2a\x55\x76\xb5\x45\xf3\xab\x69\x8f\xf8\xe5\x31\xa0\xed\xd9\x8e\xc8\x08\xd7\x5c\x38" + - "\xb0\x9e\x9d\xef\x56\xcd\x31\x12\x92\xc5\x23\x5e\x27\x4a\x47\x0d\x45\xd5\xfd\x84\x8d\xe4\x92\xa8\x85\x0a\xf1\x16" + - "\x24\x29\x60\x1a\xc6\xeb\x6b\x75\xbf\x81\x1f\xae\x72\xc8\x22\x10\x7d\x36\x94\x13\x17\x6d\x04\xc7\x9e\x45\x79\x13" + - "\xd3\x6c\xcf\x71\x96\x73\x9e\x48\x91\xe1\xf9\x20\xce\xf0\x8c\xc1\xb0\x52\xd2\x49\x73\x86\x1f\xc6\x2a\xed\x0d\xc9" + - "\xc2\x63\xfc\x2f\xc2\xbc\x42\xe0\x23\xcc\xef\x1f\x42\x54\xe1\x06\x13\x87\xd1\xf1\xe6\x23\x95\x7d\x68\x3e\x54\x6e" + - "\xfe\x7d\x50\xf2\x4d\xc8\x7e\xff\x5f\xaa\xea\x66\x08\xda\xe9\x4d\x82\x58\x74\xb7\x5c\x2e\x1a\xc9\x02\xe0\xa0\xbc" + - "\xcb\x12\xa7\x0f\x33\x17\xea\xd7\x37\xdf\x7f\xd7\xb6\x2b\x72\x51\x1c\xc8\x14\x5f\xe4\x92\x74\xc3\xa4\x05\x52\x96" + - "\x2d\x9a\xd7\x39\x47\xa7\x5f\x2e\x9a\x00\x82\xc0\x81\xed\x97\x8b\x86\xf4\x9b\xef\xd8\xde\xc6\x54\xdc\x09\x1e\x21" + - "\x66\x8d\xdc\x0c\xae\xd0\xf1\x80\x8c\x73\x40\x90\xf7\xfc\x45\xf7\x78\x6f\xcf\x7d\xbb\x37\x75\x7f\x31\xc0\x6a\x92" + - "\xe4\x0c\x9c\xd8\xf7\xbf\x7c\xb2\x37\x05\x09\xb0\x2d\x96\xc6\xaa\xd7\x2f\x3d\x06\xf8\xfe\xe3\xc7\x5f\xa0\x4f\x52" + - "\xc1\xe0\x36\xea\xc4\x55\x0d\x91\x5c\xee\xed\x94\x7e\x84\xfe\x43\x03\x12\x73\x20\x9d\xdc\x81\xd7\x29\xc7\xbd\x41" + - "\x29\xb6\x0a\x51\x02\x90\x27\xe8\xc4\xa8\xa5\xae\xd6\xba\x64\x97\x4d\xf0\x2f\xe2\x4c\x98\x83\x07\x4f\x1e\x7f\xbd" + - "\x37\xdc\xbe\x07\xd7\x35\xa5\xf2\x79\x06\xb6\x98\x5f\xf1\x22\x8e\xf4\xc0\x5c\x44\x0d\x41\xc9\x9b\x61\x2d\x59\xf7" + - "\xb6\xc5\x0b\x8c\x40\xec\xdd\x0d\x16\xad\x17\xef\x73\xf9\x90\x10\xe2\x07\xe2\xb6\xf2\x08\xfd\x3e\x49\x6a\x0d\x31" + - "\xf7\xf7\xef\x47\x13\x05\xde\xa6\xd9\x45\xd1\x2e\x9e\x37\x26\x47\x90\x56\x9b\x51\xa3\xa1\x98\xab\x8d\x2b\x02\x30" + - "\xf8\x03\x95\xcc\x77\x5c\xef\xd3\x64\x7f\x7b\xff\x45\x41\x49\x22\xec\x17\x8c\x2e\x0e\xb6\x0a\x06\x17\xaa\xad\x55" + - "\x14\xe8\x06\x50\xa6\x8c\x17\x08\xfe\x3e\xdc\x3a\xe7\x11\x8f\xcf\x04\xf3\x51\xd1\x04\x5c\x5f\xab\x74\xfc\xf7\xbd" + - "\xd3\xb6\x08\x5a\x8b\x2f\x44\x0a\xa9\x32\x71\x86\xca\x05\xfb\x05\xfa\x88\xd3\x48\x4d\x5a\xb0\x15\x13\xcf\x34\xb7" + - "\x02\x9b\xd0\x67\x58\x76\x53\xb7\xb3\x03\xa7\xd3\xeb\x52\x2f\x17\xcd\xb8\x5e\x99\x30\x45\x63\x34\x08\xf0\x2f\x89" + - "\x9c\x83\x4e\x95\xe2\x1d\xc1\xbd\x85\x27\x8c\xf6\x16\xa7\x72\x21\x60\x47\xf4\x54\x26\x1f\xa2\x04\xfb\x96\xb3\x65" + - "\x87\x7e\x23\xac\x59\x07\xc3\x14\xfc\x73\x6f\x2b\xe6\x46\x84\x4e\xb8\x07\xdd\x72\x51\x8e\xe8\x1e\xcf\x15\x0e\xb4" + - "\x57\xcb\x62\x49\xbe\x47\x09\xa4\x45\xd4\x4d\x1f\x27\xff\xf0\xa1\x82\x89\x4c\x62\xef\x45\xb7\xfa\x5e\xf7\x54\x34" + - "\x4c\xb5\xd2\x93\x89\xfa\x75\xf7\x27\xce\xdd\xb3\xfb\x4b\xd1\x2e\xa2\x70\x7f\x42\x03\xeb\x8b\xd2\x84\xfc\x9b\x10" + - "\x6b\x80\xe1\x56\xc8\x6c\x52\xe6\x3b\xe0\x43\x4b\x50\x68\xe9\xc6\xf8\xba\xf4\x59\x01\x81\xad\x5a\x7d\x2c\x4e\xad" + - "\xbe\x50\xab\xf5\xef\xbf\x97\x06\x7c\x89\x2d\xfa\x83\x56\xe6\xdc\x34\x14\x1d\x43\xa0\x3b\x76\xdd\xb0\xb7\xd4\x64" + - "\xa2\x06\x45\x8b\x50\x63\x48\xbb\x4f\x0c\x8a\xb7\x8e\x39\x5e\x99\x66\x97\x83\xc0\x4e\xb4\x2d\x40\xfc\x35\xe7\xa6" + - "\x52\x6b\x2b\x70\xa8\xd6\xab\x61\x34\x3a\xab\x97\xa6\x3b\xb8\x0b\x48\xc5\x4e\x09\x7c\x29\x34\xa1\x98\x7b\x3f\x73" + - "\xde\x5e\xd2\x8d\xab\xf7\xf8\xb9\x63\xc9\x9e\xf6\x59\x3a\xd9\x99\x04\xfb\xbc\xad\xd4\x81\xca\x62\x92\x90\xf5\x2c" + - "\xa5\x13\x32\xa5\x1b\xa3\xdc\xd4\xa9\x0b\x2b\xee\x99\xde\xc8\x80\x9e\xb8\x80\xb8\x9d\xe7\xc2\xc6\x19\x19\x62\x37" + - "\x62\x41\xa4\x69\xbc\x52\x9c\x85\xd4\x20\xbe\xb5\x15\x62\xba\xe2\xdb\xa1\xc8\x25\xc2\x81\x68\x1b\x8e\x00\xde\x66" + - "\xfc\x83\xfd\x86\x08\x1e\xc4\x7f\xe5\x31\xb6\x50\x53\x84\xce\xfc\x31\x86\x83\xab\x40\x86\x0b\x6c\x6d\x25\xae\x5f" + - "\xe1\x73\xce\x19\x2a\x3f\x67\x32\x3a\x08\x8f\x98\xfb\x98\xde\xc1\x7e\xec\x3d\x85\x44\x0d\x0f\xbe\xfe\x6a\xef\xc9" + - "\xc8\x71\x15\x8f\xf7\xfe\x22\x6a\x81\x55\x43\x9f\xe5\xde\xa7\xc1\xe3\x6a\xcb\x47\xed\xca\xce\xdf\xd1\xc9\x94\x75" + - "\x3a\x52\xa1\x6a\x8c\x20\xfe\x94\x0e\x8c\xe2\x61\xa7\xdc\x52\x78\xf3\x8c\xf3\x09\xaa\x93\xa2\xd2\xcd\xd5\x2e\x18" + - "\xf0\x25\x8c\x24\xa6\x22\xb4\x51\x2e\xc2\xb8\x8e\xc1\x83\xfd\xfd\x2f\x1f\x7f\x35\x14\x4f\x49\xff\xe8\x3a\x15\xd5" + - "\x15\xa5\x5c\x3a\x94\x73\xc1\x10\x96\xe9\x27\xa2\xc4\x8d\x9a\x0a\x87\x8c\x64\xec\xbd\xc0\x36\x83\x61\xff\x4a\xf0" + - "\x5f\x1e\x2c\x83\xcf\x98\xbc\xd6\xbe\x07\xa0\x03\x00\x9e\x3f\xf7\xe2\xe6\x56\xb4\xcb\x79\xf7\xfb\x3d\x1a\x6f\x7b" + - "\xff\x9a\xb6\x68\x74\x6b\x0a\x28\x32\x04\x75\x9a\x6d\x3a\xd4\xdd\xf3\x17\xd5\x8d\xa7\x27\xd4\x2d\xe1\x87\x21\xdd" + - "\xad\x72\xcc\x46\x94\x72\x01\x8c\x53\x90\x67\xb2\xd1\x10\xb6\x28\xd6\x76\x18\x51\xa7\x2a\x0f\xb7\x58\x1c\xb9\x26" + - "\x93\x3e\x01\x3c\x0e\xc4\xf8\xf3\x44\xf6\x02\x1a\x23\x93\xfe\xd5\xd7\x5f\x4c\xd5\xdb\x4a\x84\x1e\x14\x73\x14\xf4" + - "\x16\xda\x22\xe4\x24\xb8\x29\xb6\xe8\xb5\xaa\x71\xeb\xc1\x94\x5e\x19\xde\x0f\x1b\x89\x56\x1c\xa8\x90\xb8\x0c\x32" + - "\xf2\x49\x8a\x6e\xe2\xbf\xdf\x54\x6d\x67\xa1\xa5\xb3\x53\x2a\x8b\x91\x50\xc0\x21\x49\xe8\x00\x21\x82\xe6\x3a\xe0" + - "\x72\x7f\x00\xbc\xb1\x04\xb9\xb5\xe4\xb6\x94\x25\x58\xb3\x10\x28\x1c\xe0\x68\x37\x3c\x37\xb3\x65\xef\xf3\xcb\xdd" + - "\xf0\x26\x63\x59\x27\x41\xac\xe5\x96\x27\x83\xc3\xa9\xab\xff\xda\x7d\x32\xc4\xa7\x13\xf1\x8d\x84\x71\x65\x6c\x53" + - "\xaa\x39\x82\x24\x92\xae\xa0\xec\x5e\x45\xbe\x6d\xba\xe4\xf7\x91\x5a\xa6\x65\xf7\xd2\x9b\x68\x5e\x83\x43\x1b\xf8" + - "\x2b\x7f\x6e\x7d\xaa\x30\x08\x0e\xd7\x55\xae\xc4\xad\x1f\xcd\xb2\x0f\xbd\x1a\x04\x77\x14\x09\x6d\x43\x1d\xec\x04" + - "\x20\x77\xd4\xbc\xfe\x65\x48\xc4\x76\x23\x3e\xec\xf2\xfc\x3e\x8a\x1e\x5c\x63\x9e\xa6\x03\xfa\xb6\xa8\x72\xde\x1f" + - "\xad\x3e\x55\x0b\xb7\xeb\x44\x20\x59\xaf\xd4\x73\xeb\x18\xc0\x6f\x04\x12\x0c\x73\xec\x05\x88\x3a\xb9\xd1\x25\x45" + - "\xab\xcf\xa4\x1c\x24\x90\x06\x36\x0f\x02\x7c\x04\x68\x3b\x45\x2e\x60\xb7\x4a\x34\xbf\xf5\xc9\x32\x34\x56\xaf\xe0" + - "\xc9\xfe\x8a\x4f\xfe\x96\x0d\x51\x67\xc7\x07\x2e\x45\xbd\x76\x67\x10\x71\xac\xa7\xca\x8e\xf1\xa3\xe7\xf8\x80\xdf" + - "\xdb\x66\x36\xc5\x70\x78\x3a\xa2\x20\x1b\xd3\xcb\x0c\x28\xb6\x89\x3c\x42\x7b\xf9\x26\x73\x1e\x21\x13\x61\x4b\x63" + - "\x8c\x8c\x17\xac\x88\xf8\x56\x60\x9f\x11\x01\x49\xea\x08\xf7\xbc\x7b\x33\xee\x30\x2e\x87\xea\xcb\xbd\x2f\x15\xaa" + - "\x37\x42\x89\x8d\x90\x4e\xfc\xc2\xa7\xc5\x75\xec\x22\x79\x4d\x80\xe7\xcb\x80\x56\x2b\xf6\xc7\x19\xfd\x2f\x51\x3e" + - "\xb7\x5b\xea\x32\x97\x4a\x21\x34\x49\x35\x90\x9b\x1b\x52\xa6\x1f\x0c\x3f\x1c\x0e\x0e\x0f\x1e\x5e\x7f\x36\xbc\xfe" + - "\x70\xf8\xe1\x70\xc2\x07\x82\x61\x0e\xb1\xa8\xf5\x90\xb5\xbd\x24\x13\x0a\x4d\x55\xc6\x5d\x84\x85\x85\x87\xdc\x78" + - "\x77\xa0\x52\x35\xe0\x24\x48\xd1\xd1\xf1\xaa\x5e\x0d\xc8\x2c\x12\xcc\xf7\xba\xca\x6b\x08\xc5\x47\xc3\x6a\x40\x00" + - "\xc0\xf9\x40\xbf\x27\x5f\x63\x94\x26\x93\x8e\x87\x3c\x32\xd1\xe9\x7f\x01\x78\xa8\x23\xe1\x91\xcf\x6a\x0c\x47\xcc" + - "\x8a\x4e\x44\x2b\x98\xaa\x60\x62\xc2\xb1\xdd\x40\xe5\x00\xbd\x1a\xca\xc6\x54\x22\xa4\xcc\x0c\x50\xbf\xdd\xdc\xa3" + - "\xdc\xe4\x0f\x28\xfc\x9f\x9b\xe6\xa2\x29\xda\xd6\x54\x21\xd8\xc7\x31\x02\xba\xa8\x08\xea\xd5\xb5\xf4\x63\x53\xaf" + - "\x00\x43\x03\xbb\x18\x42\xd9\x41\x2d\x84\x8b\xef\xf1\x3e\xd0\xbd\x10\xb5\xb1\xd9\xba\x29\x33\xd2\x8e\xc6\x60\x34" + - "\x9d\x04\x9d\x83\x24\xa0\x1d\xc2\xc0\xd4\x70\x0c\x86\xf1\xb7\xf3\xc1\xdd\x70\xf8\x19\x28\xba\x93\xde\x90\xd7\xeb" + - "\xc3\x87\x2a\x73\x7f\x02\x3c\x7a\xc8\x40\x44\xb7\x4e\x31\x9f\x77\x53\xb4\x91\x0e\xc1\xe2\x8c\xaf\x32\x27\xef\x0a" + - "\xac\x24\x8f\x79\x05\xc9\xdf\xbc\x16\xc9\x4f\x17\x84\xc8\xf4\x25\xe6\xa3\xda\xbc\x3f\x20\x45\x8f\xf9\x7d\x86\x6a" + - "\x99\xc6\x2c\xcd\xf2\xc4\x10\x36\x98\x81\x98\x41\xf7\x37\x1a\xd3\xb4\xb5\xf5\xac\xd0\xae\xab\x40\xf8\x31\x9a\x45" + - "\xae\x6d\x58\xae\xe7\xe1\x48\xf4\xd8\x73\xd3\x42\xbc\x72\xc9\xf3\x01\xeb\xb8\x93\xe7\x51\x94\xb6\x11\x9c\x2e\x5a" + - "\xc0\xdd\x5e\xa8\x1b\x34\xed\x70\x54\x5c\x3c\x4d\x1e\x87\xe8\x28\x3c\x83\x14\x53\xf2\xb7\xd0\x9c\x43\xeb\x00\xdb" + - "\x01\xb9\x2e\xe4\x88\xa3\x88\x67\xba\xf2\xd2\x0d\x1b\x60\x8f\xfa\xa1\x55\xfc\xf6\xed\xe0\xaa\x60\x4d\x6c\x9c\x96" + - "\x0d\xa7\x98\x3b\x14\x01\x28\xd2\xa1\xb4\x35\xc0\xa9\x14\xe6\xdc\x20\xf8\xbc\x9e\xbb\xc7\x74\x63\xfa\xd4\xfe\xc4" + - "\x86\x84\xd4\x2f\xc4\x0d\x20\x2c\xfd\x71\x57\xe1\x9f\xc2\xa9\xfa\x93\x9b\x7a\x85\x61\x10\xd2\x20\x9e\xaf\x1d\x95" + - "\x81\xfd\xb9\xaa\x71\xd9\xc0\xac\x24\xc3\xb3\x93\x8c\x70\xbe\xf6\x90\x64\x46\x80\xef\xcd\x01\x05\x1b\x46\x27\x31" + - "\x24\xba\x67\x80\xbc\xf9\x37\xc7\xf7\xbb\xc7\x82\x30\xa9\x03\x52\x88\x1f\xc5\xdd\xc7\x1e\xf4\xbf\xea\x9b\xaa\xee" + - "\x24\x1d\x04\xaf\xfa\x74\x34\xcf\x4b\xa3\xab\xdd\xf5\x2a\xa4\x8c\x1e\xcc\x8b\xc6\x58\x5a\xb9\xb0\x46\x20\x52\x45" + - "\x20\x8e\x7d\xc6\xd0\x9f\x8c\x6d\xeb\xc6\x74\x4f\x32\x14\xd8\x38\x06\x31\x0b\x32\x1a\xc9\x51\x20\x38\x63\xda\xaa" + - "\x79\x63\x64\x18\x73\xa7\x12\xe9\xed\xb4\xd4\x67\xa8\xf0\x43\x9b\x64\x63\x76\x51\x75\x07\x19\xfa\xe8\x7a\xca\x6b" + - "\x03\x82\x9a\x9d\x35\xe6\x42\x41\x80\xb7\x95\xee\xc8\x29\x01\x70\xbd\x4c\xae\x9d\x5e\x0a\x81\xa1\x0c\x0c\xfd\x14" + - "\x11\x3b\xb8\xfc\xe6\x6b\x48\x74\xbd\xe6\x18\xf5\xf8\xf6\x86\xac\xdf\x3d\x87\x3d\x0a\xe4\x71\x7b\x08\x23\xac\x01" + - "\x30\x2c\x2c\x1d\xa4\x43\xe8\x24\xe6\x0c\xb3\xd6\xdd\x19\xc1\xa3\x43\xd2\x4a\xb9\x29\x85\x1f\x99\x78\xdc\x53\x57" + - "\xaf\xe7\x74\xdf\x5e\x8c\xb7\x7c\x12\x65\x11\xc1\x72\x95\x06\x80\x03\xdc\xc5\x03\xf4\x41\x30\x24\x2c\x3f\x6c\x90" + - "\x5b\x31\xb2\x82\x20\x27\xeb\x39\x78\xaf\xc2\x0b\x06\x0f\x1f\xe0\x3e\xd0\xe5\x70\x0a\x51\xbd\x4e\x0c\x83\x18\x7b" + - "\x74\x08\x69\xf4\x29\x86\x9c\x50\x40\x38\xe6\x96\xc8\x11\x5b\xb2\xf0\x48\xe9\x23\x95\x23\xb3\x67\x31\x9d\x1c\x32" + - "\xb3\xe4\x23\x65\x56\x18\xb8\x63\xd3\xc6\x30\x17\x31\x54\x5d\x54\xb3\x72\x9d\x1b\x1a\x9f\x70\x91\x41\xb8\xe1\x76" + - "\x59\xf6\x38\x55\x59\xf3\xdd\xfb\x37\xdf\x47\x1c\x3f\x85\xd6\x70\xaf\x64\xe3\x42\x2e\xbc\xcf\x7a\x0e\x91\x50\xbc" + - "\x17\x2d\x8f\xed\xaa\x24\x15\x78\xf9\x90\xbe\xe3\x49\x84\x6b\xfe\xa4\xae\x1d\x0d\xf1\xdf\xca\xb6\x0f\xb8\x28\x2c" + - "\xae\xff\x2c\x96\x3c\xc3\x63\x81\x2f\xcf\x73\xf9\xd4\x33\x74\x30\xf0\x5c\x1d\xa8\x06\x13\xb2\xbc\xd7\xa7\x84\xbc" + - "\x88\xac\xcf\x28\x48\xfe\x60\xd7\x93\xfd\x78\xf8\x50\x1d\x1d\x07\x37\x2a\x4c\xe8\xd2\xea\x53\x1e\x17\xd5\x1d\x8f" + - "\xfe\x88\xfb\x33\xc6\xd5\x27\xc7\x7c\x2e\x7d\xb4\xef\x88\xce\x71\xf0\x78\xf2\x1d\xa4\x95\x02\xef\x9a\x57\xb4\x93" + - "\x06\x0a\x53\xaf\xab\x63\xb1\x4c\xdc\xdb\xa1\xf0\x21\xb5\xa1\xcb\xf4\x67\xe2\x8f\xce\xc6\x53\xff\x71\x24\xd8\x45" + - "\x49\xae\xd8\x43\xc0\x34\xa7\x66\x00\xb9\xec\xb1\x8f\xa9\x87\x34\xfb\xf0\x42\xc2\x1c\xb3\x12\xf9\x3e\x81\x62\x96" + - "\xb9\x02\xc9\x93\x53\x57\xb8\xd5\xf8\x8d\xb4\x87\xc1\x4d\xc7\x3d\x40\xa9\xe0\xd1\x23\xc8\x7a\xfa\xbd\x2b\xa1\x09" + - "\x92\x15\xec\x35\x2b\xc0\x7b\x87\xac\xa6\xf1\x77\xdd\x58\x31\xf4\x65\xea\x04\xb9\xa5\x89\x2d\xee\x27\xdc\x35\x76" + - "\x2b\x5e\x47\x78\xe6\x64\xcb\xf2\x8a\xdd\x69\x42\x90\x99\x98\x34\x0a\x23\x30\xb3\xb6\x6e\x38\x1d\xb6\xc7\x05\x80" + - "\xcd\x85\x31\x06\x50\x05\xdc\xdd\xf3\x39\x26\xcf\x08\xbc\xbb\xca\xe4\x5a\xba\x02\x7f\x13\xb0\x86\x5c\x7b\x8a\x84" + - "\xea\xaa\xc0\x44\xa8\xf0\x09\xcb\x65\x94\x8d\x23\xbc\xdc\x1b\xe1\xfb\xd4\xcb\x0e\xf0\xed\xc2\x3d\xd0\x71\x98\x0b" + - "\x94\x9d\x5c\xc4\x86\x11\x57\xfe\x8b\x49\xfc\xf1\x3e\xb7\xd1\xe5\x25\x59\x6e\x75\x40\x75\x40\x0f\xa9\xba\x4e\x38" + - "\x6c\x9c\x19\x10\x0e\x02\x8b\x12\x01\xd5\x33\x4a\x69\x89\x15\x05\x28\x4f\xae\xb9\xc7\x09\x97\xb5\x51\x3f\xbe\x7d" + - "\xe7\xd5\x51\x32\x81\x31\x5c\x7f\x32\xe8\x08\xf3\xd2\x8e\x90\x2d\x88\x51\xa2\xf1\xc8\x99\x72\xce\x87\x4c\x00\xf0" + - "\xdc\x1a\xe3\xc7\x97\x71\x31\x57\x99\xeb\x50\xe6\xb3\x75\x38\x49\x4a\x84\x5c\x42\xbc\x3a\x68\xce\x38\x32\x52\x82" + - "\x8c\x78\x81\x31\x0d\x0b\xa4\xc0\x33\x91\xf0\x0b\xaf\x34\x9c\x17\xbc\x2a\x01\x9f\x59\x38\x10\x44\x56\x8a\x28\x0c" + - "\x0b\x38\xa9\x28\x51\xf7\xda\x52\x8a\x71\xd2\x6e\x45\x8a\x7b\x09\x94\x21\x18\x47\x52\x91\x95\xf3\xb1\xeb\xd6\xc0" + - "\x1f\x96\x00\x5c\x48\x4e\x9f\xe1\x8d\x63\x50\xc4\xdd\x5a\xd6\x33\xb6\x17\x60\x92\x7c\xbf\x4c\xe0\x97\x98\xaf\x97" + - "\xcb\x2b\x95\x17\xe7\xbe\xb6\x97\x97\xf1\xfd\xe8\xc8\xc8\x79\x5d\xe4\xea\xf5\x4b\xf5\xf9\x8f\xa6\x59\x16\x90\xd9" + - "\x4a\xbd\x30\x55\x61\xf2\xcf\x29\x93\xa2\x94\x08\x06\xd9\x5f\xf3\xe2\xfc\x6f\x59\x08\x94\x4a\x2f\xd2\xce\xc4\x0d" + - "\xc7\xf3\xc2\x15\xf4\xa3\x10\x50\x89\x11\x52\x22\x63\x43\x43\xa6\x27\xf4\x7d\xc4\x52\x71\x85\x34\x75\x37\x01\x8a" + - "\x5b\x68\xa9\x1e\x3e\x14\xa4\x2f\x0a\xb4\x0e\x32\x9c\x9b\x72\xf4\x45\x0d\xc1\xb3\x7e\x8d\x00\x11\x99\x81\x62\x42" + - "\xb3\x23\x0f\x4a\x14\x07\xdb\xdf\x74\xaf\x09\xf2\x0c\x94\x91\x1c\x7d\xa1\x1f\xba\x2a\x96\x1a\x9d\x5b\x6e\x0b\x1b" + - "\x61\x05\x79\x63\x56\x03\xa6\x72\xc5\x12\xfc\x42\x6e\x89\xf5\xc4\x30\x38\x27\xbe\x56\x63\x0e\x6f\xbb\x19\xd2\xa9" + - "\xec\x09\x33\xc9\xeb\xd9\x4b\x8c\x9c\x23\x3f\x23\xaf\x49\xe4\x3f\xe8\xba\x8e\xae\xa4\xbf\x9b\xd6\x11\x4a\xf2\x3b" + - "\x02\x88\x09\xed\x7d\x28\xd3\x7c\xdb\xa7\xa6\xfd\x05\x0a\xde\x32\xca\xc2\x26\x45\x0e\xf1\x0f\xf6\x8c\xe3\x6c\x34" + - "\x6e\x64\xdf\xf8\x58\x1d\x62\x1a\xff\xbd\x30\x17\x49\x8e\x49\x8c\xe2\x21\x57\x33\x6b\xda\xb7\xf0\x7b\x9a\x4c\xb8" + - "\x40\x58\x2b\xa4\x82\x7b\xb6\x6e\x7e\xac\x6d\x81\xee\xef\xb3\x75\xf3\xbd\x99\xb7\xf0\xc7\xf3\x77\xef\xde\xd7\x2b" + - "\xf8\x93\xff\xc5\x9a\xf9\x2d\x95\xd4\xe5\x0c\xb2\x4a\xf9\x5a\x60\xff\xad\xe8\x57\xb8\xb6\x66\xd6\x72\x4f\x32\x7e" + - "\x9b\x71\xbc\xdd\x6c\xdd\xd0\xd2\x30\xab\x82\x73\x43\x95\x35\xf5\xca\xe7\x3a\xd9\x0e\x18\x8e\xbe\x11\x08\x82\x1c" + - "\xa9\xa2\xda\x45\x3c\xdf\x7a\x35\x29\x0d\x04\x86\xa3\x93\x06\xb8\x62\xd4\x98\xd4\xa3\x98\x41\xdd\x5e\xdb\x12\x7a" + - "\x8a\x7c\x81\x2b\x11\x8c\xea\x30\xf7\xb6\xbd\x2a\xcd\x58\x0c\x29\x6b\x4c\x09\x30\x19\x99\xd4\x6f\xf8\x19\xc2\x14" + - "\xd4\x2f\x43\x88\x15\x29\x91\xfd\xac\xf6\xcf\x4a\x5b\xaf\x58\xc9\x10\x66\xb8\xbf\xa8\x1b\x9d\x2f\x9b\xae\x00\xc0" + - "\x78\xc4\xc3\xd2\x27\xb6\x2e\xd7\xad\xc9\x00\x12\x3c\x7a\x35\x2f\x2e\x23\x9f\xd9\x41\x58\x7c\x4c\x98\xca\x1d\x91" + - "\xea\xc6\x75\x5b\x67\x43\xf5\x37\xb5\xbb\x1f\x56\xe4\x07\x4a\xe9\x7e\x62\x14\xdc\x69\x6d\x1d\x36\x47\x68\xb3\x98" + - "\x2b\x53\x38\x6a\xe8\x56\x49\xd5\x8d\x82\x85\x2a\xac\xf2\xf9\xac\x43\x51\xcb\x45\xb9\xfb\xa0\x2f\x73\xfd\xf5\xab" + - "\xd7\x1d\x3c\xaf\x9c\xd8\xd8\x62\x3d\xb8\x72\x56\xeb\xe3\xee\xc6\x02\x5c\x7c\xdc\xd6\x2b\xff\x96\xd6\x40\xbe\x76" + - "\x3d\x66\xfa\x2c\x7d\x1b\x7c\x5d\x70\x4d\xbc\x2a\x6b\xdd\xca\xc9\x04\x15\xfb\x5e\x5a\x71\xb7\x2c\x4e\x76\x28\x7c" + - "\x73\x7b\xfc\x76\x70\x01\xe4\x91\x77\x52\xaa\x11\xfa\x25\xee\x9d\x42\x1c\x65\xd5\x0d\xca\xf6\xee\x72\xf5\x4a\xdd" + - "\x4f\x11\xec\xdd\x39\x84\x37\x07\x49\xc9\xdd\x50\x27\xfc\x1e\xe2\xd6\x79\x4f\x13\x79\xd3\xa9\x1e\x56\xbd\xbf\xfe" + - "\x12\x27\x26\x29\x2b\x5b\x28\x71\x86\x76\x98\x5e\x75\x06\x91\x81\xee\x26\x13\x3e\x75\xe9\xe4\x8c\xa1\x44\x34\x31" + - "\x48\x65\x86\x1b\x56\x16\x76\x0f\x1c\xc1\x50\x2e\x98\x6a\x37\x87\x1f\xd4\x1d\x6a\x9c\xf4\x08\x3a\xec\x59\xa6\x34" + - "\x90\x98\xae\x0e\xbf\xa4\x91\x75\x96\xbc\xba\x41\xbb\x30\x0d\x7f\xdf\x12\x5a\xbd\x15\xdd\x19\x63\x7f\x5b\xb0\x90" + - "\x23\xef\x08\xb6\x7b\x45\x7b\x44\xdc\xa3\x23\x77\x27\x8e\x3c\x95\x24\x29\x07\x54\x3a\xf8\xf4\xa4\xbe\x74\x44\xdb" + - "\x1d\xf4\xa9\x93\x43\xdc\xb2\x4d\xd5\x9e\x22\x93\x5c\x5e\xcf\x28\x88\x3d\x04\xa4\xca\x80\x7d\x89\x5b\x70\xdf\x15" + - "\x8e\xe7\x44\xf6\x2a\xdc\xec\x79\x3d\xeb\xbd\xcd\x11\xd8\xdc\xeb\xf8\x3c\xba\xb7\x56\x79\x61\x67\x75\x55\xa1\x6d" + - "\x83\x13\xcc\x85\x86\x99\xf8\xa2\x32\xca\x0e\xc2\xe8\xe9\xf6\x4e\x56\xea\xa4\xbe\x4c\x74\xde\x28\x61\xe4\xe0\xd5" + - "\x07\x72\xc6\xe9\xb7\xcf\x7f\x1a\xa9\x8f\x6b\x0b\xe0\xe2\x6a\x6f\xb4\xa7\x1a\x8d\x24\x71\xc1\x2e\x1f\xf4\xed\xb7" + - "\xa5\x9e\x9d\x7d\x6b\x9a\xe6\x4a\x3d\x19\xa9\xe2\xed\x3b\xf5\x85\x1a\xb0\x4e\x51\x15\x3f\x2e\xea\x0a\xb3\x8f\x48" + - "\x21\x17\xa6\xf2\xd4\xb4\xdf\xd6\x6b\x80\x2f\x7e\x5e\x16\xa6\x6a\x7f\x32\xb3\x16\x64\x5f\xdb\x36\x1d\x03\x3f\xad" + - "\xd5\xe6\x2f\x85\x5b\xf4\xd6\x05\x24\xa4\x10\xac\x0e\x2c\x4e\xd7\x32\x0e\xeb\x7e\x52\x5f\x02\x45\xd8\x71\xbb\x65" + - "\xec\xa4\xf9\xff\x20\xda\xb3\xcb\x53\x39\x9e\x41\x33\x8e\xcb\x80\xef\x70\x9f\xb8\x0f\xe1\xa0\x87\x2f\x7f\xdd\xf0" + - "\xa5\xa3\x01\xdb\xde\x2e\x8b\x92\x16\x13\xfa\xae\x29\x94\x82\x39\x63\xf0\x89\xde\x6d\x05\x26\x5d\x68\xf2\x47\x88" + - "\x46\x1f\xd1\xaf\xdb\x36\x3d\xc6\xad\x7b\x3e\xa0\x67\xf7\x87\xfd\xf8\xca\x5d\x65\x41\x9e\x71\xdc\x0a\x31\x73\xc0" + - "\x66\x12\xcb\x39\x48\xab\x74\x35\x86\x0a\x6f\x46\xea\xc4\xcc\x34\x08\x67\x98\xc1\xa4\xb5\xe8\xfc\x40\x75\xe1\xe7" + - "\xe9\x15\xb2\x81\x1d\x4b\x78\x02\xaf\xa4\x4f\xe4\xfd\xfe\xdd\x25\xa1\xfd\x31\xea\xc0\x09\x2f\x6b\x77\xb0\xe4\xa5" + - "\xee\x6f\xf0\x2d\xcf\xba\xde\xb1\xf1\x3a\x04\x99\xec\x82\x8f\x1a\xa3\xcb\x47\xd1\x1a\x89\x7a\xf1\x01\xc7\x24\xc9" + - "\x67\x83\x61\x02\x4f\xc9\xb0\xe6\x58\xc8\xc6\x9d\x13\x9f\x33\xdb\xb0\x01\x7e\x40\xb6\x81\x7b\x82\xc4\x71\xa9\x12" + - "\x4f\x96\x53\x7e\x93\xb4\x92\x24\x12\x88\x46\x75\x02\x59\x6a\x6c\x67\xcf\xe1\x61\x8b\x99\xc6\xbe\x6e\xe1\xf7\xef" + - "\xeb\x15\xe0\x02\x64\xa3\x80\x86\x92\x56\x88\x87\xf0\x53\x6b\x74\x67\xb1\xa7\x4a\x01\xbe\xbe\x3e\x41\xcc\x3e\x6c" + - "\x84\xa7\x1c\x81\xbd\xf1\x28\xa8\xa5\x6e\x4e\x8b\xca\xf6\x53\x94\x3a\x8c\x73\x57\x75\x86\xbe\xdb\xb7\xc1\xb1\xbe" + - "\xf7\x00\x51\x84\x9d\x92\x94\xa6\x16\xe3\x4c\x6a\xa4\x67\x1b\xab\x74\xa3\xf5\x75\xa6\x24\x48\x4e\xd2\xbf\x10\x27" + - "\x98\x52\x9f\xbe\x8d\x4c\x6a\xef\x97\x28\xfd\xc2\x67\x8c\x22\x13\x15\x03\x5f\x84\xdb\xf7\xab\xd8\xaa\xc1\xc2\xd3" + - "\x59\xec\x3e\x6a\x11\x64\xa6\x60\xf6\x89\xfb\xdd\xb3\xc7\xf1\x47\x6a\xf9\x41\x66\x67\xe3\x00\x85\x2a\x22\xb8\x93" + - "\x90\x43\xa9\x9d\x35\x75\x59\x02\xf3\xac\xd1\xbb\xac\x2e\x4b\xc7\x77\xa3\x0a\x2d\x05\xb1\xfa\x43\x7c\x30\x55\x99" + - "\xb8\x5e\xb2\x51\xf8\x98\xde\xd0\x95\x95\xa9\x1b\xa9\x90\x20\xa8\x2e\x60\x08\x45\x04\x0e\xf2\xc7\xf1\x77\x6e\x9e" + - "\x5c\x31\x5c\x24\x81\x69\xd5\x8b\x7c\x26\x42\xf1\x68\x4a\x34\xb8\x2b\x33\x97\x96\x4a\xf6\xdc\x11\x19\xc2\x07\xe8" + - "\x4f\xe9\x45\xed\x11\x38\x02\x11\x3b\xdf\x14\xda\xed\xdb\x76\xb5\x1c\xba\xff\x1e\xe1\x48\x8f\x49\x53\x11\x3a\x1f" + - "\xaf\x22\x47\x72\x09\xdc\xa4\xa2\x1a\xf3\x94\xb2\x63\xda\x7d\x37\x4d\x10\x28\xaf\xa6\xac\x8f\x11\x8b\xc0\xbe\x6a" + - "\x1b\x4a\xd1\xc4\x6e\x7b\xc7\x30\xec\x41\xe4\x69\x1e\xf7\x11\x53\x54\x4a\x88\x87\x68\xde\x46\x1d\x16\x7c\x24\x3c" + - "\x7b\x13\x24\x35\x4a\xaf\xe8\xd5\x0c\x33\x6b\xbf\xab\xeb\x33\x4b\xd1\x1e\x41\x0e\xe0\xa3\x02\x9f\xfd\x62\x4e\xce" + - "\x8a\x56\x9d\xac\x4f\xa7\x6a\xd1\xb6\x2b\x3b\x9d\x4c\x4e\xd6\xa7\x76\x7c\x01\x2f\xc6\x75\x73\x3a\xb1\x8b\xfa\xe2" + - "\xb7\x93\xf5\xe9\x78\x76\x5a\x1c\x16\xf9\xc1\xe3\x6f\xf6\xbe\xfe\x12\xbe\x3e\x35\xed\x73\xba\x4c\xdf\xb5\x57\xa5" + - "\xf1\x21\x7e\x2b\xd3\xcc\xc0\xec\xe8\xee\x5b\xaf\x37\x45\x48\x50\xea\xe0\xe4\xa4\x6e\xdb\x7a\x39\x01\xfd\x29\xd4" + - "\x26\xf9\x4d\xaf\xe2\x9e\x59\xab\x96\x75\xbe\x2e\x0d\xa5\xbe\xe0\xbc\x17\x74\x13\xe2\x3b\x88\x99\x01\xe6\x75\xe6" + - "\x93\x43\x14\xad\xc2\x0c\x53\x29\x4e\x1c\xa1\xc2\xa1\xba\x22\x45\x79\x13\xe7\x26\x90\x1b\x98\x48\xbf\xd3\x0e\x94" + - "\xce\xf3\xbf\x9b\xd6\x3d\x7d\x3d\x0f\x71\x68\xab\xe2\xd2\x94\x91\xc6\x29\x3d\x13\x9e\xf3\x88\xbc\x41\x3a\x4f\xb7" + - "\xfc\x93\x03\x12\xbf\xa5\x38\x28\x51\x25\x8b\x39\x15\x48\x67\x5e\x9f\x9a\x91\x9a\xb3\x6e\xb6\xad\x69\xba\xa2\x33" + - "\xd4\x54\xeb\x65\x55\x57\xab\x4b\x4e\x7e\x13\xfa\x11\x87\xe6\xf2\x19\x15\x8a\x0a\x3f\x19\x3b\x2a\x5b\x5d\x66\x3e" + - "\x9e\x96\xeb\x90\x7b\x7a\xfb\x1e\x9c\x06\x6f\xda\x0e\xe4\xb1\xa8\x2a\xd3\x20\xd4\xcf\x08\x7f\xc0\x2d\x3d\x52\x0b" + - "\x7a\x76\x81\x3f\xeb\x75\xcb\xe5\x10\x78\xc8\xfd\x46\xec\xa0\x4d\x84\x14\x4b\x4f\x55\x86\x55\x65\x23\x05\xe5\xa7" + - "\x2a\x83\x3a\x13\xaa\x49\xe0\x07\x1d\x84\x3f\xae\x6d\xa5\x73\xc7\x01\x4e\x55\x06\xbd\x64\xbc\x93\x11\x63\x6d\x91" + - "\xd5\x43\x65\xd9\x54\x65\xd0\x3b\x0f\x89\x12\xb5\x43\x0a\x53\x48\x33\x88\xcf\x29\xe0\x9b\x23\x72\xf1\x06\x77\x0c" + - "\x29\x70\xcb\x6e\x1f\x8b\xc1\x8f\xc4\xc8\xb7\x83\x65\xc7\xd1\x6c\x5f\x57\x4c\xb5\xb1\xbe\x14\x6c\x04\x74\xac\x0b" + - "\x5d\x54\x84\x32\xd4\x91\xf4\xe1\x6a\x96\x9d\x15\xc6\x76\xea\xe2\xfd\xd8\x66\x4e\xb4\x11\xb0\x8f\x9d\xc8\x9b\x7c" + - "\xcb\x3d\x01\xb2\x0e\x9c\xc9\xf5\xb5\x07\x21\xa1\x27\x87\xcc\xc0\x80\x1f\x17\x72\x6e\x21\x31\xe4\xa7\xdd\x3a\xb8" + - "\x0c\x49\xc2\x62\xd2\x0f\x78\xc7\x96\x58\x6b\x95\x28\xbe\xa3\x08\x89\x67\x90\x4c\xee\xc9\xe4\xeb\xc9\xe3\xbd\xfd" + - "\xc7\xe8\x32\x01\x66\x2f\x88\x52\x52\x45\xc5\x3c\x3a\x1a\x4d\xd0\x2d\xf4\x4d\x7d\xe2\xb8\x9d\x77\x7a\xae\x9b\x62" + - "\xa4\x4e\xd6\x6d\xc8\x75\x47\xc7\x16\x3c\x76\xb4\xba\x58\xd4\xa5\x51\x65\xdd\x3a\xf2\x35\xd3\x95\xca\xeb\xb1\x7a" + - "\x67\x8c\x5a\xa1\x21\x06\x03\x44\x74\x8b\x0d\xff\xfc\xd3\xf7\x50\x7f\x5e\xd8\xd9\x1a\xcc\x45\xd3\x50\x25\x13\xef" + - "\xd3\xa2\x5d\xac\x4f\xc6\xb3\x7a\x39\x41\x30\x11\xfe\xc7\x55\x39\xf9\xcb\x57\x5f\xd2\x27\x12\x8b\x6b\x93\xc9\xe1" + - "\x48\x65\x28\xcb\xfa\xcd\x7c\xdc\x13\xff\xe6\x44\x15\xfe\x10\x0f\xac\x82\xd4\x3c\x48\xd7\x83\x1f\x76\x8f\x1d\x21" + - "\xcc\x75\xd0\xbb\x6c\xd0\x94\x90\x19\x0d\x55\xaf\x78\x6f\x1f\xc1\x39\x98\xe0\xd1\x38\x06\x78\x11\x20\x72\xdd\xe7" + - "\x38\x8a\xf8\xf9\x28\xd4\x7a\xb1\x28\x66\x0b\x88\xb4\x2c\xac\x3a\x05\xd2\xc4\xa9\x77\x79\x9e\xde\xe8\x76\x31\x5e" + - "\xea\x4b\x1f\x1d\x06\x5d\x3d\xa9\xf3\xab\x23\x70\xe1\xa9\xcb\x32\x4c\xd2\xc8\xcd\x47\xdf\xf3\xbe\x8f\x6b\xe2\xc6" + - "\xd2\x8f\x3b\xcf\xf9\x63\x7c\x9d\x2e\x0c\xbd\xed\x04\x28\x06\x80\x86\x75\x1a\x47\x71\x18\x66\xc0\xad\x61\xb2\x74" + - "\x7c\xcf\x92\xf8\x33\xe2\xed\x08\xe1\x69\xeb\x16\x14\x55\xf3\xba\x99\x81\xbf\xab\xd7\x17\xc7\x1a\x3d\x21\x9b\xe0" + - "\xc1\x44\xf2\x90\x64\x6c\x7b\x77\x67\xe3\x71\xad\x60\xf9\xe8\x39\xf0\xbe\x7a\x76\xb2\xa7\x97\x81\xd2\x1d\x32\x15" + - "\x9a\x46\x60\xc2\xfc\x5e\x72\x57\x24\x34\xa5\x17\xd7\xfb\x85\x51\xd5\x7a\x79\x62\xdc\x66\x0b\x5a\x12\xd2\xc4\x05" + - "\x8f\x27\xc8\xc1\x1a\xf4\x28\xe8\x70\x1c\x78\x30\x5b\xfc\x6e\xba\x2e\x8f\x52\xfa\x4a\x0c\x86\xe1\x53\x5d\xe5\xef" + - "\x24\x46\x24\x3c\xcb\xf3\x6f\xd9\x73\xcf\x77\xf5\x27\x73\x5a\xd8\xd6\x34\x88\x8e\xe6\x76\x49\xae\x9e\xbd\x79\xe1" + - "\x39\x26\x0b\xa9\x1a\x08\x6e\xc9\x11\x9f\x13\xc8\x74\x3e\xd3\xad\xa9\x82\xa3\x32\x80\xf3\x40\x7d\xf3\xa2\x84\xec" + - "\xf1\xba\x85\x60\xb5\xb5\x75\x1c\x99\x9b\xc2\x91\xdf\x0f\xe7\x85\xc6\xac\xb4\x2b\x74\xb9\xa4\xba\x8a\xba\xf2\x81" + - "\x35\x0b\x8d\xcc\x9e\x9b\xff\xc6\xb6\xba\xca\x9d\x94\x5d\x57\x57\xcb\x7a\x6d\x45\xff\xec\x58\x3d\x13\x9d\x2e\xac" + - "\xb2\x7a\x0e\xd4\xb0\xca\xd5\xb2\xb6\xad\x6a\xea\x93\xb5\xc5\xca\x20\x83\x78\xad\x1a\x1a\xf1\x58\x41\xee\x5a\x30" + - "\xbb\x11\xa2\x52\x61\x31\x67\x22\x6b\xa5\x42\x43\xd0\x88\xc5\xc0\xec\xc9\x44\xe5\xa6\x29\xce\x1d\xab\xda\x40\xfc" + - "\x3c\xbf\x1f\x41\xbb\x34\x59\x00\x17\xd7\x2c\x01\x3d\x22\x37\x65\x71\x6e\x1a\x4a\xc7\xa8\x4a\x6e\xd8\x4f\x19\x66" + - "\xc8\x57\x2f\x6a\x24\xe2\xe4\x8e\xea\x88\x0c\x7b\x72\x12\x1e\xb8\x4f\xf2\x08\x68\x53\xa2\x83\x17\x1a\x02\x1e\x27" + - "\x13\xb2\x5e\x95\x0a\x72\x76\xce\xcb\x62\x06\x41\xe1\x8b\x02\x90\x97\x0a\xab\xce\x4d\x03\x5e\x04\xf5\x9c\xba\x3a" + - "\x02\xe7\x4a\x77\x61\x5d\xd4\xcd\xd9\x98\x76\xc6\x0f\x75\x4b\x2a\x33\x77\x9d\x2c\xf5\x65\xb1\x5c\x2f\x95\xe3\x61" + - "\xf5\x49\x51\x16\xed\xd5\x48\x95\xc5\x49\xa3\x9b\x82\x17\x5c\x37\x06\x16\x98\x26\x00\x41\x3b\x68\xbe\x66\xa5\x06" + - "\x07\x55\xb3\xb4\xa6\x3c\x37\x16\x83\x04\x79\x45\x69\x35\x71\xfe\xd0\xe5\x81\x22\x49\x94\xe6\x91\xc3\x88\x51\x8a" + - "\x79\xf3\x02\x5c\xb4\x90\x14\x43\x3e\xf8\xaa\x1d\x8b\x79\xd7\x51\xa0\xd9\x18\x22\xd6\x97\x75\xe3\x58\xc9\xb9\x5b" + - "\x12\x34\x19\x5b\x83\xf3\xdf\x77\x29\x36\x27\xeb\xe6\xcc\x4c\x1c\x35\x2b\x1a\xf3\xd1\x4e\x2e\x8a\xb3\x62\xf2\xf3" + - "\x2a\x87\x05\xd9\x65\x6f\xdf\x5d\x3f\x03\x0f\x5c\x81\x5d\x37\x22\x37\x7d\x52\xa7\x8d\xdb\x9f\xb4\x93\x74\x94\xc1" + - "\x7b\x0b\x5f\x8c\xf5\x92\x79\x7a\x7c\x30\x50\x19\x6e\xc7\x6c\x04\x4e\x6c\xb7\x42\x3f\x3d\x8d\xc0\x3e\xbc\xc3\x00" + - "\x3a\x08\xbd\xd1\x2b\x70\x3f\xf5\x33\x43\x59\x59\xeb\xb9\xf7\x4a\x75\xec\xc6\x6f\xf4\xda\x3b\x17\xd0\xae\x60\x3f" + - "\x23\x5f\x8d\xdb\x86\x9f\x6d\xac\xe5\xb3\x50\xc1\x67\x92\x1a\x89\x6d\x18\xf9\x70\x1a\xb3\x92\x6e\x6e\xfc\x29\x4c" + - "\x14\xf5\x88\x46\x1c\x5e\xa9\xdf\x3e\x0b\xfe\x1c\xf0\x19\x54\xf3\xf0\x61\xdc\xf5\xcd\x75\xf8\xa1\xfe\x26\xe6\xaf" + - "\xeb\x44\xe8\x29\x2a\x38\xe5\xac\x6a\xeb\x49\xa0\xdb\xa0\x9f\xa9\x02\xb0\x52\xe6\x05\xf8\x79\x80\x89\xbe\x08\x5b" + - "\x73\xf0\xe0\x2f\xfb\x7b\x8f\x1f\xcc\xea\xa5\x23\xea\xd3\xfd\xbd\xd1\x27\xf2\x5d\x4f\x9e\xfc\x65\x08\xb5\xb8\x46" + - "\x9e\x03\x96\xf9\x3f\xde\xc1\xe9\x3b\x69\xea\x0b\x6b\x1a\x65\x96\xeb\x52\xb7\x75\x63\xd5\xe0\xc1\xfe\x17\x4f\xbe" + - "\xfa\x6a\x18\xef\xb5\xaa\xc6\xb4\x04\x30\x01\x3d\xd6\x92\x74\x16\xc4\xcc\x86\x81\x87\x9d\x94\xce\x89\xbb\xe5\xdc" + - "\x66\xfb\xff\x03\x00\x00\xff\xff\x1d\x30\x27\xdd\x1d\xea\x03\x00") - -func gzipBindataAssetsjsjquery211js() (*gzipAsset, error) { - bytes := _gzipBindataAssetsjsjquery211js - info := gzipBindataFileInfo{ - name: "assets/js/jquery-2.1.1.js", - size: 256541, - md5checksum: "", - mode: os.FileMode(438), - modTime: time.Unix(1520997241, 0), - } - - a := &gzipAsset{bytes: bytes, info: info} - - return a, nil -} - - - -// GzipAsset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func GzipAsset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _gzipbindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("GzipAsset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} -} - -// MustGzipAsset is like GzipAsset but panics when GzipAsset would return an error. -// It simplifies safe initialization of global variables. -// nolint: deadcode -func MustGzipAsset(name string) []byte { - a, err := GzipAsset(name) - if err != nil { - panic("asset: GzipAsset(" + name + "): " + err.Error()) - } - - return a -} - -// GzipAssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or could not be loaded. -func GzipAssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _gzipbindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("GzipAssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} -} - -// GzipAssetNames returns the names of the assets. -// nolint: deadcode -func GzipAssetNames() []string { - names := make([]string, 0, len(_gzipbindata)) - for name := range _gzipbindata { - names = append(names, name) - } - return names -} - -// -// _gzipbindata is a table, holding each asset generator, mapped to its name. -// -var _gzipbindata = map[string]func() (*gzipAsset, error){ - "assets/css/bootstrap.min.css": gzipBindataAssetscssbootstrapmincss, - "assets/favicon.ico": gzipBindataAssetsfaviconico, - "assets/js/jquery-2.1.1.js": gzipBindataAssetsjsjquery211js, -} - - -// GzipAssetDir returns the file names below a certain -// directory embedded in the file by bindata. -// For example if you run bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then GzipAssetDir("data") would return []string{"foo.txt", "img"} -// GzipAssetDir("data/img") would return []string{"a.png", "b.png"} -// GzipAssetDir("foo.txt") and GzipAssetDir("notexist") would return an error -// GzipAssetDir("") will return []string{"data"}. -func GzipAssetDir(name string) ([]string, error) { - node := _gzipbintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, &os.PathError{ - Op: "open", - Path: name, - Err: os.ErrNotExist, - } - } - } - } - if node.Func != nil { - return nil, &os.PathError{ - Op: "open", - Path: name, - Err: os.ErrNotExist, - } - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - - -type gzipBintree struct { - Func func() (*gzipAsset, error) - Children map[string]*gzipBintree -} - -var _gzipbintree = &gzipBintree{Func: nil, Children: map[string]*gzipBintree{ - "assets": {Func: nil, Children: map[string]*gzipBintree{ - "css": {Func: nil, Children: map[string]*gzipBintree{ - "bootstrap.min.css": {Func: gzipBindataAssetscssbootstrapmincss, Children: map[string]*gzipBintree{}}, - }}, - "favicon.ico": {Func: gzipBindataAssetsfaviconico, Children: map[string]*gzipBintree{}}, - "js": {Func: nil, Children: map[string]*gzipBintree{ - "jquery-2.1.1.js": {Func: gzipBindataAssetsjsjquery211js, Children: map[string]*gzipBintree{}}, - }}, - }}, -}} diff --git a/file-server/embedding-gziped-files-into-app/main.go b/file-server/embedding-gziped-files-into-app/main.go deleted file mode 100644 index 944c251d..00000000 --- a/file-server/embedding-gziped-files-into-app/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" -) - -// NOTE: need different tool than the "embedding-files-into-app" example. -// -// Follow these steps first: -// $ go get -u github.com/kataras/bindata/cmd/bindata -// $ bindata ./assets/... -// $ go build -// $ ./embedding-gziped-files-into-app -// "physical" files are not used, you can delete the "assets" folder and run the example. - -func newApp() *iris.Application { - app := iris.New() - - // Note the `GzipAsset` and `GzipAssetNames` are different from `go-bindata`'s `Asset` and `AssetNames, - // that means that you can use both `go-bindata` and `bindata` tools, - // the `go-bindata` can be used for the view engine's `Binary` method - // and the `bindata` with the `StaticEmbeddedGzip` (x8 times faster than the StaticEmbeded with `go-bindata`). - app.StaticEmbeddedGzip("/static", "./assets", GzipAsset, GzipAssetNames) - - return app -} - -func main() { - app := newApp() - - // http://localhost:8080/static/css/bootstrap.min.css - // http://localhost:8080/static/js/jquery-2.1.1.js - // http://localhost:8080/static/favicon.ico - app.Run(iris.Addr(":8080")) -} diff --git a/file-server/embedding-gzipped-files-into-app-bindata/bindata.go b/file-server/embedding-gzipped-files-into-app-bindata/bindata.go new file mode 100644 index 00000000..a4167288 --- /dev/null +++ b/file-server/embedding-gzipped-files-into-app-bindata/bindata.go @@ -0,0 +1,383 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// ../embedding-files-into-app-bindata/assets/css/main.css +// ../embedding-files-into-app-bindata/assets/favicon.ico +// ../embedding-files-into-app-bindata/assets/js/main.js +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _cssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x28\xc9\xcd\x51\xa8\xe6\xe5\xe2\x4c\xcb\xcf\x2b\xd1\x4d\x4b\xcc\xcd\xcc\xa9\xb4\x52\x28\x4e\xcc\x2b\xd6\x2d\x4e\x2d\xca\x4c\xb3\xe6\xe5\xe2\xd4\x2d\x4f\x4d\xca\xce\x2c\xd1\x2d\x49\xad\x28\xd1\x2d\xce\xac\x4a\xd5\x4d\x4c\xc9\x2a\x2d\x2e\xb1\x52\x30\x34\x30\x50\x05\xab\xc8\x2d\xc6\x21\xcb\xcb\x55\x0b\x08\x00\x00\xff\xff\x32\x4c\x06\xc6\x63\x00\x00\x00") + +func cssMainCssBytes() ([]byte, error) { + return bindataRead( + _cssMainCss, + "css/main.css", + ) +} + +func cssMainCss() (*asset, error) { + bytes, err := cssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "css/main.css", size: 99, mode: os.FileMode(438), modTime: time.Unix(1613718750, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _faviconIco = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00") + +func faviconIcoBytes() ([]byte, error) { + return bindataRead( + _faviconIco, + "favicon.ico", + ) +} + +func faviconIco() (*asset, error) { + bytes, err := faviconIcoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "favicon.ico", size: 15086, mode: os.FileMode(438), modTime: time.Unix(1612640817, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _jsMainJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xce\xcf\x2b\xce\xcf\x49\xd5\xcb\xc9\x4f\xd7\x50\x4a\xad\x48\xcc\x2d\xc8\x49\x55\xd2\xb4\x06\x04\x00\x00\xff\xff\xc8\x9f\xbd\x5f\x17\x00\x00\x00") + +func jsMainJsBytes() ([]byte, error) { + return bindataRead( + _jsMainJs, + "js/main.js", + ) +} + +func jsMainJs() (*asset, error) { + bytes, err := jsMainJsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "js/main.js", size: 23, mode: os.FileMode(438), modTime: time.Unix(1613718745, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "css/main.css": cssMainCss, + "favicon.ico": faviconIco, + "js/main.js": jsMainJs, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "css": {nil, map[string]*bintree{ + "main.css": {cssMainCss, map[string]*bintree{}}, + }}, + "favicon.ico": {faviconIco, map[string]*bintree{}}, + "js": {nil, map[string]*bintree{ + "main.js": {jsMainJs, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/file-server/embedding-gzipped-files-into-app-bindata/main.go b/file-server/embedding-gzipped-files-into-app-bindata/main.go new file mode 100644 index 00000000..78809bbe --- /dev/null +++ b/file-server/embedding-gzipped-files-into-app-bindata/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +// How to run: +// +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// $ go-bindata -prefix "../embedding-files-into-app-bindata/assets/" -fs ../embedding-files-into-app-bindata/assets/... +// $ go run -mod=mod . +// Time to complete the compression and caching of [2/3] files: 31.9998ms +// Total size reduced from 156.6 kB to: +// br (22.9 kB) [85.37%] +// snappy (41.7 kB) [73.37%] +// gzip (27.9 kB) [82.16%] +// deflate (27.9 kB) [82.19%] + +var dirOptions = iris.DirOptions{ + IndexName: "index.html", + // The `Compress` field is ignored + // when the file is cached (when Cache.Enable is true), + // because the cache file has a map of pre-compressed contents for each encoding + // that is served based on client's accept-encoding. + Compress: true, // true or false does not matter here. + Cache: iris.DirCacheOptions{ + Enable: true, + CompressIgnore: iris.MatchImagesAssets, + // Here, define the encodings that the cached files should be pre-compressed + // and served based on client's needs. + Encodings: []string{"gzip", "deflate", "br", "snappy"}, + CompressMinSize: 50, // files smaller than this size will NOT be compressed. + Verbose: 1, + }, +} + +func newApp() *iris.Application { + app := iris.New() + app.HandleDir("/static", AssetFile(), dirOptions) + return app +} + +func main() { + app := newApp() + + // http://localhost:8080/static/css/main.css + // http://localhost:8080/static/js/main.js + // http://localhost:8080/static/favicon.ico + app.Listen(":8080") +} diff --git a/file-server/embedding-gziped-files-into-app/main_test.go b/file-server/embedding-gzipped-files-into-app-bindata/main_test.go similarity index 56% rename from file-server/embedding-gziped-files-into-app/main_test.go rename to file-server/embedding-gzipped-files-into-app-bindata/main_test.go index 596ecc7f..b4f4c3e4 100644 --- a/file-server/embedding-gziped-files-into-app/main_test.go +++ b/file-server/embedding-gzipped-files-into-app-bindata/main_test.go @@ -2,13 +2,13 @@ package main import ( "bytes" - "io/ioutil" + "os" "path/filepath" "runtime" "strings" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" "github.com/klauspost/compress/gzip" ) @@ -20,7 +20,7 @@ type resource string func (r resource) contentType() string { switch filepath.Ext(r.String()) { case ".js": - return "application/javascript" + return "text/javascript" case ".css": return "text/css" case ".ico": @@ -48,29 +48,32 @@ func (r resource) loadFromBase(dir string) string { fullpath := filepath.Join(dir, filename) - b, err := ioutil.ReadFile(fullpath) + b, err := os.ReadFile(fullpath) if err != nil { panic(fullpath + " failed with error: " + err.Error()) } result := string(b) if runtime.GOOS != "windows" { - result = strings.Replace(result, "\n", "\r\n", -1) + result = strings.ReplaceAll(result, "\n", "\r\n") + result = strings.ReplaceAll(result, "\r\r", "") } return result } var urls = []resource{ - "/static/css/bootstrap.min.css", - "/static/js/jquery-2.1.1.js", + "/static/css/main.css", + "/static/js/main.js", "/static/favicon.ico", } // if bindata's values matches with the assets/... contents -// and secondly if the StaticEmbedded had successfully registered +// and secondly if the HandleDir had successfully registered // the routes and gave the correct response. func TestEmbeddingGzipFilesIntoApp(t *testing.T) { + dirOptions.Cache.Verbose = 0 app := newApp() + e := httptest.New(t, app) if runtime.GOOS != "windows" { @@ -81,26 +84,43 @@ func TestEmbeddingGzipFilesIntoApp(t *testing.T) { for i, u := range urls { url := u.String() - rawContents := u.loadFromBase("./assets") + rawContents := u.loadFromBase("../embedding-files-into-app-bindata/assets") + shouldBeCompressed := int64(len(rawContents)) >= dirOptions.Cache.CompressMinSize - response := e.GET(url).Expect() + request := e.GET(url) + if shouldBeCompressed { + request.WithHeader("Accept-Encoding", "gzip") + } + response := request.Expect() response.ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()) + if shouldBeCompressed { + response.ContentEncoding("gzip") + } if expected, got := response.Raw().StatusCode, httptest.StatusOK; expected != got { t.Fatalf("[%d] of '%s': expected %d status code but got %d", i, url, expected, got) } + rawBody := response.Body().Raw() - func() { - reader, err := gzip.NewReader(bytes.NewBuffer(response.Content)) + if shouldBeCompressed { + reader, err := gzip.NewReader(strings.NewReader(rawBody)) defer reader.Close() if err != nil { t.Fatalf("[%d] of '%s': %v", i, url, err) } buf := new(bytes.Buffer) reader.WriteTo(buf) - if rawContents != buf.String() { - t.Fatalf("[%d] of '%s': expected body:\n%s but got:\n%s", i, url, rawContents, buf.String()) + if expected, got := rawContents, buf.String(); expected != got { + // t.Fatalf("[%d] of '%s': expected body:\n%s but got:\n%s", i, url, expected, got) + // let's reduce the output here... + // they are big files, no need to check for length here. + t.Fatalf("[%d] %s, expected body to look like: '%s...%s' but got '%s...%s'", i, url, expected[:40], expected[len(rawContents)-40:], got[:40], got[len(got)-40:]) } - }() + } else { + if expected, got := rawContents, rawBody; expected != got { + t.Fatalf("[%d] %s, expected body to look like: '%s...%s' but got '%s...%s'", i, url, expected[:40], expected[len(rawContents)-40:], got[:40], got[len(got)-40:]) + } + } + } } diff --git a/file-server/favicon/main.go b/file-server/favicon/main.go index dd857e6e..f10f6088 100644 --- a/file-server/favicon/main.go +++ b/file-server/favicon/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -20,5 +20,5 @@ func main() { so iris serves your favicon in that path too (you can change it).`) }) // if favicon doesn't show to you, try to clear your browser's cache. - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/file-server/file-server/main.go b/file-server/file-server/main.go new file mode 100644 index 00000000..a49f73e1 --- /dev/null +++ b/file-server/file-server/main.go @@ -0,0 +1,137 @@ +package main + +import ( + "crypto/md5" + "fmt" + "io" + "mime/multipart" + "os" + "path" + "strconv" + "strings" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" +) + +func init() { + os.Mkdir("./uploads", 0700) +} + +const ( + maxSize = 1 * iris.GB + uploadDir = "./uploads" +) + +func main() { + app := iris.New() + + view := iris.HTML("./views", ".html") + view.AddFunc("formatBytes", func(b int64) string { + const unit = 1000 + if b < unit { + return fmt.Sprintf("%d B", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %cB", + float64(b)/float64(div), "kMGTPE"[exp]) + }) + app.RegisterView(view) + + // Serve assets (e.g. javascript, css). + // app.HandleDir("/public", iris.Dir("./public")) + + app.Get("/", index) + + app.Get("/upload", uploadView) + app.Post("/upload", upload) + + filesRouter := app.Party("/files") + { + filesRouter.HandleDir("/", iris.Dir(uploadDir), iris.DirOptions{ + Compress: true, + ShowList: true, + + // Optionally, force-send files to the client inside of showing to the browser. + Attachments: iris.Attachments{ + Enable: true, + // Optionally, control data sent per second: + Limit: 50.0 * iris.KB, + Burst: 100 * iris.KB, + // Change the destination name through: + // NameFunc: func(systemName string) string {...} + }, + + DirList: iris.DirListRich(iris.DirListRichOptions{ + // Optionally, use a custom template for listing: + // Tmpl: dirListRichTemplate, + TmplName: "dirlist.html", + }), + }) + + auth := basicauth.Default(map[string]string{ + "myusername": "mypassword", + }) + + filesRouter.Delete("/{file:path}", auth, deleteFile) + } + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.Redirect("/upload") +} + +func uploadView(ctx iris.Context) { + now := time.Now().Unix() + h := md5.New() + io.WriteString(h, strconv.FormatInt(now, 10)) + token := fmt.Sprintf("%x", h.Sum(nil)) + + if err := ctx.View("upload.html", token); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func upload(ctx iris.Context) { + ctx.SetMaxRequestBodySize(maxSize) + + _, _, err := ctx.UploadFormFiles(uploadDir, beforeSave) + if err != nil { + ctx.StopWithError(iris.StatusRequestEntityTooLarge, err) + return + } + + ctx.Redirect("/files") +} + +func beforeSave(ctx iris.Context, file *multipart.FileHeader) bool { + ip := ctx.RemoteAddr() + ip = strings.ReplaceAll(ip, ".", "_") + ip = strings.ReplaceAll(ip, ":", "_") + + file.Filename = ip + "-" + file.Filename + return true +} + +func deleteFile(ctx iris.Context) { + // It does not contain the system path, + // as we are not exposing it to the user. + fileName := ctx.Params().Get("file") + + filePath := path.Join(uploadDir, fileName) + + if err := os.RemoveAll(filePath); err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Redirect("/files") +} diff --git a/file-server/file-server/views/dirlist.html b/file-server/file-server/views/dirlist.html new file mode 100644 index 00000000..2b676f0c --- /dev/null +++ b/file-server/file-server/views/dirlist.html @@ -0,0 +1,125 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{.Title}}</title> + <style> + a { + padding: 8px 8px; + text-decoration: none; + cursor: pointer; + color: #10a2ff; + } + + table { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + height: 100%; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + border: 1px solid #cbcbcb; + } + + table caption { + color: #000; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; + } + + table td, + table th { + border-left: 1px solid #cbcbcb; + border-width: 0 0 0 1px; + font-size: inherit; + margin: 0; + overflow: visible; + padding: 0.5em 1em; + } + + table thead { + background-color: #10a2ff; + color: #fff; + text-align: left; + vertical-align: bottom; + } + + table td { + background-color: transparent; + } + + .table-odd td { + background-color: #f2f2f2; + } + + .table-bordered td { + border-bottom: 1px solid #cbcbcb; + } + + .table-bordered tbody>tr:last-child>td { + border-bottom-width: 0; + } + </style> +</head> + +<body> + <table class="table-bordered table-odd"> + <thead> + <tr> + <th>#</th> + <th>Name</th> + <th>Size</th> + <th>Actions</th> + </tr> + </thead> + <tbody> + {{ range $idx, $file := .Files }} + <tr> + <td>{{ $idx }}</td> + {{ if $file.Download }} + <td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}" download>{{ $file.Name }}</a></td> + {{ else }} + <td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}">{{ $file.Name }}</a></td> + {{ end }} + {{ if $file.Info.IsDir }} + <td>Dir</td> + {{ else }} + <td>{{ formatBytes $file.Info.Size }}</td> + {{ end }} + + <td><input type="button" style="background-color:transparent;border:0px;cursor:pointer;" value="❌" + onclick="deleteFile({{ $file.RelPath }})" /></td> + </tr> + {{ end }} + </tbody> + </table> + <script type="text/javascript"> + function deleteFile(filename) { + if (!confirm("Are you sure you want to delete " + filename + " ?")) { + return; + } + + fetch('/files/' + filename, + { + method: "DELETE", + // If you don't want server to prompt for username/password: + // credentials:"include", + headers: { + // "Authorization": "Basic " + btoa("myusername:mypassword") + "X-Requested-With": "XMLHttpRequest", + }, + }). + then(data => location.reload()). + catch(e => alert(e)); + } + </script> +</body> + +</html> \ No newline at end of file diff --git a/file-server/file-server/views/upload.html b/file-server/file-server/views/upload.html new file mode 100644 index 00000000..a278be2e --- /dev/null +++ b/file-server/file-server/views/upload.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Upload Files</title> +</head> + +<body> + <form enctype="multipart/form-data" action="/upload" method="POST"> + <input type="file" id="upload_files" name="upload_files" multiple /> <input type="hidden" name="token" + value="{{.}}" /> + + <input type="button" value="Upload Using Javascript" onclick="uploadFiles()" /> + <input type="submit" value="Upload by submiting the form" /> + </form> + + <script type="text/javascript"> + function uploadFiles() { + let files = document.getElementById("upload_files").files; + let formData = new FormData(); + for (var i = 0; i < files.length; i++) { + formData.append("files[]", files[i]); + } + + fetch('/upload', + { + method: "POST", + body: formData + }). + then(data => window.location = "/files"). + catch(e => window.alert("upload failed: file too large")); + } + </script> +</body> + +</html> \ No newline at end of file diff --git a/file-server/http2push-embedded-gzipped/bindata.go b/file-server/http2push-embedded-gzipped/bindata.go new file mode 100644 index 00000000..dbea0bd3 --- /dev/null +++ b/file-server/http2push-embedded-gzipped/bindata.go @@ -0,0 +1,581 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// ../http2push/assets/app2/app2app3/css/main.css +// ../http2push/assets/app2/app2app3/dirs/dir1/text.txt +// ../http2push/assets/app2/app2app3/dirs/dir2/text.txt +// ../http2push/assets/app2/app2app3/dirs/text.txt +// ../http2push/assets/app2/app2app3/index.html +// ../http2push/assets/app2/index.html +// ../http2push/assets/app2/mydir/text.txt +// ../http2push/assets/css/main.css +// ../http2push/assets/favicon.ico +// ../http2push/assets/index.html +// ../http2push/assets/js/main.js +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data, name string) ([]byte, error) { + gz, err := gzip.NewReader(strings.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _app2App2app3CssMainCss = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x29\x4d\xb5\xe6\xe5\xaa\x05\x04\x00\x00\xff\xff\x52\xd7\xbb\x8b\x26\x00\x00\x00" + +func app2App2app3CssMainCssBytes() ([]byte, error) { + return bindataRead( + _app2App2app3CssMainCss, + "app2/app2app3/css/main.css", + ) +} + +func app2App2app3CssMainCss() (*asset, error) { + bytes, err := app2App2app3CssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/css/main.css", size: 38, mode: os.FileMode(438), modTime: time.Unix(1595043712, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsDir1TextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\x20\xc2\x50\xbf\x24\xb5\xa2\x44\xaf\xa4\xa2\x04\x10\x00\x00\xff\xff\x87\xaf\x9d\x00\x20\x00\x00\x00" + +func app2App2app3DirsDir1TextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsDir1TextTxt, + "app2/app2app3/dirs/dir1/text.txt", + ) +} + +func app2App2app3DirsDir1TextTxt() (*asset, error) { + bytes, err := app2App2app3DirsDir1TextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/dir1/text.txt", size: 32, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsDir2TextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\x20\xc2\x48\xbf\x24\xb5\xa2\x44\xaf\xa4\xa2\x04\x10\x00\x00\xff\xff\x84\x14\xaa\xeb\x20\x00\x00\x00" + +func app2App2app3DirsDir2TextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsDir2TextTxt, + "app2/app2app3/dirs/dir2/text.txt", + ) +} + +func app2App2app3DirsDir2TextTxt() (*asset, error) { + bytes, err := app2App2app3DirsDir2TextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/dir2/text.txt", size: 32, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsTextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\xfa\x25\xa9\x15\x25\x7a\x25\x15\x25\x80\x00\x00\x00\xff\xff\x64\xfe\x96\xd6\x1b\x00\x00\x00" + +func app2App2app3DirsTextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsTextTxt, + "app2/app2app3/dirs/text.txt", + ) +} + +func app2App2app3DirsTextTxt() (*asset, error) { + bytes, err := app2App2app3DirsTextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/text.txt", size: 27, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3IndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\x3f\x4f\xc3\x40\x0c\xc5\xf7\x48\xf9\x0e\xc6\x33\xed\x91\x76\x61\xb8\x8b\x54\xf1\x47\x6c\x30\x94\x81\xf1\x7a\x31\x9c\x85\x73\x39\xe5\x4c\x4b\xbf\x3d\x4a\x68\x90\x58\x6c\x3d\xfb\xbd\x9f\x64\xdb\xab\xfb\xe7\xbb\xfd\xdb\xcb\x03\x44\xed\xa5\xad\x2b\x3b\x75\x10\x9f\x3e\x1c\x52\xc2\xb6\xae\xa6\x19\xf9\xae\xad\x2b\x00\x00\xdb\x93\x7a\x08\xd1\x8f\x85\xd4\xe1\xeb\xfe\x71\x75\x8b\xff\x76\xc9\xf7\xe4\xf0\xc8\x74\xca\xc3\xa8\x08\x61\x48\x4a\x49\x1d\x9e\xb8\xd3\xe8\x3a\x3a\x72\xa0\xd5\x2c\xae\x81\x13\x2b\x7b\x59\x95\xe0\x85\x5c\xb3\xbe\xf9\x63\x09\xa7\x4f\x18\x49\x1c\x16\x3d\x0b\x95\x48\xa4\x08\x71\xa4\x77\x87\x26\x7f\x1d\x84\x83\xf1\x39\x6f\xe6\xe2\x73\xde\x9a\x50\x8a\xe9\x3d\xa7\x75\x28\x05\xc1\x2c\x20\x65\x15\x6a\x77\x39\x6f\x76\x39\x6f\xad\xf9\xd5\x75\x65\xcd\xe5\xac\xba\xb2\x87\xa1\x3b\x2f\xfe\xd8\xb4\x4f\x24\x32\xc0\x12\x01\x4e\x1d\x7d\x5b\x13\x9b\x39\x75\xf1\xce\x80\xe9\x67\x3f\x01\x00\x00\xff\xff\xef\x25\x54\xc8\x43\x01\x00\x00" + +func app2App2app3IndexHtmlBytes() ([]byte, error) { + return bindataRead( + _app2App2app3IndexHtml, + "app2/app2app3/index.html", + ) +} + +func app2App2app3IndexHtml() (*asset, error) { + bytes, err := app2App2app3IndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/index.html", size: 323, mode: os.FileMode(438), modTime: time.Unix(1595043725, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2IndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb4\xf3\x48\xcd\xc9\xc9\x57\x70\x2c\x28\x30\x52\xc8\xcc\x4b\x49\xad\xb0\xd1\xcf\x30\xb4\x03\x04\x00\x00\xff\xff\x75\x17\xab\xfa\x19\x00\x00\x00" + +func app2IndexHtmlBytes() ([]byte, error) { + return bindataRead( + _app2IndexHtml, + "app2/index.html", + ) +} + +func app2IndexHtml() (*asset, error) { + bytes, err := app2IndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/index.html", size: 25, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2MydirTextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x2a\x2d\x2e\x51\x48\x54\x28\x49\xad\x28\xd1\x03\x04\x00\x00\xff\xff\x2f\xf9\x22\x98\x0c\x00\x00\x00" + +func app2MydirTextTxtBytes() ([]byte, error) { + return bindataRead( + _app2MydirTextTxt, + "app2/mydir/text.txt", + ) +} + +func app2MydirTextTxt() (*asset, error) { + bytes, err := app2MydirTextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/mydir/text.txt", size: 12, mode: os.FileMode(438), modTime: time.Unix(1594787248, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _cssMainCss = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00" + +func cssMainCssBytes() ([]byte, error) { + return bindataRead( + _cssMainCss, + "css/main.css", + ) +} + +func cssMainCss() (*asset, error) { + bytes, err := cssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _faviconIco = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00" + +func faviconIcoBytes() ([]byte, error) { + return bindataRead( + _faviconIco, + "favicon.ico", + ) +} + +func faviconIco() (*asset, error) { + bytes, err := faviconIcoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "favicon.ico", size: 15086, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _indexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x91\x3d\x4f\xc3\x30\x10\x86\xf7\x48\xf9\x0f\xd7\x9b\x40\x22\x35\x6c\x0c\x71\x96\x42\x57\x90\x28\x03\xa3\xeb\x5c\x9b\x6b\x1d\x27\xb2\x2f\x69\xfb\xef\x51\x3e\xca\xe7\x64\xdf\xeb\xbb\xc7\x8f\xec\x7c\xf1\xf4\xb2\xda\x7c\xbc\x3e\x43\x25\xb5\x2b\xd2\x24\x1f\x56\x70\xc6\xef\x35\x92\xc7\x22\x4d\x86\x8c\x4c\x59\xa4\x09\x00\x40\x5e\x93\x18\xb0\x95\x09\x91\x44\xe3\xfb\x66\x9d\x3d\xe2\xaf\x33\x6f\x6a\xd2\xd8\x33\x9d\xda\x26\x08\x82\x6d\xbc\x90\x17\x8d\x27\x2e\xa5\xd2\x25\xf5\x6c\x29\x1b\x8b\x3b\x60\xcf\xc2\xc6\x65\xd1\x1a\x47\xfa\x61\x79\xff\xc5\x72\xec\x8f\x10\xc8\x69\x64\xdb\x78\x84\x2a\xd0\x4e\xa3\x6a\xbb\xad\x63\xab\x76\xa6\x1f\xe2\x25\xdb\x06\x41\x2e\x2d\x69\xe4\xda\xec\x49\x9d\xb3\xa9\x5d\xfd\xe7\x44\xb9\x38\x8a\x15\x91\xfc\xa5\xd9\x18\x55\x6d\xd8\x2f\x6d\x8c\x3f\x46\x85\xc5\x51\xb1\x66\x47\xf0\x46\xa1\xa7\x90\xab\x29\x4a\x93\x5c\xcd\x6f\x92\x26\xf9\xb6\x29\x2f\xd7\x11\xf6\x6d\x27\xb3\xd0\xb6\x13\x19\x54\x1a\x6f\x1d\xdb\xa3\xc6\xc6\xaf\x86\xcd\xcd\x2d\x42\x6f\x5c\x47\x1a\xc7\x1a\x6a\x5a\x4c\xb7\xce\x90\x68\x03\xb7\x57\x8a\xd0\x59\xd4\xc1\xf4\x66\x4a\x11\x62\xb0\xdf\xe6\x87\x59\xfc\x10\xb1\xc8\xd5\xd4\x32\xea\xcd\x52\xa3\xe9\xf0\xb3\x9f\x01\x00\x00\xff\xff\x00\xcf\x96\xa8\xe9\x01\x00\x00" + +func indexHtmlBytes() ([]byte, error) { + return bindataRead( + _indexHtml, + "index.html", + ) +} + +func indexHtml() (*asset, error) { + bytes, err := indexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "index.html", size: 489, mode: os.FileMode(438), modTime: time.Unix(1594886229, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _jsMainJs = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xce\xcf\x2b\xce\xcf\x49\xd5\xcb\xc9\x4f\xd7\x50\x4a\xad\x48\xcc\x2d\xc8\x49\x55\xd2\xb4\xe6\xe5\xe2\xe5\x4a\x2b\xcd\x4b\x2e\xc9\xcc\xcf\x53\xc8\xcf\x73\xce\xc9\x4c\xce\xd6\xd0\x54\xa8\xe6\xe5\x52\x50\x50\x50\x28\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2a\x2d\x29\xc9\xcf\x53\x48\x06\xa9\x49\x4d\x01\x6b\xae\x05\x04\x00\x00\xff\xff\xa4\xb7\x99\x52\x57\x00\x00\x00" + +func jsMainJsBytes() ([]byte, error) { + return bindataRead( + _jsMainJs, + "js/main.js", + ) +} + +func jsMainJs() (*asset, error) { + bytes, err := jsMainJsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "js/main.js", size: 87, mode: os.FileMode(438), modTime: time.Unix(1594787764, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "app2/app2app3/css/main.css": app2App2app3CssMainCss, + "app2/app2app3/dirs/dir1/text.txt": app2App2app3DirsDir1TextTxt, + "app2/app2app3/dirs/dir2/text.txt": app2App2app3DirsDir2TextTxt, + "app2/app2app3/dirs/text.txt": app2App2app3DirsTextTxt, + "app2/app2app3/index.html": app2App2app3IndexHtml, + "app2/index.html": app2IndexHtml, + "app2/mydir/text.txt": app2MydirTextTxt, + "css/main.css": cssMainCss, + "favicon.ico": faviconIco, + "index.html": indexHtml, + "js/main.js": jsMainJs, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "app2": {nil, map[string]*bintree{ + "app2app3": {nil, map[string]*bintree{ + "css": {nil, map[string]*bintree{ + "main.css": {app2App2app3CssMainCss, map[string]*bintree{}}, + }}, + "dirs": {nil, map[string]*bintree{ + "dir1": {nil, map[string]*bintree{ + "text.txt": {app2App2app3DirsDir1TextTxt, map[string]*bintree{}}, + }}, + "dir2": {nil, map[string]*bintree{ + "text.txt": {app2App2app3DirsDir2TextTxt, map[string]*bintree{}}, + }}, + "text.txt": {app2App2app3DirsTextTxt, map[string]*bintree{}}, + }}, + "index.html": {app2App2app3IndexHtml, map[string]*bintree{}}, + }}, + "index.html": {app2IndexHtml, map[string]*bintree{}}, + "mydir": {nil, map[string]*bintree{ + "text.txt": {app2MydirTextTxt, map[string]*bintree{}}, + }}, + }}, + "css": {nil, map[string]*bintree{ + "main.css": {cssMainCss, map[string]*bintree{}}, + }}, + "favicon.ico": {faviconIco, map[string]*bintree{}}, + "index.html": {indexHtml, map[string]*bintree{}}, + "js": {nil, map[string]*bintree{ + "main.js": {jsMainJs, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/file-server/http2push-embedded-gzipped/main.go b/file-server/http2push-embedded-gzipped/main.go new file mode 100644 index 00000000..210f4833 --- /dev/null +++ b/file-server/http2push-embedded-gzipped/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "regexp" + + "github.com/kataras/iris/v12" +) + +// How to run: +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// $ go-bindata -nomemcopy -fs -prefix "../http2push/assets" ../http2push/assets/... +// $ go run . + +var opts = iris.DirOptions{ + IndexName: "index.html", + PushTargetsRegexp: map[string]*regexp.Regexp{ + "/": iris.MatchCommonAssets, + "/app2/app2app3": iris.MatchCommonAssets, + }, + ShowList: true, + Cache: iris.DirCacheOptions{ + Enable: true, + CompressIgnore: iris.MatchImagesAssets, + // Here, define the encodings that the cached files should be pre-compressed + // and served based on client's needs. + Encodings: []string{"gzip", "deflate", "br", "snappy"}, + CompressMinSize: 50, // files smaller than this size will NOT be compressed. + Verbose: 1, + }, +} + +func main() { + app := iris.New() + app.HandleDir("/public", AssetFile(), opts) + + // https://127.0.0.1/public + // https://127.0.0.1/public/app2 + // https://127.0.0.1/public/app2/app2app3 + // https://127.0.0.1/public/app2/app2app3/dirs + app.Run(iris.TLS(":443", "../http2push/mycert.crt", "../http2push/mykey.key")) +} diff --git a/file-server/http2push-embedded/bindata.go b/file-server/http2push-embedded/bindata.go new file mode 100644 index 00000000..dbea0bd3 --- /dev/null +++ b/file-server/http2push-embedded/bindata.go @@ -0,0 +1,581 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// ../http2push/assets/app2/app2app3/css/main.css +// ../http2push/assets/app2/app2app3/dirs/dir1/text.txt +// ../http2push/assets/app2/app2app3/dirs/dir2/text.txt +// ../http2push/assets/app2/app2app3/dirs/text.txt +// ../http2push/assets/app2/app2app3/index.html +// ../http2push/assets/app2/index.html +// ../http2push/assets/app2/mydir/text.txt +// ../http2push/assets/css/main.css +// ../http2push/assets/favicon.ico +// ../http2push/assets/index.html +// ../http2push/assets/js/main.js +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data, name string) ([]byte, error) { + gz, err := gzip.NewReader(strings.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _app2App2app3CssMainCss = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x29\x4d\xb5\xe6\xe5\xaa\x05\x04\x00\x00\xff\xff\x52\xd7\xbb\x8b\x26\x00\x00\x00" + +func app2App2app3CssMainCssBytes() ([]byte, error) { + return bindataRead( + _app2App2app3CssMainCss, + "app2/app2app3/css/main.css", + ) +} + +func app2App2app3CssMainCss() (*asset, error) { + bytes, err := app2App2app3CssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/css/main.css", size: 38, mode: os.FileMode(438), modTime: time.Unix(1595043712, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsDir1TextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\x20\xc2\x50\xbf\x24\xb5\xa2\x44\xaf\xa4\xa2\x04\x10\x00\x00\xff\xff\x87\xaf\x9d\x00\x20\x00\x00\x00" + +func app2App2app3DirsDir1TextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsDir1TextTxt, + "app2/app2app3/dirs/dir1/text.txt", + ) +} + +func app2App2app3DirsDir1TextTxt() (*asset, error) { + bytes, err := app2App2app3DirsDir1TextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/dir1/text.txt", size: 32, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsDir2TextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\x20\xc2\x48\xbf\x24\xb5\xa2\x44\xaf\xa4\xa2\x04\x10\x00\x00\xff\xff\x84\x14\xaa\xeb\x20\x00\x00\x00" + +func app2App2app3DirsDir2TextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsDir2TextTxt, + "app2/app2app3/dirs/dir2/text.txt", + ) +} + +func app2App2app3DirsDir2TextTxt() (*asset, error) { + bytes, err := app2App2app3DirsDir2TextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/dir2/text.txt", size: 32, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3DirsTextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\x2c\x28\x30\xd2\x07\x11\x89\x05\x05\xc6\xfa\x29\x99\x45\xc5\xfa\x25\xa9\x15\x25\x7a\x25\x15\x25\x80\x00\x00\x00\xff\xff\x64\xfe\x96\xd6\x1b\x00\x00\x00" + +func app2App2app3DirsTextTxtBytes() ([]byte, error) { + return bindataRead( + _app2App2app3DirsTextTxt, + "app2/app2app3/dirs/text.txt", + ) +} + +func app2App2app3DirsTextTxt() (*asset, error) { + bytes, err := app2App2app3DirsTextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/dirs/text.txt", size: 27, mode: os.FileMode(438), modTime: time.Unix(1594843207, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2App2app3IndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\x3f\x4f\xc3\x40\x0c\xc5\xf7\x48\xf9\x0e\xc6\x33\xed\x91\x76\x61\xb8\x8b\x54\xf1\x47\x6c\x30\x94\x81\xf1\x7a\x31\x9c\x85\x73\x39\xe5\x4c\x4b\xbf\x3d\x4a\x68\x90\x58\x6c\x3d\xfb\xbd\x9f\x64\xdb\xab\xfb\xe7\xbb\xfd\xdb\xcb\x03\x44\xed\xa5\xad\x2b\x3b\x75\x10\x9f\x3e\x1c\x52\xc2\xb6\xae\xa6\x19\xf9\xae\xad\x2b\x00\x00\xdb\x93\x7a\x08\xd1\x8f\x85\xd4\xe1\xeb\xfe\x71\x75\x8b\xff\x76\xc9\xf7\xe4\xf0\xc8\x74\xca\xc3\xa8\x08\x61\x48\x4a\x49\x1d\x9e\xb8\xd3\xe8\x3a\x3a\x72\xa0\xd5\x2c\xae\x81\x13\x2b\x7b\x59\x95\xe0\x85\x5c\xb3\xbe\xf9\x63\x09\xa7\x4f\x18\x49\x1c\x16\x3d\x0b\x95\x48\xa4\x08\x71\xa4\x77\x87\x26\x7f\x1d\x84\x83\xf1\x39\x6f\xe6\xe2\x73\xde\x9a\x50\x8a\xe9\x3d\xa7\x75\x28\x05\xc1\x2c\x20\x65\x15\x6a\x77\x39\x6f\x76\x39\x6f\xad\xf9\xd5\x75\x65\xcd\xe5\xac\xba\xb2\x87\xa1\x3b\x2f\xfe\xd8\xb4\x4f\x24\x32\xc0\x12\x01\x4e\x1d\x7d\x5b\x13\x9b\x39\x75\xf1\xce\x80\xe9\x67\x3f\x01\x00\x00\xff\xff\xef\x25\x54\xc8\x43\x01\x00\x00" + +func app2App2app3IndexHtmlBytes() ([]byte, error) { + return bindataRead( + _app2App2app3IndexHtml, + "app2/app2app3/index.html", + ) +} + +func app2App2app3IndexHtml() (*asset, error) { + bytes, err := app2App2app3IndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/app2app3/index.html", size: 323, mode: os.FileMode(438), modTime: time.Unix(1595043725, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2IndexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb4\xf3\x48\xcd\xc9\xc9\x57\x70\x2c\x28\x30\x52\xc8\xcc\x4b\x49\xad\xb0\xd1\xcf\x30\xb4\x03\x04\x00\x00\xff\xff\x75\x17\xab\xfa\x19\x00\x00\x00" + +func app2IndexHtmlBytes() ([]byte, error) { + return bindataRead( + _app2IndexHtml, + "app2/index.html", + ) +} + +func app2IndexHtml() (*asset, error) { + bytes, err := app2IndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/index.html", size: 25, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _app2MydirTextTxt = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xca\x2a\x2d\x2e\x51\x48\x54\x28\x49\xad\x28\xd1\x03\x04\x00\x00\xff\xff\x2f\xf9\x22\x98\x0c\x00\x00\x00" + +func app2MydirTextTxtBytes() ([]byte, error) { + return bindataRead( + _app2MydirTextTxt, + "app2/mydir/text.txt", + ) +} + +func app2MydirTextTxt() (*asset, error) { + bytes, err := app2MydirTextTxtBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "app2/mydir/text.txt", size: 12, mode: os.FileMode(438), modTime: time.Unix(1594787248, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _cssMainCss = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00" + +func cssMainCssBytes() ([]byte, error) { + return bindataRead( + _cssMainCss, + "css/main.css", + ) +} + +func cssMainCss() (*asset, error) { + bytes, err := cssMainCssBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _faviconIco = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x0b\x70\x55\xc7\x79\xde\x7b\xce\x45\x12\xb2\x90\xc4\xc3\xe6\x61\x3b\x90\xf8\x31\xc4\x19\x6c\x32\xe3\xc4\x34\xe3\xc6\x34\x6d\xed\xd4\x69\x62\x32\x49\x9a\xa6\x75\xea\x36\x33\xee\xd8\x9e\xb4\x75\xdc\x7a\xa6\xc5\x31\x02\xa6\xd3\x84\x47\x28\x6f\x3b\xc6\x3c\xcc\xeb\x9e\xbd\x08\x21\x04\x92\x28\x12\x0e\x08\x5b\x3c\xec\x02\x92\x78\x08\x21\x09\x41\x25\x24\x10\xe8\x71\xb5\xe7\xdc\xd7\xb9\xf7\xef\xfc\xff\x9e\x73\x74\x25\xdd\x97\x24\x82\x33\x1e\xce\xcc\x3f\x7b\xee\x9e\xdd\xff\xff\xf6\xdf\x7f\xff\xfd\xf7\xdf\xcb\x98\x8b\xa9\x2c\x3f\x1f\xcb\x19\xec\x15\x37\x63\x5f\x67\x8c\xcd\x98\x21\x7f\x6b\xf9\x8c\x6d\x72\x33\x36\x7b\xb6\xf5\xfb\x11\xc6\x9e\xbd\x97\xb1\x99\x8c\xb1\x7c\x6c\xc7\x64\x3d\x3d\x6e\x76\xdb\x1f\xe1\x75\xab\x42\x53\x7e\x22\x3c\x6c\x91\xf0\xb0\x02\x22\xae\x14\x08\x8f\xab\x40\xec\x64\x92\xf0\x5d\x53\xfe\x59\xec\x64\x5f\x15\x1e\xa6\x08\x4f\x7f\x7f\xdf\x7a\x96\xa1\x97\x3c\xb8\x3f\x78\xfa\x0d\x08\x9e\x5d\x08\xc1\xda\x5f\x82\x51\xf6\x65\x30\xca\x67\x41\xf0\xcc\xbf\x11\x19\x07\x1e\x07\xbd\x78\x2a\x18\x65\x8f\xb5\x0b\x4d\x7d\xad\x6f\x07\x73\x0b\xcd\x45\xfd\xbb\x17\xb3\x0c\xa3\x62\xce\xfe\xa8\xd1\x0a\xf8\x98\x6d\x25\x10\x38\xfe\x53\x88\xdc\x3a\x01\x66\x6b\x11\x11\xbe\x07\x8e\xfd\x2d\x84\x2e\x2c\x05\xff\xd1\x79\x3d\xc2\xc3\x7e\x20\x78\x06\x13\x5c\x89\xe9\xdf\x06\xd1\x50\x2f\x04\x4e\xfc\x0c\xcc\x6b\xa5\x60\x1c\xfd\x21\x74\x6c\x1e\x47\x84\xef\x58\x17\xf8\xe4\x65\x30\x6f\x54\x81\x71\xe0\x89\xea\xbe\x2d\x6c\xd2\x80\xfe\xfe\x76\x30\x6f\x1c\x81\x60\xed\x7c\x08\x9e\x5d\x0c\x2d\xeb\xc7\x41\xed\xd2\x29\x50\xbb\x74\x32\xbd\x63\x1d\x7e\xc3\x36\xa1\x73\xff\x19\x14\x1e\x36\x4f\x78\xc7\xc4\xf4\xef\x80\x70\xd3\xfb\x10\x6e\x5c\x0f\xdd\x65\x73\xe1\xdc\xf2\x89\xd0\xb1\x25\x0f\x6e\x7c\x90\x07\xe7\x7f\x33\x81\xea\xf0\x5b\xb8\x79\x13\x61\xd0\x8b\xa7\x2c\x09\x7c\xfc\x57\xac\x7b\x11\xf6\x7f\x6a\x5f\xd4\xb8\x06\xa1\xfa\x15\x10\x6e\x7a\x0f\x3a\xb4\xc7\xa0\x61\x55\x3e\x04\x8f\xfc\x39\x84\x3e\xfa\x4b\x68\x5c\x93\x4f\x75\xf8\x2d\x74\x71\x05\x44\x45\x13\xea\x54\xeb\x7c\x85\xa9\x48\xf8\x1e\x15\xcd\xf4\xcd\xee\x7f\x71\x65\x3e\x04\x3e\x7c\x86\x78\x5c\x5a\x1d\xd3\xbf\x7e\x05\xa0\x2c\x94\x89\xb2\x03\xd5\x3f\x66\x88\x05\x31\x21\x36\x1b\xff\xd9\xe5\x13\xe1\xda\xc6\x5c\x68\xdf\x94\x4b\x63\x71\xf0\x37\xbd\x0f\x38\x56\x1c\x33\x8e\x1d\x75\x80\xba\x40\x9d\x0c\xd6\x5f\xcd\x92\x29\x44\x83\xf5\x87\xba\x76\xfa\x73\x85\xe1\x5c\x18\x07\x9e\x38\x86\x18\x68\x8e\xac\xf9\xbb\xbe\x39\x87\xc8\x99\xbf\x13\x3f\xa3\x39\xc6\xb9\x8e\xed\x4f\xb6\xe0\x61\x3f\x40\xdb\x40\x1b\x41\x5b\x19\x62\x3f\xc7\x7f\x4a\xb6\x85\x0f\xda\x9a\xdd\x9f\xd6\x80\xe6\x62\xd2\x26\xd5\xd7\xd0\x46\xc9\x56\x0f\x3c\xde\x6f\xbf\xe5\xb3\xc8\xa6\xd1\xb6\xc9\xc6\x4f\xbf\x01\x68\xf3\x68\xfb\xce\x3a\xf2\x30\x26\x76\x32\x85\xd6\x08\xae\x95\xc1\xeb\x87\xd6\x14\xb3\x69\x11\xad\x39\xaf\x5b\x1d\xed\xfa\x05\x60\x8c\x65\x32\xc6\x54\x8b\x5c\x31\x64\x3d\x0b\x63\xe8\xb0\x45\x2d\x56\xdf\x99\x96\x8f\x99\x1b\xeb\x67\xf2\x47\x8b\xea\xf3\xf9\x08\xae\x22\xe5\x09\xae\x4e\x17\x5c\xfd\xc2\x28\x69\x8a\xe0\xca\x58\xb4\x3d\xdb\x17\xa6\x29\xff\x5f\x04\x57\x5b\x85\xe6\xba\x92\x90\xb8\x1a\x43\x4a\x4c\xbd\x62\xd7\xb7\x08\xae\xd6\x0b\xae\xfe\x8f\xe0\xea\x9b\x38\x1e\x1f\x1f\x4b\xfe\x34\xb5\x7c\xa5\x40\xec\xca\x02\xbd\x64\x3a\xe8\xfb\xbe\x38\x94\x4a\xa6\x83\xf0\x66\x82\xd0\x14\x10\x9a\x0b\x44\xe1\x38\x5c\x2b\x44\xf8\x4e\x75\x5c\x01\xe1\x75\x03\xf2\x11\x9a\x2b\x2a\xb8\x52\x2b\xb8\x3a\x4f\x68\x8a\x92\x0c\x03\xc9\xf7\xb0\x02\xa3\xfc\x2b\x10\xe9\xae\x85\xa8\x7e\x15\xa2\xfa\x95\x18\xba\x0a\xa1\xb3\x8b\x49\xbe\xbe\xe7\x5e\x08\xfe\xef\x3f\x81\xd9\x51\x09\x91\xbe\x4b\x44\xf8\x8e\x75\xf8\x4d\x70\x37\x04\x3e\xfe\x11\xf9\x14\xbd\x68\x3c\xe2\xe8\x14\x5c\x7d\x49\x78\x99\x2b\x11\x06\x47\xfe\x81\xd9\x10\x0d\xde\x82\xc1\x8f\x79\xe3\x30\xe8\x7b\xa7\x81\x51\xfa\x28\x98\xd7\xca\x00\xa2\xa6\xfc\x80\x65\xcc\x3b\x7e\xc3\x36\xfa\xde\x07\x08\x93\xd9\x5a\x0c\xfa\xfe\x87\x41\x68\xac\x43\x70\xf5\x59\x92\xe3\x1d\xea\x1a\x92\xc9\x8f\x06\x3a\xc1\xff\xe1\x5c\xda\x67\x91\x27\x3e\x91\xde\x0b\xe4\xaf\xfc\x47\x5f\x20\xc2\x77\xac\x23\xac\x1d\x95\xd4\xd6\xff\xe1\x9f\x10\x2f\xfa\x5d\xf2\x05\xc4\x70\x4c\x70\xf5\x7e\x94\x35\x1c\xf9\xa1\xc6\x77\x68\x3e\x43\x17\x57\x4a\xfe\xe8\xc3\xcb\xbe\x8c\xfc\xa0\xcf\x23\x09\xdf\xb1\x0e\xbf\x51\x9f\x8b\x2b\x65\x9f\xc6\x77\xe8\x37\xee\x4f\x62\xd7\x58\xb4\x8f\x05\x3e\x9e\x35\xc4\x1e\x13\xc9\x8f\x06\xbb\xc0\xa8\xfc\x23\xf0\x1f\xfa\x63\x88\x86\xba\x21\x72\xeb\x24\x18\xfb\x1f\x82\xde\x1d\x2e\x68\xdd\x30\x0e\x1a\x56\x4f\x24\xc2\x77\xac\xc3\x6f\xd8\x06\xdb\x62\x1f\xec\x8b\xef\x10\xd6\xc1\xff\xd1\xf7\x11\x67\x83\xe0\xea\x97\x06\xeb\x20\x91\x7c\xd2\xdd\xee\x3c\x08\x37\x6f\x04\x30\x0d\x08\x7c\x34\x8f\xe4\x34\xae\x99\x00\xa7\x7f\x3d\x0d\x4e\xfd\xea\x7e\x22\x7c\xc7\x3a\xfc\x86\x6d\xb0\x6d\xb8\x69\x23\xf5\xb5\xe7\xcc\x6c\x3f\x00\x62\x77\x6e\x54\x68\xae\x57\xad\xf5\x96\x52\x7e\xb0\x6e\x01\xe8\xfb\x66\xd0\x1a\x30\xaf\x95\x83\x28\xcc\x81\x2b\xef\xe6\x92\x3c\x24\x8a\x63\x96\x4d\x71\x7e\xe3\x37\x6c\x83\x6d\xb1\x0f\xf6\x0d\xd6\x15\x48\x5d\x86\x7c\x64\x47\xc2\xc3\xf6\x0a\xae\x66\xc6\xea\x20\xae\xfc\x48\x08\xfc\x55\xdf\x05\x7f\xd5\x77\x00\x22\x41\x08\x7e\xfa\x2a\x74\x6d\x53\xa1\x6e\xf9\x64\x92\x75\x69\xcd\x44\xb8\xb9\x35\x13\x6e\x6d\xcb\x80\xe6\x75\xe3\xa9\x0e\xbf\x61\x1b\x6c\x8b\x7d\xb0\xaf\xbf\xea\x7b\xc4\x8b\xec\xe2\xec\x22\x9c\x83\x66\xc1\xd5\x19\xa9\xe4\xd3\xdc\x1f\x98\x0d\xc1\x33\x6f\x42\x34\xec\x03\x7f\xe5\x1c\x68\xdb\x30\x96\xe4\x9c\xfb\xcd\x7d\xd0\xbd\x63\x0c\xe8\x85\x63\x41\x2f\xbc\x07\x7a\x3d\x6e\xa8\x5f\x39\x89\xbe\x61\x1b\x6c\x8b\x7d\xb0\xaf\xe4\xd9\x65\xd9\x6e\x19\x88\x5d\xd9\xba\xd0\x5c\x73\x53\xca\xd7\xff\x0f\xf4\xfd\x0f\x41\xa8\x61\x35\xf9\x1f\x7d\xdf\x74\x68\x5e\x97\x47\xf3\xdd\xf2\x4e\x1e\xc9\x0d\x9f\xfc\x3b\x30\x4f\xbd\x02\xc6\x9e\x09\xd0\xba\x21\x07\x4e\xfd\x6a\x1a\xb5\xc1\xb6\xe4\xb3\x1a\x56\x13\x0f\xe4\x25\xd7\xed\x39\x5c\x9b\x51\xa1\xb1\x17\xe3\xc8\x7f\x0b\x63\x13\x5c\xef\xd4\xb6\xaf\x91\x7c\x6b\xf8\xf2\x16\x5a\xdb\x62\xcf\x64\xb8\xb4\x7a\x3c\xc9\x68\xdb\x90\x0d\xfe\xb2\x87\x01\x2e\x2d\x07\x68\x5a\x05\x81\xca\x27\xe1\xfa\xe6\x4c\x39\x2f\xab\xc7\x53\xdb\x88\xaf\x9e\xfa\x22\x0f\xe4\xe5\xc4\x47\xa5\x8f\xa2\x0d\xfc\x22\x8e\xfc\x5f\xe0\x37\x3b\x5e\x4f\x2e\xff\x1e\xf0\x97\x7e\x11\xa2\x0d\x4b\x00\x9a\x56\x42\xe0\xe0\x13\x70\x7d\x53\x56\x6a\xf9\x81\x4e\x8a\xbf\x70\xac\x43\xe4\x6b\xec\x45\xd4\x0d\xea\x28\xbe\xfe\x67\x38\xfa\x6f\x5e\x97\x2f\xfd\xcb\xd1\xe7\x21\x74\xec\x87\xa0\xef\xce\x81\xab\xbf\x1d\x67\x7d\xcb\xb3\xd6\xcc\x50\xfd\xe3\xdc\xe2\x1c\xcb\xb3\xd0\x60\xf9\xae\xb9\x68\x1b\xe4\xdf\x53\xd8\x1f\xda\x39\xda\xbe\xee\x55\x41\xf7\xba\xc9\x16\xcf\xaf\xb8\x2f\xa5\xfd\x25\x95\x8f\x6b\x42\x63\xcd\xb8\xcf\x25\x5c\x7f\x5b\xe5\xfa\xc3\x39\xb8\xf0\xdf\xf7\x42\xfb\xc6\x7b\xa0\x63\x53\x36\x5c\x5c\x35\x29\xad\xf5\x97\x42\x7e\x26\xfa\x06\xda\x37\xc2\xbe\xb4\xfc\x0f\xd2\x99\x25\xd3\xd2\xf2\x3f\xc9\xe5\x2b\xf6\x1c\xbc\x86\x3e\x12\x7d\xe5\x50\xff\xeb\x8f\xe3\x7f\x25\x0d\xf5\xbf\xfe\x21\xfe\x37\x99\xfc\x18\x1d\x7c\x09\xf7\x08\xdc\x2b\xc0\xd4\x69\xef\x30\x2a\x46\xb9\xff\x58\x73\x9f\x5a\xbe\xc2\x7c\x1a\xed\x8d\x0b\x70\xaf\xc4\x3d\x53\xee\xbf\xef\x8e\x7a\xff\x4d\x47\x7e\x8c\x0e\xee\xc7\x58\x01\x63\x06\xd4\x1d\xf6\x41\x9b\x18\x51\xfc\x61\xf9\xb2\xb4\xe5\x7b\x55\x1b\xc3\xb3\x18\x33\x61\xec\x84\x31\x14\xf1\xdc\xfb\x40\x5a\xf1\x97\x4e\xf1\xd7\x34\x8a\xd9\x06\x3f\xa9\xe4\x3b\xb6\x48\xb1\xa2\xfa\x12\xc6\x8e\x18\x43\x62\x2c\x89\x31\x25\xc6\x96\x29\xe3\x4f\x6f\x26\xc5\xaa\xf1\x62\x58\x8c\x6d\x31\xc6\x4d\x26\xbf\x7f\x3d\x60\xcc\xac\xce\xa3\x18\x1a\x63\x69\x8c\xa9\xb9\x5b\xc6\xd8\x14\x7f\xe7\xc4\xc4\xdf\x39\xb2\x0e\x63\x73\x8c\x91\x93\xc5\xf0\xc4\x47\x49\x2a\x9f\x30\x68\x0a\xf3\x15\x65\x31\x6b\xaf\x7e\xd3\x3a\x53\xd4\x5b\x67\x8c\x44\xe7\x0f\x49\xc9\xcf\x30\xad\xd6\x59\x27\xa9\xfc\x58\x5d\xf4\x69\x14\x2f\x8d\x95\x67\xab\x51\x9f\xcf\xa6\x5b\x67\xbd\xb4\xe4\x7f\xde\x1f\x7b\x6d\x1c\x66\x2a\x1c\x66\x0c\xe9\x99\xc3\x8c\x4d\xb7\x28\xcf\xa2\x4c\x8b\xd4\x74\xa8\xc5\xa2\x1e\x8b\x02\x16\x99\x8c\xa9\xc0\x48\x90\x6a\xcb\x9d\xc9\x18\x9b\xcd\x18\xfb\xfb\xd8\x3c\xc5\xc3\x9f\xb5\x56\xee\x3e\x77\x9f\x3f\xcc\xc7\xda\x1f\x1f\x16\x5c\x7d\x5b\x70\x75\xa1\xe0\x6a\xc1\xef\x89\x6c\xde\xff\x2a\xb8\xfa\x37\x82\x2b\xb3\x05\x57\x72\x7a\x35\xc6\x0c\x2d\x79\x3e\x29\x0d\xfc\xdf\x16\x5c\x0d\x0a\xae\xc2\x1d\x22\x53\x70\xb5\x53\x70\xf5\x20\xed\xeb\x5c\xc9\xc7\x58\xc3\x48\x33\x3f\x97\x18\xbf\x42\xb1\x57\x5a\x84\x6d\x07\x60\x4a\xd2\x37\x6e\x5b\x97\xfd\x1b\xf5\x56\x2a\xb8\xfa\x24\xec\x67\x4c\xe7\xc3\x1b\x83\x83\x5f\x73\x05\x31\xc6\x0b\xd6\xbe\x45\xe7\xf2\x64\x14\x3c\xbb\x08\x8c\x8a\xa7\xfa\x71\x21\xc6\xc2\x1c\x30\x0e\x7e\x0d\x02\x27\xfe\x81\x78\x20\xe1\x3b\xd6\xc9\x78\x84\x39\xd8\xf5\xe2\x29\x60\x94\xcd\x04\xe1\xcd\x8a\x1d\x47\xa3\xe0\xea\x0b\x7e\xce\x5c\x7a\x8a\xfc\x64\x7c\xfc\x2c\x48\xf1\x75\xb8\x6f\x48\x9c\x37\xf8\x31\xdb\x4a\x64\x9c\x84\xb2\xbd\x19\xe0\x3f\xf2\x17\x60\xb6\xee\x85\x68\xe0\x26\x40\x34\x12\x13\x20\x46\xa8\x0e\xbf\x61\x1b\x6c\x8b\x7d\xf4\xe2\xc9\x10\x6a\x58\x0b\xe1\xcb\x5b\xc1\xa8\xfc\x46\xff\x9c\x70\xb5\x0d\xc7\xd0\xa3\x65\x33\x91\xe6\x3c\x0c\x17\x7f\xa4\xeb\x14\xc5\xb4\xc2\xc3\xe8\x3c\x43\xb1\x65\xb0\x3b\xe5\x98\xb1\x0d\xb6\xc5\x3e\xf2\x7c\x30\x13\x22\xdd\x35\x10\xf5\x5f\xa7\x73\xa9\x28\xbc\xc7\x1e\x43\x93\xe0\xca\x53\x14\x73\x16\xa6\x8e\x89\x86\x83\x9f\xce\x41\x55\xdf\x23\xec\x62\x77\x2e\x9d\xc7\xed\xb3\xa8\x1c\x5c\x10\xa2\xa2\x05\x22\xb7\x3e\x21\xc2\x77\xac\xeb\xff\x1e\xa2\x3e\xd8\x17\x79\x20\xaf\x68\xa8\x87\xda\x84\xea\x97\xcb\xbc\xb3\x1c\x43\xa5\xe0\xea\xe4\x74\x62\xba\xe1\xe0\x0f\x35\xac\x91\x36\xc0\xdd\x10\xac\x7b\xbb\x1f\x7b\x34\x0c\x66\x47\x05\xdd\x3d\xe9\xa5\x8f\x80\x5e\x34\x51\x52\xe9\x23\xf2\x3e\xaa\xa3\x82\xda\xd8\x63\x08\xd6\xfe\x52\xc6\xee\xde\x0c\xe2\x69\x8f\x1d\xcf\x4d\x92\xbf\x1a\x45\x7f\xeb\xf3\x32\x57\x5f\x0a\x3b\x4a\x17\x3f\xea\xd2\x28\x9f\x25\xf5\x76\xe4\x3b\xfd\x79\xad\x70\x1f\x84\xce\xff\x17\xe8\x7b\x26\x59\xfe\xc6\xca\xdb\xdb\x3e\x46\x63\xf4\x0d\xdb\xd8\xbc\xe9\x0c\x78\xe4\x79\xe2\x85\x3c\x69\x9e\x68\x7e\x7b\x21\x50\xfd\x63\x7b\x4d\x5f\x13\x5c\xfd\x7a\xca\x73\x45\x9a\xf8\x69\x7e\xad\xb5\x67\xde\xa8\xea\xd7\x59\xdd\x02\x79\x0f\xc1\xa5\x1f\xe9\xd9\x39\x06\x6e\x6e\xcd\x22\xc2\x77\xb9\x36\x5d\xd4\x06\xdb\xda\xf6\x64\xde\x38\x42\xbc\x90\x27\xf2\x76\x4c\xac\xbb\x86\x72\x44\xd6\x18\xde\xd3\xb9\xcb\x9d\xcc\x1f\xa5\x83\x9f\xf2\x5c\x15\x73\x48\x5f\x81\x4f\x5f\x75\xce\xa8\xe1\xcb\x5b\x1c\x9b\x45\xac\x57\xde\xcd\xa3\x5c\x66\xcd\xd2\x29\x44\xf8\x8e\x75\x72\x1c\x0a\xb5\xc5\x3e\x92\xa9\x49\xbc\x68\x0e\x2a\xe6\x0c\x38\x5b\x87\x2e\x2c\xb1\xce\x86\x6a\xbb\xe0\xea\x57\x93\x9f\x2d\x53\xe3\xa7\x5c\xcf\xae\x6c\xb2\x03\xb3\xb3\x5a\xea\xa9\xaf\x51\x9e\x5d\x35\x06\xdd\xdb\x33\x9c\x9c\x53\x3c\xc2\x6f\xd8\x86\xfc\x4e\xf9\x57\x9c\xfc\x9f\xd9\xf9\xb1\xb4\xbb\xc2\x6c\x30\xdb\xcb\xfb\xf5\xa5\x5f\x95\x79\x41\xb9\x67\x2c\x12\xdc\x9d\xf0\xce\x2a\x1d\xfc\xe4\xdf\xc8\x5f\x7c\x97\x72\xf1\x54\x57\xf3\xef\x64\x17\xbd\x1e\x37\xe5\x6c\x12\x61\xb7\x09\xdb\x60\x5b\xec\x83\x7d\xe5\x00\x0c\xe2\x89\xbc\x51\xc6\x00\x99\x75\x0b\x6d\x1b\x3a\x2e\xb8\x32\x61\xa4\xf8\xf1\x37\xe5\xe9\x35\x06\xa1\x86\x55\x96\x7e\x5a\xc0\x28\x9d\x49\x75\xad\xef\x8d\x1b\x82\xb5\x76\xd9\xc0\x7b\x00\x9b\xb0\xad\xed\xfb\xa3\xfa\x15\x69\x2b\x17\x57\x51\x1d\xca\x88\x95\x8d\xfe\x57\xde\x9f\x29\x3e\xc1\xd5\x6f\x26\xce\x8f\x24\xc7\x1f\xf1\x35\x80\x5e\xf2\x00\xe8\xbb\xf3\x21\x72\xf3\x98\x65\xf7\x1f\x80\xf0\x8e\x81\x9e\x1d\x63\xc8\xc6\x6d\x7c\x35\x4b\xa7\x92\xbd\xdf\xda\x96\x09\x5d\xdb\x33\xa1\x6d\x43\x8e\x73\xbf\x60\xe7\xf9\xb1\x0f\xfa\x48\xdc\x7b\x89\xff\xcd\x6a\xe2\x4d\x79\x65\x5f\xc3\x40\xbd\xfd\xee\x5b\xb6\x0d\x51\x7e\x3b\xde\x3a\x4e\x85\xdf\xec\x38\x44\xb6\x6f\x94\x3d\x46\xff\x67\xc0\x27\x70\xf2\x65\xe2\x7b\xed\xfd\x9c\x98\xbc\xe7\x54\xa9\x5f\x27\x16\x50\x40\xe7\x2a\x5c\xdf\x9c\x4d\xf7\x32\x76\x3b\xec\x83\x7d\x03\x9f\xfc\xa3\xc4\xe9\x6f\x27\xde\x28\x03\x65\x0d\xb0\xa1\x9a\xff\xb0\xf1\x6f\xd3\xb9\x2b\xee\x9d\x69\x2a\xfc\xa4\x6b\x9c\xdf\xc3\xcf\x01\x44\x02\x94\xcb\x35\x2a\x9f\xa6\xba\xa6\xb5\x13\x9c\x7c\x29\xae\x51\x9f\x47\xe6\x93\xf4\xc2\x6c\xd0\x77\x8f\x73\xe2\xcd\xcb\xeb\xf3\x9d\xfc\x2a\xf6\x21\x7e\x87\x9e\x96\x79\xe1\x48\x80\x78\x63\x1d\xca\x1a\x20\xfb\x2a\xb7\xf7\xb3\x6a\xc1\x95\xdc\x91\xe0\x0f\x5d\x58\x26\xfd\xe6\xf1\x97\xa4\xbe\xc4\x65\xca\x5d\xf5\xee\x54\x29\xe7\x6d\xeb\xb5\x0d\xf5\xca\x5d\x60\xec\x9d\x4a\x77\x30\x91\xda\x37\xc0\x5f\x3e\x93\xc6\xd3\xf9\xc1\x58\xb2\x2d\x3b\x4f\xee\xdb\xa9\x12\x0f\xe4\x45\xf3\x79\xfc\x25\x92\x81\xb2\x06\xd8\xee\xcd\x13\xf2\xce\x98\x2b\x4d\x82\xab\x0f\x26\xc9\x91\x3e\x97\x08\x3f\xed\x4f\x3b\x19\x04\x4f\xbd\x2e\x79\xf6\xd4\xd2\xbe\xd3\xbd\x7d\x0c\x9c\xb5\x6c\x1b\xb1\xe1\x7e\xa5\x7b\x55\x08\x1d\xfb\x11\x40\xf3\x5a\x22\xf3\xf4\xcf\x69\x2e\xd0\xff\xa3\xed\x23\x7e\xec\xd3\xbd\xdd\x4d\x31\x74\xa4\xa7\x4e\xca\x38\xf5\xba\x94\x81\xfb\x5b\xac\xef\x10\xcd\x74\xf7\x64\xdd\x79\xcf\x4a\x82\xff\x5b\x42\x63\x86\x71\xf0\xc9\x21\xb1\x24\xf9\x4e\xe4\x5d\x3b\xdf\xd2\xc9\x71\xd0\x8b\xf2\xa1\x6b\x5b\x86\xe3\x63\xb0\xec\xda\x9e\x41\xf7\x6f\x66\xcd\xeb\x00\xcd\x6b\x00\x9a\x56\x43\xb4\x7e\x31\x18\x7b\x27\x83\xcf\x23\xe7\x0a\xf1\x3b\x6d\x8b\xf2\xe9\xff\x3a\x24\xa3\x76\xbe\x94\x31\xc8\x87\x62\x6c\x4a\x31\x8b\xc6\xfa\x04\x57\x9f\x4e\x82\xff\x69\x6c\x43\xb1\x88\xff\xfa\xc8\xf0\x6f\xcb\x00\x7d\x57\x16\x98\x67\x7e\xde\x8f\xff\x42\x01\x18\xc5\x93\x08\xff\xf9\x91\xe0\x0f\x76\x03\xea\x14\x75\x4b\x3a\x4e\x8c\x7f\x16\xe5\x96\xf7\xcd\xa0\x39\x4b\x6e\x3f\x75\x34\xf7\x68\x03\xb6\xfd\xa0\xef\xb9\xb1\x85\xee\xd3\x21\x78\xe4\xcf\xe8\x0e\x10\xed\x27\x7c\xe2\x45\xd0\xbd\x19\xd0\xbd\x23\x83\xda\x0e\xdb\x7e\xc2\x7d\x74\x67\x81\xb6\x4d\x36\x9e\x18\xff\x83\xb8\x46\xf4\xa2\x09\x74\xdf\x31\x92\xf5\x7b\xf5\xb7\xb9\x96\xef\xc9\x81\x60\xd5\x73\x10\xaa\xfe\x3e\xe8\xc5\xf7\x82\xce\x15\xba\xd3\xc2\x31\x9e\xfa\xb5\xbd\x7e\x95\xb4\xd6\xef\x20\xfc\xdf\x8e\x8f\x9f\x72\xeb\xb9\xe4\xa3\x70\x5f\xb9\xca\x07\xf0\x48\xd7\x7f\x9e\x5b\x81\x7b\x53\x46\x7f\xec\x6c\x91\x4f\xeb\x8f\x2f\xb0\x6d\xe3\x30\xfc\x67\xba\xf8\xe5\xde\xa0\x6e\x47\x1e\xc1\x9a\xf9\x03\x78\xa4\xbb\x7f\x21\x35\xad\x1b\x0f\xbd\x9e\x31\xd6\x3d\xa6\x0a\x7d\x9a\x9b\xe6\x05\x75\x3f\x64\xff\x3a\xf9\xb2\xb5\x46\x13\xef\x5f\xe9\xe0\xd7\xed\xbb\x3e\xdc\xa3\x51\x2f\xbf\xfb\xd3\x81\x71\x48\xdc\xf8\x61\x6b\xdc\xf8\xc1\xde\xc7\x30\x6e\x40\x9c\xa8\xeb\x58\xec\xc3\x89\x1f\xd2\xc5\x1f\xb3\x06\xbe\x29\xb8\xd2\xa7\xef\xb9\x0f\x22\x5d\x9f\x0e\xe0\xe1\xc4\x6f\x17\xd3\x8b\xdf\x12\xd1\x70\xe2\xb7\xe1\xe1\xa7\x35\x30\x81\x62\x55\xcd\x45\xe7\xd0\xd8\xe7\xb3\x88\x9f\x87\x85\x5f\x53\x18\xfd\x3f\x95\xab\x8b\xe5\x19\xe3\x71\x3a\x43\x38\x6b\xe0\xf7\x76\x7e\xa9\x8e\x7b\x7e\x19\x2e\xfe\x18\x1b\xc2\xb3\x5a\x07\x9e\xdd\xf0\x0c\xe7\xf0\xb9\x23\xe7\xc7\x9b\xa3\xc4\x4f\x7e\xc8\x8d\x67\x66\x3a\xa7\xef\x7f\x88\xce\xd2\xf6\x93\xf6\xf9\x7d\x47\xcc\xf9\x7d\x47\xb2\xf3\x7b\x55\xdc\xf3\xfb\x48\xf1\xc7\xcc\xc1\xd7\x28\x77\x81\x3e\xae\xfa\xaf\x29\xa7\x01\x43\xf2\x27\xcf\x0f\xcc\x9f\x9c\xbb\x3d\xf9\x93\xd1\xe2\xef\xe3\x2e\xe6\xe3\x4c\x91\x67\x66\x35\x8a\x7e\x8e\xd6\xb2\xa5\xb3\xd4\xf9\xab\x17\xc1\x28\x7d\x04\xf4\x3d\x13\x89\x8c\x44\xf9\xab\xba\xb7\x87\xe6\xaf\x6e\x03\xfe\x98\x39\x98\x2c\xb8\x7a\xc8\xb6\xd9\x50\xfd\x32\x99\x1b\x0c\xf5\x38\xfe\xe2\xf6\xe5\x0f\x13\xe7\x4e\x47\x84\xbf\x50\xb5\xfd\xe9\x1c\x2b\x97\x4a\xb9\x55\xfa\xdf\x50\xe0\x3a\x44\xba\xcf\xc8\xdc\x37\xda\x8a\x9d\xbf\x4d\x82\xc1\xc1\x62\xe5\x6f\xb1\x0f\xe5\x7e\x4b\x1f\xa5\x5c\x70\xd2\x3e\x23\xc0\x4f\x63\xf0\xba\x58\x8f\x27\x1b\xe7\xe1\x05\x99\xd3\x56\x68\xbe\x8d\xca\x6f\xd0\xbe\x19\x6a\x58\xeb\xac\x3d\x27\x7f\xde\x56\x92\x7e\xfe\xbc\xe4\x41\x30\xdb\xf6\xa5\x1e\xf3\x08\xf1\xe3\xa3\x7b\x15\x66\xec\xa2\xff\x6d\xbc\x60\xdd\x2d\x48\xbc\xbb\xb2\xe8\xbf\x31\x7a\xf1\xd4\x24\xf7\x17\xf3\x89\x12\xdd\x5f\x18\x15\x4f\xd1\x1d\x48\xca\x7b\x92\xda\xb7\xac\xff\xda\xba\x86\x8d\x9f\xc6\xc0\x5d\x0c\xbc\xe4\x5b\xd1\x27\x95\x39\x77\x64\x8e\x8f\x19\xcd\xfd\xd1\xb0\xee\xa9\x46\x84\x1f\x1f\x43\x73\xd9\x6b\x7a\xbc\xbc\x6b\xa3\x3b\xb7\x4e\xeb\x0e\xee\x4e\xdd\xf7\x8d\x18\xbf\x33\x0e\x8f\xc2\x7a\x8b\x54\x8c\x35\x72\x04\x57\x67\x0b\xae\xfe\xc4\xba\x0b\x2d\xb8\x03\xf7\xae\x6f\x5b\x77\xbc\x23\xc6\x7f\xf7\xb9\xfb\x7c\x9e\x1e\xb9\x43\x24\x2e\x5b\x18\x63\xcf\x58\x65\x9e\x55\x66\x5a\xa5\x6b\x50\xc9\xec\xb2\xc0\x2a\x9f\x19\x54\x4e\x4f\x50\xe6\x25\x28\x33\x6f\x5f\xd9\x93\xa0\x0c\x24\x28\xcd\x41\x65\xd4\x2a\xc1\x2e\x17\x0e\x2a\x5b\xac\xb2\xc7\x2a\x4d\xab\x4c\xa1\xdf\xff\x0f\x00\x00\xff\xff\xc6\xb9\x24\x2f\xee\x3a\x00\x00" + +func faviconIcoBytes() ([]byte, error) { + return bindataRead( + _faviconIco, + "favicon.ico", + ) +} + +func faviconIco() (*asset, error) { + bytes, err := faviconIcoBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "favicon.ico", size: 15086, mode: os.FileMode(438), modTime: time.Unix(1565946440, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _indexHtml = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x91\x3d\x4f\xc3\x30\x10\x86\xf7\x48\xf9\x0f\xd7\x9b\x40\x22\x35\x6c\x0c\x71\x96\x42\x57\x90\x28\x03\xa3\xeb\x5c\x9b\x6b\x1d\x27\xb2\x2f\x69\xfb\xef\x51\x3e\xca\xe7\x64\xdf\xeb\xbb\xc7\x8f\xec\x7c\xf1\xf4\xb2\xda\x7c\xbc\x3e\x43\x25\xb5\x2b\xd2\x24\x1f\x56\x70\xc6\xef\x35\x92\xc7\x22\x4d\x86\x8c\x4c\x59\xa4\x09\x00\x40\x5e\x93\x18\xb0\x95\x09\x91\x44\xe3\xfb\x66\x9d\x3d\xe2\xaf\x33\x6f\x6a\xd2\xd8\x33\x9d\xda\x26\x08\x82\x6d\xbc\x90\x17\x8d\x27\x2e\xa5\xd2\x25\xf5\x6c\x29\x1b\x8b\x3b\x60\xcf\xc2\xc6\x65\xd1\x1a\x47\xfa\x61\x79\xff\xc5\x72\xec\x8f\x10\xc8\x69\x64\xdb\x78\x84\x2a\xd0\x4e\xa3\x6a\xbb\xad\x63\xab\x76\xa6\x1f\xe2\x25\xdb\x06\x41\x2e\x2d\x69\xe4\xda\xec\x49\x9d\xb3\xa9\x5d\xfd\xe7\x44\xb9\x38\x8a\x15\x91\xfc\xa5\xd9\x18\x55\x6d\xd8\x2f\x6d\x8c\x3f\x46\x85\xc5\x51\xb1\x66\x47\xf0\x46\xa1\xa7\x90\xab\x29\x4a\x93\x5c\xcd\x6f\x92\x26\xf9\xb6\x29\x2f\xd7\x11\xf6\x6d\x27\xb3\xd0\xb6\x13\x19\x54\x1a\x6f\x1d\xdb\xa3\xc6\xc6\xaf\x86\xcd\xcd\x2d\x42\x6f\x5c\x47\x1a\xc7\x1a\x6a\x5a\x4c\xb7\xce\x90\x68\x03\xb7\x57\x8a\xd0\x59\xd4\xc1\xf4\x66\x4a\x11\x62\xb0\xdf\xe6\x87\x59\xfc\x10\xb1\xc8\xd5\xd4\x32\xea\xcd\x52\xa3\xe9\xf0\xb3\x9f\x01\x00\x00\xff\xff\x00\xcf\x96\xa8\xe9\x01\x00\x00" + +func indexHtmlBytes() ([]byte, error) { + return bindataRead( + _indexHtml, + "index.html", + ) +} + +func indexHtml() (*asset, error) { + bytes, err := indexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "index.html", size: 489, mode: os.FileMode(438), modTime: time.Unix(1594886229, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _jsMainJs = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xce\xcf\x2b\xce\xcf\x49\xd5\xcb\xc9\x4f\xd7\x50\x4a\xad\x48\xcc\x2d\xc8\x49\x55\xd2\xb4\xe6\xe5\xe2\xe5\x4a\x2b\xcd\x4b\x2e\xc9\xcc\xcf\x53\xc8\xcf\x73\xce\xc9\x4c\xce\xd6\xd0\x54\xa8\xe6\xe5\x52\x50\x50\x50\x28\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2a\x2d\x29\xc9\xcf\x53\x48\x06\xa9\x49\x4d\x01\x6b\xae\x05\x04\x00\x00\xff\xff\xa4\xb7\x99\x52\x57\x00\x00\x00" + +func jsMainJsBytes() ([]byte, error) { + return bindataRead( + _jsMainJs, + "js/main.js", + ) +} + +func jsMainJs() (*asset, error) { + bytes, err := jsMainJsBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "js/main.js", size: 87, mode: os.FileMode(438), modTime: time.Unix(1594787764, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "app2/app2app3/css/main.css": app2App2app3CssMainCss, + "app2/app2app3/dirs/dir1/text.txt": app2App2app3DirsDir1TextTxt, + "app2/app2app3/dirs/dir2/text.txt": app2App2app3DirsDir2TextTxt, + "app2/app2app3/dirs/text.txt": app2App2app3DirsTextTxt, + "app2/app2app3/index.html": app2App2app3IndexHtml, + "app2/index.html": app2IndexHtml, + "app2/mydir/text.txt": app2MydirTextTxt, + "css/main.css": cssMainCss, + "favicon.ico": faviconIco, + "index.html": indexHtml, + "js/main.js": jsMainJs, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "app2": {nil, map[string]*bintree{ + "app2app3": {nil, map[string]*bintree{ + "css": {nil, map[string]*bintree{ + "main.css": {app2App2app3CssMainCss, map[string]*bintree{}}, + }}, + "dirs": {nil, map[string]*bintree{ + "dir1": {nil, map[string]*bintree{ + "text.txt": {app2App2app3DirsDir1TextTxt, map[string]*bintree{}}, + }}, + "dir2": {nil, map[string]*bintree{ + "text.txt": {app2App2app3DirsDir2TextTxt, map[string]*bintree{}}, + }}, + "text.txt": {app2App2app3DirsTextTxt, map[string]*bintree{}}, + }}, + "index.html": {app2App2app3IndexHtml, map[string]*bintree{}}, + }}, + "index.html": {app2IndexHtml, map[string]*bintree{}}, + "mydir": {nil, map[string]*bintree{ + "text.txt": {app2MydirTextTxt, map[string]*bintree{}}, + }}, + }}, + "css": {nil, map[string]*bintree{ + "main.css": {cssMainCss, map[string]*bintree{}}, + }}, + "favicon.ico": {faviconIco, map[string]*bintree{}}, + "index.html": {indexHtml, map[string]*bintree{}}, + "js": {nil, map[string]*bintree{ + "main.js": {jsMainJs, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/file-server/http2push-embedded/main.go b/file-server/http2push-embedded/main.go new file mode 100644 index 00000000..e8dfbbf9 --- /dev/null +++ b/file-server/http2push-embedded/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "regexp" + + "github.com/kataras/iris/v12" +) + +// How to run: +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latesta +// $ go-bindata -nomemcopy -fs -prefix "../http2push/assets" ../http2push/assets/... +// # OR if the ./assets directory was inside this example foder: +// # go-bindata -nomemcopy -refix "assets" ./assets/... +// +// $ go run . +// Physical files are not used, you can delete the "assets" folder and run the example. + +var opts = iris.DirOptions{ + IndexName: "index.html", + PushTargetsRegexp: map[string]*regexp.Regexp{ + "/": iris.MatchCommonAssets, + "/app2/app2app3": iris.MatchCommonAssets, + }, + Compress: false, + ShowList: true, +} + +func main() { + app := iris.New() + app.HandleDir("/public", AssetFile(), opts) + + // https://127.0.0.1/public + // https://127.0.0.1/public/app2 + // https://127.0.0.1/public/app2/app2app3 + // https://127.0.0.1/public/app2/app2app3/dirs + app.Run(iris.TLS(":443", "../http2push/mycert.crt", "../http2push/mykey.key")) +} diff --git a/file-server/http2push/assets/app2/app2app3/css/main.css b/file-server/http2push/assets/app2/app2app3/css/main.css new file mode 100644 index 00000000..d60afbdf --- /dev/null +++ b/file-server/http2push/assets/app2/app2app3/css/main.css @@ -0,0 +1,3 @@ +body { + background-color: blue; +} \ No newline at end of file diff --git a/file-server/http2push/assets/app2/app2app3/dirs/dir1/text.txt b/file-server/http2push/assets/app2/app2app3/dirs/dir1/text.txt new file mode 100644 index 00000000..fc7b9c64 --- /dev/null +++ b/file-server/http2push/assets/app2/app2app3/dirs/dir1/text.txt @@ -0,0 +1 @@ +app2/app2app3/dirs/dir1/text.txt \ No newline at end of file diff --git a/file-server/http2push/assets/app2/app2app3/dirs/dir2/text.txt b/file-server/http2push/assets/app2/app2app3/dirs/dir2/text.txt new file mode 100644 index 00000000..9fb3e047 --- /dev/null +++ b/file-server/http2push/assets/app2/app2app3/dirs/dir2/text.txt @@ -0,0 +1 @@ +app2/app2app3/dirs/dir2/text.txt \ No newline at end of file diff --git a/file-server/http2push/assets/app2/app2app3/dirs/text.txt b/file-server/http2push/assets/app2/app2app3/dirs/text.txt new file mode 100644 index 00000000..eaad5124 --- /dev/null +++ b/file-server/http2push/assets/app2/app2app3/dirs/text.txt @@ -0,0 +1 @@ +app2/app2app3/dirs/text.txt \ No newline at end of file diff --git a/file-server/http2push/assets/app2/app2app3/index.html b/file-server/http2push/assets/app2/app2app3/index.html new file mode 100644 index 00000000..ba5282d2 --- /dev/null +++ b/file-server/http2push/assets/app2/app2app3/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="/public/app2/app2app3/css/main.css" /> + <title>App2App3</title> +</head> + +<body> + <h1>Hello App2App3 index</h1> +</body> + +</html> \ No newline at end of file diff --git a/file-server/http2push/assets/app2/index.html b/file-server/http2push/assets/app2/index.html new file mode 100644 index 00000000..8193d822 --- /dev/null +++ b/file-server/http2push/assets/app2/index.html @@ -0,0 +1 @@ +<h1>Hello App2 index</h1> \ No newline at end of file diff --git a/file-server/http2push/assets/app2/mydir/text.txt b/file-server/http2push/assets/app2/mydir/text.txt new file mode 100644 index 00000000..f1cc1278 --- /dev/null +++ b/file-server/http2push/assets/app2/mydir/text.txt @@ -0,0 +1 @@ +just a text. \ No newline at end of file diff --git a/file-server/single-page-application/embedded-single-page-application/public/css/main.css b/file-server/http2push/assets/css/main.css similarity index 100% rename from file-server/single-page-application/embedded-single-page-application/public/css/main.css rename to file-server/http2push/assets/css/main.css diff --git a/subdomains/multi/public/upload_resources/favicon.ico b/file-server/http2push/assets/favicon.ico similarity index 100% rename from subdomains/multi/public/upload_resources/favicon.ico rename to file-server/http2push/assets/favicon.ico diff --git a/file-server/http2push/assets/index.html b/file-server/http2push/assets/index.html new file mode 100644 index 00000000..6e445135 --- /dev/null +++ b/file-server/http2push/assets/index.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="icon" href="/public/favicon.ico" type="image/x-icon" /> + <link rel="stylesheet" href="/public/css/main.css" /> + <title>File Server</title> +</head> + +<body> + <input type="button" onclick="onClick()" value="Click me!" /> + + <script type="text/javascript" src="/public/js/main.js"></script> +</body> + +</html> \ No newline at end of file diff --git a/file-server/http2push/assets/js/main.js b/file-server/http2push/assets/js/main.js new file mode 100644 index 00000000..f97190ca --- /dev/null +++ b/file-server/http2push/assets/js/main.js @@ -0,0 +1,5 @@ +console.log("example"); + +function onClick() { + window.alert("button clicked"); +} \ No newline at end of file diff --git a/file-server/http2push/main.go b/file-server/http2push/main.go new file mode 100644 index 00000000..277c68f0 --- /dev/null +++ b/file-server/http2push/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "regexp" + + "github.com/kataras/iris/v12" +) + +var opts = iris.DirOptions{ + IndexName: "index.html", + // Optionally register files (map's values) to be served + // when a specific path (map's key WITHOUT prefix) is requested + // is fired before client asks (HTTP/2 Push). + // E.g. "/" (which serves the `IndexName` if not empty). + // + // Note: Requires running server under TLS, + // that's why we use `iris.TLS` below. + // PushTargets: map[string][]string{ + // "/": { // Relative path without prefix. + // "favicon.ico", + // "js/main.js", + // "css/main.css", + // // ^ Relative to the index, if need absolute ones start with a slash ('/'). + // }, + // }, + // OR use regexp: + PushTargetsRegexp: map[string]*regexp.Regexp{ + // Match all js, css and ico files + // from all files (recursively). + // "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$"), + // OR: + "/": iris.MatchCommonAssets, + "/app2/app2app3": iris.MatchCommonAssets, + }, + Compress: true, + ShowList: true, +} + +func main() { + app := iris.New() + app.HandleDir("/public", iris.Dir("./assets"), opts) + + // Open your browser's Network tools, + // navigate to https://127.0.0.1/public. + // you should see `Initiator` tab: "Push / public". + // + // https://127.0.0.1/public + // https://127.0.0.1/public/app2 + // https://127.0.0.1/public/app2/app2app3 + // https://127.0.0.1/public/app2/app2app3/dirs + app.Run(iris.TLS(":443", "mycert.crt", "mykey.key")) +} diff --git a/file-server/http2push/mycert.crt b/file-server/http2push/mycert.crt new file mode 100644 index 00000000..9db93b09 --- /dev/null +++ b/file-server/http2push/mycert.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUfwMd9auWixp19UnXOmyxJ9Jkv7IwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA2MjUwOTUxNDdaFw0yMTA2 +MjUwOTUxNDdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDlVGyGAQ9uyfNbwZyrtYOSjLpxf5NpNToh2OzU7gy2 +OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwje+IjGZBw8x6E+8WoGdSzbrEZ6pUV +wKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO888dwK/mbIHrHTq4nO3o0gAdAJwu +amn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA0AT8eg544GyCdyteAH11oCDsHS8/ +DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8eJohddRTK6zHe9ixZTt/soayOF7OS +QQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po6bqDnUzdnkqAAwwymQapHMuHXZKN +rhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt+0AidLRH+dCY7MS9Ngga/sAK3vID +gSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat4y0VwSyysUy887vHr6lMK5CrAT/l +Ch8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bVGYsEYrrW+bCNN9wCGYTZEyX++os9 +v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w3wPf9K4Y40MNxeR90nyX4zjXGF1/ +91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L2UBwMacsfjBbN4djOc5IuYMar/VN +GQIDAQABo1MwUTAdBgNVHQ4EFgQUtkf+yAvqgZC8f22iJny9hFEDolMwHwYDVR0j +BBgwFoAUtkf+yAvqgZC8f22iJny9hFEDolMwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAE2QasBVru618rxupyJgEHw6r4iv7sz1Afz3Q5qJ4oSA9 +xVsrVCjr3iHRFSw8Rf670E8Ffk/JjzS65mHw6zeZj/ANBKQWLjRlqzYXeetq5HzG +SIgaG7p1RFvvzz3+leFGzjinZ6sKbfB4OB72o2YN+fO8DsDxgGKll0W4KAazizSe +HY9Pgu437tWnwF16rFO3IL47n5HzYlRoGIPOpzFoNX5+fyn9GlnKEtONF2QBKTjY +rdjvqFRByDiC74d8z/Yx8IiDRn1mTcG90JLR9+c6M7fruha9Y/rJfw+4AhVh5ZDz +Bl9rGPjwEs5zwutYvVAJzs7AVcighYP1lHKoJ7DxBDQeyBsYlUNk2l6bmZgLgGUZ ++2OyWlqc/jD2GdDsIaZ4i7QqhTI/6aYZIf5zUkblKV1aMSaDulKxRv//OwW28Jax +9EEoV7VaFb3sOkB/tZGhusXeQVtdrhahT3KkZLNwmNXoXWKJ5LjeUlFWJyV6JbDe +y/PIWWCwWqyuFCSZS+Cg3RDgAzfSxkI8uVZ+IKKJS3UluDX45lxXtbRrvTQ+oDrA +6ga5c1Vz9C4kn1K5yW4d7QIvg6vPiy7gvl+//sz9oxUM3yswInDBY0HKLgT0Uq9b +YzLDh2RSaHsgHMPy2BKqR+q2N+lpg7inAWuJM1Huq6eHFqhiyQkzsfscBd1Dpm8= +-----END CERTIFICATE----- diff --git a/file-server/http2push/mykey.key b/file-server/http2push/mykey.key new file mode 100644 index 00000000..39f7b3af --- /dev/null +++ b/file-server/http2push/mykey.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDlVGyGAQ9uyfNb +wZyrtYOSjLpxf5NpNToh2OzU7gy2OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwj +e+IjGZBw8x6E+8WoGdSzbrEZ6pUVwKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO +888dwK/mbIHrHTq4nO3o0gAdAJwuamn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA +0AT8eg544GyCdyteAH11oCDsHS8/DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8e +JohddRTK6zHe9ixZTt/soayOF7OSQQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po +6bqDnUzdnkqAAwwymQapHMuHXZKNrhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt ++0AidLRH+dCY7MS9Ngga/sAK3vIDgSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat +4y0VwSyysUy887vHr6lMK5CrAT/lCh8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bV +GYsEYrrW+bCNN9wCGYTZEyX++os9v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w +3wPf9K4Y40MNxeR90nyX4zjXGF1/91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L +2UBwMacsfjBbN4djOc5IuYMar/VNGQIDAQABAoICAQCtWx1SSxjkcerxsLEDKApW +zOTfiUXgoOjZz0ZwS6b2VWDfyWAPU1r4ps39KaU+F+lzDhWjpYQqhbMjG7G9QMTs +bQvkEQLAaQ5duU5NPgQG1oCUsj8rMSBpGGz4jBnm834QHMk7VTjYYbKu3WTyo8cU +U2/+UDEkfxRlC+IkCmMFv1FxgMZ5PbktC/eDnYMhP2Pq7Q5ZWAVHymk9IMK0LHwm +Kdg842K4A3zTXwGkGwetDCMm+YQpG5TxqX/w82BRcCuTR5h8fnYSsWLEIvKwWyIl +ppcjaUnrFPG2yhxLqWUIKPpehuEjjhQMt9rDNoh6MHsJZZY5Dp5eq91EIvLoLQ99 +hXBmD4P8LDop4r0jniPZJi/ACsaD0jBooA4525+Kouq7RP28Jp/pek7lVOOcBgRv +D3zyESbKfqoaOfyfQ2ff4sILnTAr4V2nq3ekphGEYJrWN0ZoADcLdnr1cZ8L+VBI +o/4mi5/3HID/UEDliHSa97hxxGBEqTto0ZuXuNwfwx5ho33uVT6zNwRgiJ62Bgu3 +Fhk/wVGuZxWvb1KHUNInG9cvsslhO4Vu9wJvYj91BnRq36rsyKKid5DrU+PNgmog +lw3IXQpTojyRCYPuG9TKqEZ6b+so7GTKhBOjiwaupMOletVRGSAdbE81VN6HtxNW +aj39+FnxzMAlsieib+PBAQKCAQEA+t1fOYSaZBo7pZUmo2S0zulUEJjrYRGKJlWJ +4psWSwFu/7/3UL4q0RBQaSRew9u/YSpaNlBYfcpnFVOjiLwHq5Hx46Eq0BuKsNlJ +1/qxw9qjHqcrOre6K4/7NaWLPuM9fEmV+3MhFVXgv+WC5BHOowRTlOG30vIcC1J2 +L5xsBUsxDDY13cD1bLKRmFcyMFM8y7wMZmo7H/WfVmyoPKQaC43pTcmIXH0Jr2Ws +Wsfh18mhjtamaOPEFx5K0x4d0PI8tW5ouiUUkVIDaue27XfS969qEChv768/44eX +WeqcekaG9jv2noMClt79rYd3Lne9HkgY6IT9FT+JqXfu+KYwuQKCAQEA6gYzUsGB +9GQO8DE8AYn7JwNOtg1X4zKakXiGxH+nuZb7wJjAeGdYqTHySxPBXg0A2nDwoyz5 +4sAdLAr3FZoIvTzo7M5KIKFDzfyDmQDavhroH1mBAEiqKGNniP+RND3nWBBqDK1R +qcqbhI3Kj5Ycany6a4nP+hZRBIyT9sfJ0S0YruSY8IGXgDwhlJrZ7bsWMZylrgD/ +1qnPL0KqVBY8YR8msRj88h72IlD5o0kwvisOIvyhA0YgwGBb6lg7A+DifiF03ZlS +2yELbIkKDVr+p3jC7MBh4B+OJY68AMl6wVjAaDM1AZnpjKE5YmZg5+Ks5823zILo +PrSB9hn0+DIPYQKCAQEAh9x+JuNmzhHa/dkiHNl8hpadHYQD7gUWwZ4P1/bQAv0a +xU2MvmDPRXxFYDv/SqlnI1NRmhq3YiDM5SLv7SyQJt4al4IAcsaHvTFgqaSuw3hU +YVR9uAYqwE7w6OPn3r4o3Xfoz05Ru4FP//1nfucZ9vVv4rC/4nGWuJcHRM+9PLy1 +KnztfVR0VlL7QPrwRnW99kS4nnqn3K4khiTAlF73cAyCLsuXmydoqGIzDtMzv68G +XRpo82NvHmoccevcj/2w3T2XYECWvAEjsrEdQ8xiKBwLIAcWYEOUIUCcumiyKBKs +IwzkioI/U8AeuO0lobfdZ1n6i2sCuZA4mNxIQseWmQKCAQEA5YkfXdQeuq5JWJ1x +1bCYfjNoSHfd9CH2KSimRqVOxWGpm8Y3QeFbvNgYZjsCNlVauOZ9oA7FKfp0onY+ +0xk56SKM83eCjW6fKrK6AKAt7LhHZDhNpxGek+6r5luE+FCfUGkJG1YD+x2WW/UW +8K6zQF8GGeQZ8Zlh7axUlIBxGpG43BGrUHpLNqPD7BXWGq6dnhufBYRFay8y34/r +sH3+yuPa92ki7/geQppZwCZRgLSKMRbIdoWaKhZZEQlpGOzCOiRmk9OGyRcoNVRU +X7UYgPqZdc1cMo/AxGWzULJNjMaYMZvIKcHkqOKZfkIcWlSictn7pMPhN1+k+NWM +yMORAQKCAQAyXl02h/c2ihx6cjKlnNeDr2ZfzkoiAvFuKaoAR+KVvb9F9X7ZgKSi +wudZyelTglIVCYXeRmG09uX3rNGCzFrweRwgn6x/8DnN5pMRJVZOXFdgR+V9uKep +K6F7DYbPyggvLOAsezB+09i9lwxM+XdA2whVpL5NFR1rGfFglnE1EQHcEvNONkcv +0h8x9cNSptJyRDLiTIKI9EhonuzwzkGpvjULQE8MLbT8PbjoLFINcE9ZWhwtyw0V +XO32KE8iLKt3KzHz9CfTRCI3M7DwD752AC6zRr8ZS/HXzs+5WTkdVVEtRC7Abd3y +W2TzuSMYNDu876twbTVQJED3mwOAQ3J7 +-----END PRIVATE KEY----- diff --git a/file-server/send-files/files/first.zip b/file-server/send-files/files/first.zip index 431fa5fd..c98f5ac8 100644 Binary files a/file-server/send-files/files/first.zip and b/file-server/send-files/files/first.zip differ diff --git a/file-server/send-files/main.go b/file-server/send-files/main.go index ca3d5045..3e5c46a1 100644 --- a/file-server/send-files/main.go +++ b/file-server/send-files/main.go @@ -1,16 +1,31 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { app := iris.New() + app.Logger().SetLevel("debug") - app.Get("/", func(ctx iris.Context) { - file := "./files/first.zip" - ctx.SendFile(file, "c.zip") - }) + app.Get("/", download) + app.Get("/download", downloadWithRateLimit) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") +} + +func download(ctx iris.Context) { + src := "./files/first.zip" + ctx.SendFile(src, "client.zip") +} + +func downloadWithRateLimit(ctx iris.Context) { + // REPLACE THAT WITH A BIG LOCAL FILE OF YOUR OWN. + src := "./files/first.zip" + dest := "" /* optionally, keep it empty to resolve the filename based on the "src" */ + + // Limit download speed to ~50Kb/s with a burst of 100KB. + limit := 50.0 * iris.KB + burst := 100 * iris.KB + ctx.SendFileWithRate(src, dest, limit, burst) } diff --git a/file-server/single-page-application/basic/main.go b/file-server/single-page-application/basic/main.go index 649f7066..4ed60e4d 100644 --- a/file-server/single-page-application/basic/main.go +++ b/file-server/single-page-application/basic/main.go @@ -1,35 +1,15 @@ package main -import ( - "github.com/kataras/iris" -) - -// same as embedded-single-page-application but without go-bindata, the files are "physical" stored in the -// current system directory. - -var page = struct { - Title string -}{"Welcome"} +import "github.com/kataras/iris/v12" func newApp() *iris.Application { app := iris.New() - app.RegisterView(iris.HTML("./public", ".html")) - app.Get("/", func(ctx iris.Context) { - ctx.ViewData("Page", page) - ctx.View("index.html") + app.HandleDir("/", iris.Dir("./public"), iris.DirOptions{ + IndexName: "index.html", + SPA: true, }) - // or just serve index.html as it is: - // app.Get("/{f:path}", func(ctx iris.Context) { - // ctx.ServeFile("index.html", false) - // }) - - assetHandler := app.StaticHandler("./public", false, false) - // as an alternative of SPA you can take a look at the /routing/dynamic-path/root-wildcard - // example too - app.SPA(assetHandler) - return app } @@ -37,8 +17,7 @@ func main() { app := newApp() // http://localhost:8080 - // http://localhost:8080/index.html - // http://localhost:8080/app.js - // http://localhost:8080/css/main.css - app.Run(iris.Addr(":8080")) + // http://localhost:8080/about + // http://localhost:8080/a_notfound + app.Listen(":8080") } diff --git a/file-server/single-page-application/basic/main_test.go b/file-server/single-page-application/basic/main_test.go deleted file mode 100644 index 6e7b3410..00000000 --- a/file-server/single-page-application/basic/main_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "io/ioutil" - "path/filepath" - "strings" - "testing" - - "github.com/kataras/iris/httptest" -) - -type resource string - -func (r resource) String() string { - return string(r) -} - -func (r resource) strip(strip string) string { - s := r.String() - return strings.TrimPrefix(s, strip) -} - -func (r resource) loadFromBase(dir string) string { - filename := r.String() - - if filename == "/" { - filename = "/index.html" - } - - fullpath := filepath.Join(dir, filename) - - b, err := ioutil.ReadFile(fullpath) - if err != nil { - panic(fullpath + " failed with error: " + err.Error()) - } - - result := string(b) - - return result -} - -var urls = []resource{ - "/", - "/index.html", - "/app.js", - "/css/main.css", -} - -func TestSPA(t *testing.T) { - app := newApp() - e := httptest.New(t, app, httptest.Debug(false)) - - for _, u := range urls { - url := u.String() - contents := u.loadFromBase("./public") - contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1) - - e.GET(url).Expect(). - Status(httptest.StatusOK). - Body().Equal(contents) - } -} diff --git a/file-server/single-page-application/basic/public/index.html b/file-server/single-page-application/basic/public/index.html index 78f89888..68ed82d5 100644 --- a/file-server/single-page-application/basic/public/index.html +++ b/file-server/single-page-application/basic/public/index.html @@ -1,14 +1,19 @@ -<html> +<!DOCTYPE html> +<html lang="en"> <head> - <title>{{ .Page.Title }}</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Iris SPA Router Example</title> </head> <body> - <h1> Hello from index.html </h1> + <div id="app"> + </div> - <script src="/app.js"> </script> + <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> + <script src="./index.js"></script> </body> </html> \ No newline at end of file diff --git a/file-server/single-page-application/basic/public/index.js b/file-server/single-page-application/basic/public/index.js new file mode 100644 index 00000000..56e8229d --- /dev/null +++ b/file-server/single-page-application/basic/public/index.js @@ -0,0 +1,21 @@ +const NotFound = { template: '<p>Page not found</p>' } +const Home = { template: '<p>home page</p>' } +const About = { template: '<p>about page</p>' } + +const routes = { + '/': Home, + '/about': About +} + +const app = new Vue({ + el: '#app', + data: { + currentRoute: window.location.pathname + }, + computed: { + ViewComponent () { + return routes[this.currentRoute] || NotFound + } + }, + render (h) { return h(this.ViewComponent) } +}) diff --git a/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go b/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go index d020adb7..e9ad65da 100644 --- a/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go +++ b/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go @@ -1,10 +1,9 @@ -// Code generated by go-bindata. -// sources: +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: // public/app.js // public/css/main.css // public/index.html -// DO NOT EDIT! - package main import ( @@ -12,7 +11,7 @@ import ( "compress/gzip" "fmt" "io" - "io/ioutil" + "net/http" "os" "path/filepath" "strings" @@ -22,7 +21,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -30,7 +29,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -51,81 +50,178 @@ type bindataFileInfo struct { modTime time.Time } +// Name return file name func (fi bindataFileInfo) Name() string { return fi.name } + +// Size return file size func (fi bindataFileInfo) Size() int64 { return fi.size } + +// Mode return file mode func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + +// ModTime return file modify time func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + +// IsDir return file whether a directory func (fi bindataFileInfo) IsDir() bool { - return false + return fi.mode&os.ModeDir != 0 } + +// Sys return file is sys mode func (fi bindataFileInfo) Sys() interface{} { return nil } -var _publicAppJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00") +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _appJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00") -func publicAppJsBytes() ([]byte, error) { +func appJsBytes() ([]byte, error) { return bindataRead( - _publicAppJs, - "public/app.js", + _appJs, + "app.js", ) } -func publicAppJs() (*asset, error) { - bytes, err := publicAppJsBytes() +func appJs() (*asset, error) { + bytes, err := appJsBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "public/app.js", size: 39, mode: os.FileMode(511), modTime: time.Unix(1499700236, 0)} + info := bindataFileInfo{name: "app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _publicCssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00") +var _cssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00") -func publicCssMainCssBytes() ([]byte, error) { +func cssMainCssBytes() ([]byte, error) { return bindataRead( - _publicCssMainCss, - "public/css/main.css", + _cssMainCss, + "css/main.css", ) } -func publicCssMainCss() (*asset, error) { - bytes, err := publicCssMainCssBytes() +func cssMainCss() (*asset, error) { + bytes, err := cssMainCssBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "public/css/main.css", size: 41, mode: os.FileMode(511), modTime: time.Unix(1499700236, 0)} + info := bindataFileInfo{name: "css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _publicIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4c\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x28\xe9\x7e\x64\xed\x35\x10\x46\xc1\x50\x21\x30\x0b\xbd\xbd\x29\xc5\xc4\xf5\x7f\x6f\xde\x50\x94\x3d\x5b\xad\xb4\xa2\xc8\x2e\x58\xad\x00\x80\x24\x49\x66\x7b\xe5\x9c\x0b\xee\xad\xec\xe8\xe2\x24\x79\x54\xf7\x60\x32\xe7\xaa\x15\x99\xe9\x68\x45\xb7\x12\x3e\x3f\x3b\x6e\x16\x7f\x6e\x7a\x05\x7e\xaf\x47\x08\x64\xe2\x36\xf8\x49\x76\xdf\x52\x15\xf4\xe6\x2f\x8b\x71\xb5\xae\xcf\xbe\x58\x80\xcc\x39\x8c\xc6\xbc\x3c\x72\xc7\xb3\xdf\x00\x00\x00\xff\xff\x7e\xad\xd1\x97\xb3\x00\x00\x00") +var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4c\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x28\xe9\x7e\x64\xed\x35\x10\x46\xc1\x50\x21\x30\x0b\xbd\xbd\x29\xc5\xc4\xf5\x7f\x6f\xde\x50\x94\x3d\x5b\xad\xb4\xa2\xc8\x2e\x58\xad\x00\x80\x24\x49\x66\x7b\xe5\x9c\x0b\xee\xad\xec\xe8\xe2\x24\x79\x54\xf7\x60\x32\xe7\xaa\x15\x99\xe9\x68\x45\xb7\x12\x3e\x3f\x3b\x6e\x16\x7f\x6e\x7a\x05\x7e\xaf\x47\x08\x64\xe2\x36\xf8\x49\x76\xdf\x52\x15\xf4\xe6\x2f\x8b\x71\xb5\xae\xcf\xbe\x58\x80\xcc\x39\x8c\xc6\xbc\x3c\x72\xc7\xb3\xdf\x00\x00\x00\xff\xff\x7e\xad\xd1\x97\xb3\x00\x00\x00") -func publicIndexHtmlBytes() ([]byte, error) { +func indexHtmlBytes() ([]byte, error) { return bindataRead( - _publicIndexHtml, - "public/index.html", + _indexHtml, + "index.html", ) } -func publicIndexHtml() (*asset, error) { - bytes, err := publicIndexHtmlBytes() +func indexHtml() (*asset, error) { + bytes, err := indexHtmlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "public/index.html", size: 179, mode: os.FileMode(511), modTime: time.Unix(1510219864, 0)} + info := bindataFileInfo{name: "index.html", size: 179, mode: os.FileMode(438), modTime: time.Unix(1565946441, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -182,20 +278,22 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "public/app.js": publicAppJs, - "public/css/main.css": publicCssMainCss, - "public/index.html": publicIndexHtml, + "app.js": appJs, + "css/main.css": cssMainCss, + "index.html": indexHtml, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error @@ -228,13 +326,11 @@ type bintree struct { } var _bintree = &bintree{nil, map[string]*bintree{ - "public": {nil, map[string]*bintree{ - "app.js": {publicAppJs, map[string]*bintree{}}, - "css": {nil, map[string]*bintree{ - "main.css": {publicCssMainCss, map[string]*bintree{}}, - }}, - "index.html": {publicIndexHtml, map[string]*bintree{}}, + "app.js": {appJs, map[string]*bintree{}}, + "css": {nil, map[string]*bintree{ + "main.css": {cssMainCss, map[string]*bintree{}}, }}, + "index.html": {indexHtml, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory @@ -251,7 +347,7 @@ func RestoreAsset(dir, name string) error { if err != nil { return err } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) if err != nil { return err } diff --git a/file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go b/file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go index 14140f92..bda9d4d6 100644 --- a/file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go +++ b/file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go @@ -1,19 +1,18 @@ package main -import "github.com/kataras/iris" +import "github.com/kataras/iris/v12" -// $ go get -u github.com/shuLhan/go-bindata/... -// $ go-bindata ./public/... -// $ go build -// $ ./embedded-single-page-application-with-other-routes +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// $ go-bindata -fs -prefix "public" ./public/... +// $ go run . func newApp() *iris.Application { app := iris.New() - app.OnErrorCode(404, func(ctx iris.Context) { + app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) { ctx.Writef("404 not found here") }) - app.StaticEmbedded("/", "./public", Asset, AssetNames) + app.HandleDir("/", AssetFile()) // Note: // if you want a dynamic index page then see the file-server/embedded-single-page-application @@ -51,5 +50,5 @@ func main() { // http://localhost:8080/.well-known/metrics // // Remember: we could use the root wildcard `app.Get("/{param:path}")` and serve the files manually as well. - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/file-server/single-page-application/embedded-single-page-application-with-other-routes/public/app.js b/file-server/single-page-application/embedded-single-page-application-with-other-routes/public/app.js index c47a1fd5..c009a1b9 100644 --- a/file-server/single-page-application/embedded-single-page-application-with-other-routes/public/app.js +++ b/file-server/single-page-application/embedded-single-page-application-with-other-routes/public/app.js @@ -1 +1 @@ -window.alert("app.js loaded from \"/"); \ No newline at end of file +window.alert("app.js loaded from static page of \"/"); \ No newline at end of file diff --git a/file-server/single-page-application/embedded-single-page-application/bindata.go b/file-server/single-page-application/embedded-single-page-application/bindata.go index 6f2d1085..0312f7ce 100644 --- a/file-server/single-page-application/embedded-single-page-application/bindata.go +++ b/file-server/single-page-application/embedded-single-page-application/bindata.go @@ -1,10 +1,10 @@ -// Code generated by go-bindata. -// sources: -// public/app.js -// public/css/main.css -// public/index.html -// DO NOT EDIT! +// Code generated by go-bindata. (@generated) DO NOT EDIT. +// Package main generated by go-bindata.// sources: +// data/public/app.js +// data/public/app2/index.html +// data/public/css/main.css +// data/views/index.html package main import ( @@ -13,6 +13,7 @@ import ( "fmt" "io" "io/ioutil" + "net/http" "os" "path/filepath" "strings" @@ -22,7 +23,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -30,7 +31,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -51,25 +52,122 @@ type bindataFileInfo struct { modTime time.Time } +// Name return file name func (fi bindataFileInfo) Name() string { return fi.name } + +// Size return file size func (fi bindataFileInfo) Size() int64 { return fi.size } + +// Mode return file mode func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + +// ModTime return file modify time func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + +// IsDir return file whether a directory func (fi bindataFileInfo) IsDir() bool { - return false + return fi.mode&os.ModeDir != 0 } + +// Sys return file is sys mode func (fi bindataFileInfo) Sys() interface{} { return nil } +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + var _publicAppJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2a\xcf\xcc\x4b\xc9\x2f\xd7\x4b\xcc\x49\x2d\x2a\xd1\x50\x4a\x2c\x28\xd0\xcb\x2a\x56\xc8\xc9\x4f\x4c\x49\x4d\x51\x48\x2b\xca\xcf\x55\x88\x51\xd2\x57\xd2\xb4\x06\x04\x00\x00\xff\xff\xa9\x06\xf7\xa3\x27\x00\x00\x00") func publicAppJsBytes() ([]byte, error) { @@ -85,12 +183,32 @@ func publicAppJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "public/app.js", size: 39, mode: os.FileMode(438), modTime: time.Unix(1497458456, 0)} + info := bindataFileInfo{name: "public/app.js", size: 39, mode: os.FileMode(420), modTime: time.Unix(1663416115, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _publicApp2IndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xcd\x31\x0a\x02\x31\x10\x85\xe1\x7e\x4e\xf1\x4a\x6d\x0c\xbb\xf5\x10\xb0\xdb\x42\x41\xd0\x0b\x44\x33\x9a\x40\xd6\x0c\x32\x85\xde\x5e\x86\x6c\xf9\xe0\xf1\xfd\x5c\x6c\x6d\x91\x88\x8b\xa4\x1c\x09\x00\xd8\xaa\x35\x89\x47\x55\xcc\x1c\xc6\x20\x0e\xe3\x40\x7c\xef\xf9\xb7\x1d\xcb\x14\xb1\xbb\x5a\xb2\xfa\xc0\x72\x3b\x9f\x70\x49\x2f\xd9\x63\x91\xd6\x3a\x9e\x9f\xbe\x22\xa9\xce\xa1\xbe\xb3\x7c\x0f\x1e\x02\x87\x32\x39\x36\x10\x57\x3d\xff\x0f\x00\x00\xff\xff\xdd\xbe\x30\x69\x85\x00\x00\x00") + +func publicApp2IndexHtmlBytes() ([]byte, error) { + return bindataRead( + _publicApp2IndexHtml, + "public/app2/index.html", + ) +} + +func publicApp2IndexHtml() (*asset, error) { + bytes, err := publicApp2IndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "public/app2/index.html", size: 133, mode: os.FileMode(420), modTime: time.Unix(1663416115, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _publicCssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\xe5\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xe5\xaa\xe5\xe5\x02\x04\x00\x00\xff\xff\x03\x25\x9c\x89\x29\x00\x00\x00") +var _publicCssMainCss = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xca\x4f\xa9\x54\xa8\xe6\x52\x50\x50\x50\x48\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x48\xca\x49\x4c\xce\xb6\xe6\xaa\xe5\x02\x04\x00\x00\xff\xff\x96\x97\xac\xb1\x26\x00\x00\x00") func publicCssMainCssBytes() ([]byte, error) { return bindataRead( @@ -105,27 +223,27 @@ func publicCssMainCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "public/css/main.css", size: 41, mode: os.FileMode(438), modTime: time.Unix(1497455997, 0)} + info := bindataFileInfo{name: "public/css/main.css", size: 38, mode: os.FileMode(420), modTime: time.Unix(1663416115, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _publicIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8e\x41\x0e\xc2\x20\x10\x45\xf7\x24\xdc\xe1\xa7\x07\x80\x74\x3f\xb2\x76\xe9\xc2\x0b\x60\x41\xc1\x50\x21\xc0\x42\xd3\xf4\xee\x06\x4a\x97\x93\xf7\x66\xde\x90\xab\x6b\x50\x9c\x71\x46\xce\x6a\xa3\x38\x03\x00\xaa\xbe\x06\xab\xb6\x0d\xe2\xa6\x5f\x56\xdc\xdb\x88\x7d\x27\x79\x00\xce\x48\x0e\x9d\x33\x7a\x44\xf3\x3b\x17\xdd\xac\x70\xb5\x21\x44\x3c\x73\x5c\xe1\x3f\xc6\x7e\x45\x6b\x80\xa4\x9b\xbb\x3f\xcc\xb2\x64\x9f\x2a\x4a\x5e\x2e\x93\xd4\x29\x89\x77\x99\x14\x40\xf2\x00\xbd\x31\x2e\xf7\x5c\xfb\xf3\x1f\x00\x00\xff\xff\x25\xe9\x37\x57\xae\x00\x00\x00") +var _viewsIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x2c\xce\xbd\x0e\xc2\x30\x0c\x04\xe0\xdd\x4f\x71\xea\x04\x4b\xa2\xee\xc6\x33\x23\x43\x5f\x20\xb4\x86\x04\xa5\x34\x6a\x22\x7e\x54\xf5\xdd\x51\x14\x46\xeb\x7c\xfa\x8e\x7d\x99\xa3\x10\xb1\x57\x37\x09\x01\x00\x97\x50\xa2\xca\xb6\xc1\x5c\xdc\x5d\xcd\x50\x4f\xec\x3b\xdb\x16\x10\xdb\xf6\x4c\x7c\x5d\xa6\xef\xbf\xe4\x7b\xc1\x61\xd0\x39\x45\x57\xf4\x88\xb3\xc6\xb8\xe0\xb6\x2e\x33\x5e\x41\xdf\xd9\x86\xe7\xa4\x1f\x53\x35\xb0\xf5\xbd\x10\xb5\x5e\x1e\xd7\x90\x0a\xf2\x3a\x9e\x3a\xeb\x52\x32\x8f\xdc\x09\xc0\xb6\x05\x55\x6b\x4a\x65\xeb\xd6\x5f\x00\x00\x00\xff\xff\xd6\xa4\xa5\x16\xb2\x00\x00\x00") -func publicIndexHtmlBytes() ([]byte, error) { +func viewsIndexHtmlBytes() ([]byte, error) { return bindataRead( - _publicIndexHtml, - "public/index.html", + _viewsIndexHtml, + "views/index.html", ) } -func publicIndexHtml() (*asset, error) { - bytes, err := publicIndexHtmlBytes() +func viewsIndexHtml() (*asset, error) { + bytes, err := viewsIndexHtmlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "public/index.html", size: 174, mode: os.FileMode(438), modTime: time.Unix(1497460815, 0)} + info := bindataFileInfo{name: "views/index.html", size: 178, mode: os.FileMode(420), modTime: time.Unix(1663416115, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -182,20 +300,23 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "public/app.js": publicAppJs, - "public/css/main.css": publicCssMainCss, - "public/index.html": publicIndexHtml, + "public/app.js": publicAppJs, + "public/app2/index.html": publicApp2IndexHtml, + "public/css/main.css": publicCssMainCss, + "views/index.html": viewsIndexHtml, } // AssetDir returns the file names below a certain // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error @@ -230,10 +351,15 @@ type bintree struct { var _bintree = &bintree{nil, map[string]*bintree{ "public": {nil, map[string]*bintree{ "app.js": {publicAppJs, map[string]*bintree{}}, + "app2": {nil, map[string]*bintree{ + "index.html": {publicApp2IndexHtml, map[string]*bintree{}}, + }}, "css": {nil, map[string]*bintree{ "main.css": {publicCssMainCss, map[string]*bintree{}}, }}, - "index.html": {publicIndexHtml, map[string]*bintree{}}, + }}, + "views": {nil, map[string]*bintree{ + "index.html": {viewsIndexHtml, map[string]*bintree{}}, }}, }} diff --git a/file-server/single-page-application/basic/public/app.js b/file-server/single-page-application/embedded-single-page-application/data/public/app.js similarity index 100% rename from file-server/single-page-application/basic/public/app.js rename to file-server/single-page-application/embedded-single-page-application/data/public/app.js diff --git a/file-server/single-page-application/embedded-single-page-application/data/public/app2/index.html b/file-server/single-page-application/embedded-single-page-application/data/public/app2/index.html new file mode 100644 index 00000000..fc7a0997 --- /dev/null +++ b/file-server/single-page-application/embedded-single-page-application/data/public/app2/index.html @@ -0,0 +1,11 @@ +<html> + +<head> + <title>App 2</title> +</head> + +<body> + <h1> (Static HTML Page) Hello from app2/index.html </h1> +</body> + +</html> \ No newline at end of file diff --git a/file-server/single-page-application/embedded-single-page-application/data/public/css/main.css b/file-server/single-page-application/embedded-single-page-application/data/public/css/main.css new file mode 100644 index 00000000..7db3df1d --- /dev/null +++ b/file-server/single-page-application/embedded-single-page-application/data/public/css/main.css @@ -0,0 +1,3 @@ +body { + background-color: black; +} diff --git a/file-server/single-page-application/embedded-single-page-application/public/index.html b/file-server/single-page-application/embedded-single-page-application/data/views/index.html similarity index 69% rename from file-server/single-page-application/embedded-single-page-application/public/index.html rename to file-server/single-page-application/embedded-single-page-application/data/views/index.html index 78f89888..f1773c3c 100644 --- a/file-server/single-page-application/embedded-single-page-application/public/index.html +++ b/file-server/single-page-application/embedded-single-page-application/data/views/index.html @@ -5,7 +5,7 @@ </head> <body> - <h1> Hello from index.html </h1> + <h1> (Template) Hello from views/index.html </h1> <script src="/app.js"> </script> diff --git a/file-server/single-page-application/embedded-single-page-application/main.go b/file-server/single-page-application/embedded-single-page-application/main.go index 8c44a3e0..3e0f65d7 100644 --- a/file-server/single-page-application/embedded-single-page-application/main.go +++ b/file-server/single-page-application/embedded-single-page-application/main.go @@ -1,13 +1,12 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) -// $ go get -u github.com/shuLhan/go-bindata/... -// $ go-bindata ./public/... -// $ go build -// $ ./embedded-single-page-application +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// $ go-bindata -prefix "data" -fs ./data/... +// $ go run . var page = struct { Title string @@ -15,24 +14,24 @@ var page = struct { func newApp() *iris.Application { app := iris.New() - app.RegisterView(iris.HTML("./public", ".html").Binary(Asset, AssetNames)) + + app.RegisterView(iris.HTML(AssetFile(), ".html").RootDir("views")) + + // Using the iris.PrefixDir you can select + // which directories to use under a particular file system, + // e.g. for views the ./public: + // publicFS := iris.PrefixDir("./public", AssetFile()) + publicFS := iris.PrefixDir("./public", AssetFile()) + app.HandleDir("/", publicFS) app.Get("/", func(ctx iris.Context) { ctx.ViewData("Page", page) - ctx.View("index.html") + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) - assetHandler := iris.StaticEmbeddedHandler("./public", Asset, AssetNames, false) // keep that false if you use the `go-bindata` tool. - // as an alternative of SPA you can take a look at the /routing/dynamic-path/root-wildcard - // example too - // or - // app.StaticEmbedded if you don't want to redirect on index.html and simple serve your SPA app (recommended). - - // public/index.html is a dynamic view, it's handlded by root, - // and we don't want to be visible as a raw data, so we will - // the return value of `app.SPA` to modify the `IndexNames` by; - app.SPA(assetHandler).AddIndexName("index.html") - return app } @@ -40,16 +39,8 @@ func main() { app := newApp() // http://localhost:8080 - // http://localhost:8080/index.html // http://localhost:8080/app.js // http://localhost:8080/css/main.css - app.Run(iris.Addr(":8080")) + // http://localhost:8080/app2 + app.Listen(":8080") } - -// Note that app.Use/UseGlobal/Done will be executed -// only to the registered routes like our index (app.Get("/", ..)). -// The file server is clean, but you can still add middleware to that by wrapping its "assetHandler". -// -// With this method, unlike StaticWeb("/" , "./public") which is not working by-design anymore, -// all custom http errors and all routes are working fine with a file server that is registered -// to the root path of the server. diff --git a/file-server/single-page-application/embedded-single-page-application/main_test.go b/file-server/single-page-application/embedded-single-page-application/main_test.go index 348be2ee..c1302d1e 100644 --- a/file-server/single-page-application/embedded-single-page-application/main_test.go +++ b/file-server/single-page-application/embedded-single-page-application/main_test.go @@ -1,13 +1,13 @@ package main import ( - "io/ioutil" + "os" "path/filepath" "runtime" "strings" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) type resource string @@ -15,7 +15,7 @@ type resource string func (r resource) contentType() string { switch filepath.Ext(r.String()) { case ".js": - return "application/javascript" + return "text/javascript" case ".css": return "text/css" default: @@ -35,28 +35,30 @@ func (r resource) strip(strip string) string { func (r resource) loadFromBase(dir string) string { filename := r.String() - if filename == "/" { - filename = "/index.html" + if strings.HasSuffix(filename, "/") { + filename = filename + "index.html" } fullpath := filepath.Join(dir, filename) - b, err := ioutil.ReadFile(fullpath) + b, err := os.ReadFile(fullpath) if err != nil { panic(fullpath + " failed with error: " + err.Error()) } result := string(b) if runtime.GOOS != "windows" { - result = strings.Replace(result, "\n", "\r\n", -1) + result = strings.ReplaceAll(result, "\n", "\r\n") + result = strings.ReplaceAll(result, "\r\r", "") } return result } var urls = []resource{ "/", - "/index.html", "/app.js", "/css/main.css", + "/app2/", + "/app2/index.html", } func TestSPAEmbedded(t *testing.T) { @@ -65,12 +67,18 @@ func TestSPAEmbedded(t *testing.T) { for _, u := range urls { url := u.String() - contents := u.loadFromBase("./public") + base := "./data/public" + if u == "/" || u == "/index.html" { + base = "./data/views" + } + contents := u.loadFromBase(base) contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1) e.GET(url).Expect(). Status(httptest.StatusOK). ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). - Body().Equal(contents) + Body().IsEqual(contents) } + + e.GET("/index.html").Expect().Status(httptest.StatusNotFound) // only root is served. } diff --git a/file-server/single-page-application/embedded-single-page-application/public/app.js b/file-server/single-page-application/embedded-single-page-application/public/app.js deleted file mode 100644 index c47a1fd5..00000000 --- a/file-server/single-page-application/embedded-single-page-application/public/app.js +++ /dev/null @@ -1 +0,0 @@ -window.alert("app.js loaded from \"/"); \ No newline at end of file diff --git a/file-server/spa-vue-router/frontend/css/page.css b/file-server/spa-vue-router/frontend/css/page.css new file mode 100644 index 00000000..04a5c737 --- /dev/null +++ b/file-server/spa-vue-router/frontend/css/page.css @@ -0,0 +1,4 @@ +.router-link-active { + color: red; + } + \ No newline at end of file diff --git a/file-server/spa-vue-router/frontend/index.html b/file-server/spa-vue-router/frontend/index.html new file mode 100644 index 00000000..99eb9bc8 --- /dev/null +++ b/file-server/spa-vue-router/frontend/index.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Iris + Vue Router</title> + <script src="https://unpkg.com/vue/dist/vue.js"></script> + <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> + <link rel="stylesheet" href="/css/page.css"> +</head> + +<body> + <div id="app"> + <h1>Hello App!</h1> + <p> + <!-- use router-link component for navigation. --> + <!-- specify the link by passing the `to` prop. --> + <!-- `<router-link>` will be rendered as an `<a>` tag by default --> + <router-link to="/foo">Go to Foo</router-link> + <router-link to="/bar">Go to Bar</router-link> + </p> + <!-- route outlet --> + <!-- component matched by the route will render here --> + <router-view></router-view> + </div> + <script src="/js/app.js"></script> +</body> + +</html> \ No newline at end of file diff --git a/file-server/spa-vue-router/frontend/js/app.js b/file-server/spa-vue-router/frontend/js/app.js new file mode 100644 index 00000000..f114c6d6 --- /dev/null +++ b/file-server/spa-vue-router/frontend/js/app.js @@ -0,0 +1,33 @@ +// 0. If using a module system (e.g. via vue-cli), import Vue and VueRouter +// and then call `Vue.use(VueRouter)`. + +// 1. Define route components. +// These can be imported from other files +const Foo = { template: '<div>foo</div>' } +const Bar = { template: '<div>bar</div>' } + +// 2. Define some routes +// Each route should map to a component. The "component" can +// either be an actual component constructor created via +// `Vue.extend()`, or just a component options object. +// We'll talk about nested routes later. +const routes = [ + { path: '/foo', component: Foo }, + { path: '/bar', component: Bar } +] + +// 3. Create the router instance and pass the `routes` option +// You can pass in additional options here, but let's +// keep it simple for now. +const router = new VueRouter({ + routes // short for `routes: routes` +}) + +// 4. Create and mount the root instance. +// Make sure to inject the router with the router option to make the +// whole app router-aware. +const app = new Vue({ + router +}).$mount('#app') + +// Now the app has started! \ No newline at end of file diff --git a/file-server/spa-vue-router/main.go b/file-server/spa-vue-router/main.go new file mode 100644 index 00000000..680f2be2 --- /dev/null +++ b/file-server/spa-vue-router/main.go @@ -0,0 +1,35 @@ +// Package main simply shows how you can getting started with Iris and Vue Router. +// Read more at: https://router.vuejs.org/guide/#html +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.HandleDir("/", "./frontend") + + app.Listen(":8080") +} + +/* For those who want to use HTML template as the index page + and serve static files in the root request path + and use vue router as the main router of the entire application, + please follow the below code example: + +func fullVueRouter() { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + app.OnAnyErrorCode(index) + app.HandleDir("/", "./frontend") + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} +*/ diff --git a/file-server/subdomain/assets/app2/app22/just_a_text_no_index.txt b/file-server/subdomain/assets/app2/app22/just_a_text_no_index.txt new file mode 100644 index 00000000..f1cc1278 --- /dev/null +++ b/file-server/subdomain/assets/app2/app22/just_a_text_no_index.txt @@ -0,0 +1 @@ +just a text. \ No newline at end of file diff --git a/file-server/subdomain/assets/app2/app2app3/index.html b/file-server/subdomain/assets/app2/app2app3/index.html new file mode 100644 index 00000000..750f10ba --- /dev/null +++ b/file-server/subdomain/assets/app2/app2app3/index.html @@ -0,0 +1 @@ +<h1>Hello App2App3 index</h1> \ No newline at end of file diff --git a/file-server/subdomain/assets/app2/index.html b/file-server/subdomain/assets/app2/index.html new file mode 100644 index 00000000..8193d822 --- /dev/null +++ b/file-server/subdomain/assets/app2/index.html @@ -0,0 +1 @@ +<h1>Hello App2 index</h1> \ No newline at end of file diff --git a/file-server/subdomain/assets/css/main.css b/file-server/subdomain/assets/css/main.css new file mode 100644 index 00000000..7db3df1d --- /dev/null +++ b/file-server/subdomain/assets/css/main.css @@ -0,0 +1,3 @@ +body { + background-color: black; +} diff --git a/file-server/subdomain/assets/favicon.ico b/file-server/subdomain/assets/favicon.ico new file mode 100644 index 00000000..c370da51 Binary files /dev/null and b/file-server/subdomain/assets/favicon.ico differ diff --git a/file-server/subdomain/assets/index.html b/file-server/subdomain/assets/index.html new file mode 100644 index 00000000..06651a45 --- /dev/null +++ b/file-server/subdomain/assets/index.html @@ -0,0 +1 @@ +<h1>Hello index</h1> \ No newline at end of file diff --git a/file-server/subdomain/assets/js/jquery-2.1.1.js b/file-server/subdomain/assets/js/jquery-2.1.1.js new file mode 100644 index 00000000..07f93514 --- /dev/null +++ b/file-server/subdomain/assets/js/jquery-2.1.1.js @@ -0,0 +1 @@ +console.log("example"); \ No newline at end of file diff --git a/file-server/subdomain/hosts b/file-server/subdomain/hosts new file mode 100644 index 00000000..69c1a384 --- /dev/null +++ b/file-server/subdomain/hosts @@ -0,0 +1,2 @@ +127.0.0.1 examle.com +127.0.0.1 v1.examle.com \ No newline at end of file diff --git a/file-server/subdomain/main.go b/file-server/subdomain/main.go new file mode 100644 index 00000000..bae492f4 --- /dev/null +++ b/file-server/subdomain/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +const ( + addr = "example.com:80" + subdomain = "v1" +) + +func newApp() *iris.Application { + app := iris.New() + app.Favicon("./assets/favicon.ico") + + v1 := app.Subdomain(subdomain) + v1.HandleDir("/", iris.Dir("./assets")) + + // http://v1.example.com + // http://v1.example.com/css/main.css + // http://v1.example.com/js/jquery-2.1.1.js + // http://v1.example.com/favicon.ico + return app +} + +func main() { + app := newApp() + app.Listen(addr) +} diff --git a/file-server/subdomain/main_test.go b/file-server/subdomain/main_test.go new file mode 100644 index 00000000..ea0504cc --- /dev/null +++ b/file-server/subdomain/main_test.go @@ -0,0 +1,81 @@ +package main + +import ( + "net" + "os" + "path/filepath" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +type resource string + +func (r resource) contentType() string { + switch filepath.Ext(r.String()) { + case ".js": + return "text/javascript" + case ".css": + return "text/css" + case ".ico": + return "image/x-icon" + case ".html", "": + return "text/html" + default: + return "text/plain" + } +} + +func (r resource) String() string { + return string(r) +} + +func (r resource) loadFromBase(dir string) string { + filename := r.String() + + if filepath.Ext(filename) == "" { + // root /. + filename = filename + "/index.html" + } + + fullpath := filepath.Join(dir, filename) + + b, err := os.ReadFile(fullpath) + if err != nil { + panic(fullpath + " failed with error: " + err.Error()) + } + + result := string(b) + + return result +} + +func TestFileServerSubdomainBasic(t *testing.T) { + urls := []resource{ + "/css/main.css", + "/js/jquery-2.1.1.js", + "/favicon.ico", + "/app2", + "/app2/app2app3", + "/", + } + + app := newApp() + e := httptest.New(t, app) + + host, _, err := net.SplitHostPort(addr) + if err != nil { + t.Fatal(err) + } + host = "http://" + subdomain + "." + host + + for _, u := range urls { + url := u.String() + contents := u.loadFromBase("./assets") + + e.GET(url).WithURL(host).Expect(). + Status(httptest.StatusOK). + ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()). + Body().IsEqual(contents) + } +} diff --git a/http_request/upload-file/main.go b/file-server/upload-file/main.go similarity index 88% rename from http_request/upload-file/main.go rename to file-server/upload-file/main.go index bc6cf50d..ccec044e 100644 --- a/http_request/upload-file/main.go +++ b/file-server/upload-file/main.go @@ -4,11 +4,11 @@ import ( "crypto/md5" "fmt" "io" - "os" + "path/filepath" "strconv" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) const maxSize = 5 << 20 // 5MB @@ -31,7 +31,10 @@ func main() { // ctx.ViewData("", token) // or add second argument to the `View` method. // Token will be passed as {{.}} in the template. - ctx.View("upload_form.html", token) + if err := ctx.View("upload_form.html", token); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) /* Read before continue. @@ -99,31 +102,22 @@ func main() { // Handle the post request from the upload_form.html to the server app.Post("/upload", iris.LimitRequestBodySize(maxSize+1<<20), func(ctx iris.Context) { // Get the file from the request. - file, info, err := ctx.FormFile("uploadfile") + f, fh, err := ctx.FormFile("uploadfile") if err != nil { ctx.StatusCode(iris.StatusInternalServerError) ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>") return } + defer f.Close() - defer file.Close() - fname := info.Filename - - // Create a file with the same name - // assuming that you have a folder named 'uploads' - out, err := os.OpenFile("./uploads/"+fname, - os.O_WRONLY|os.O_CREATE, 0666) - + _, err = ctx.SaveFormFile(fh, filepath.Join("./uploads", fh.Filename)) if err != nil { ctx.StatusCode(iris.StatusInternalServerError) ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>") return } - defer out.Close() - - io.Copy(out, file) }) // start the server at http://localhost:8080 with post limit at 5 MB. - app.Run(iris.Addr(":8080") /* 0.*/, iris.WithPostMaxMemory(maxSize)) + app.Listen(":8080" /* 0.*/, iris.WithPostMaxMemory(maxSize)) } diff --git a/http_request/upload-file/templates/upload_form.html b/file-server/upload-file/templates/upload_form.html similarity index 100% rename from http_request/upload-file/templates/upload_form.html rename to file-server/upload-file/templates/upload_form.html diff --git a/http_request/upload-files/uploads/.gitkeep b/file-server/upload-file/uploads/.gitkeep similarity index 100% rename from http_request/upload-files/uploads/.gitkeep rename to file-server/upload-file/uploads/.gitkeep diff --git a/file-server/upload-files/main.go b/file-server/upload-files/main.go new file mode 100644 index 00000000..8a9e1cf1 --- /dev/null +++ b/file-server/upload-files/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "crypto/md5" + "fmt" + "io" + "mime/multipart" + "strconv" + "strings" + "time" + + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + // start the server at http://localhost:8080 with post limit at 32 MB. + app.Listen(":8080", iris.WithPostMaxMemory(32<<20 /* same as 32 * iris.MB */)) +} + +func newApp() *iris.Application { + app := iris.New() + app.RegisterView(iris.HTML("./templates", ".html")) + + // Serve the upload_form.html to the client. + app.Get("/upload", func(ctx iris.Context) { + // create a token (optionally). + + now := time.Now().Unix() + h := md5.New() + io.WriteString(h, strconv.FormatInt(now, 10)) + token := fmt.Sprintf("%x", h.Sum(nil)) + + // render the form with the token for any use you'd like. + if err := ctx.View("upload_form.html", token); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + // Handle the post request from the upload_form.html to the server. + app.Post("/upload", func(ctx iris.Context) { + // + // UploadFormFiles + // uploads any number of incoming files ("multiple" property on the form input). + // + + // second argument is optional, + // it can be used to change a file's name based on the request, + // at this example we will showcase how to use it + // by prefixing the uploaded file with the current user's ip. + _, _, err := ctx.UploadFormFiles("./uploads", beforeSave) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + }) + + app.Post("/upload_manual", func(ctx iris.Context) { + // Get the max post value size passed via iris.WithPostMaxMemory. + maxSize := ctx.Application().ConfigurationReadOnly().GetPostMaxMemory() + + err := ctx.Request().ParseMultipartForm(maxSize) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + form := ctx.Request().MultipartForm + + files := form.File["files[]"] + failures := 0 + for _, file := range files { + _, err = ctx.SaveFormFile(file, "./uploads/"+file.Filename) + if err != nil { + failures++ + ctx.Writef("failed to upload: %s\n", file.Filename) + } + } + ctx.Writef("%d files uploaded", len(files)-failures) + }) + + return app +} + +func beforeSave(ctx iris.Context, file *multipart.FileHeader) bool { + ip := ctx.RemoteAddr() + // make sure you format the ip in a way + // that can be used for a file name (simple case): + ip = strings.ReplaceAll(ip, ".", "_") + ip = strings.ReplaceAll(ip, ":", "_") + + // you can use the time.Now, to prefix or suffix the files + // based on the current time as well, as an exercise. + // i.e unixTime := time.Now().Unix() + // prefix the Filename with the $IP- + // no need for more actions, internal uploader will use this + // name to save the file into the "./uploads" folder. + if ip == "" { + return true // don't change the file but continue saving it. + } + + _ = ip + // file.Filename = ip + "-" + file.Filename + return true +} diff --git a/file-server/upload-files/main_test.go b/file-server/upload-files/main_test.go new file mode 100644 index 00000000..91eb8742 --- /dev/null +++ b/file-server/upload-files/main_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestUploadFiles(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + // upload the file itself. + fh, err := os.Open("main.go") + if err != nil { + t.Fatal(err) + } + defer fh.Close() + + e.POST("/upload").WithMultipart().WithFile("files", "main.go", fh). + Expect().Status(httptest.StatusOK) + + f, err := os.Open("uploads/main.go") + if err != nil { + t.Fatalf("expected file to get actually uploaded on the system directory but: %v", err) + } + f.Close() + + os.Remove(f.Name()) +} diff --git a/http_request/upload-files/templates/upload_form.html b/file-server/upload-files/templates/upload_form.html similarity index 100% rename from http_request/upload-files/templates/upload_form.html rename to file-server/upload-files/templates/upload_form.html diff --git a/http_responsewriter/quicktemplate/models/.gitkeep b/file-server/upload-files/uploads/.gitkeep similarity index 100% rename from http_responsewriter/quicktemplate/models/.gitkeep rename to file-server/upload-files/uploads/.gitkeep diff --git a/file-server/webdav/main.go b/file-server/webdav/main.go new file mode 100644 index 00000000..be981a8e --- /dev/null +++ b/file-server/webdav/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "net/http" + "os" + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/recover" + + "golang.org/x/net/webdav" +) + +func main() { + app := iris.New() + + app.Logger().SetLevel("debug") + app.Use(recover.New()) + app.Use(accesslog.New(os.Stdout).Handler) + + webdavHandler := &webdav.Handler{ + FileSystem: webdav.Dir("./"), + LockSystem: webdav.NewMemLS(), + Logger: func(r *http.Request, err error) { + if err != nil { + app.Logger().Error(err) + } + }, + } + + app.HandleMany(strings.Join(iris.WebDAVMethods, " "), "/{p:path}", iris.FromStd(webdavHandler)) + + app.Listen(":8080", + iris.WithoutServerError(iris.ErrServerClosed, iris.ErrURLQuerySemicolon), + iris.WithoutPathCorrection, + ) +} + +/* Test with cURL or postman: + +* List files: + curl --location --request PROPFIND 'http://localhost:8080' +* Get File: + curl --location --request GET 'http://localhost:8080/test.txt' +* Upload File: + curl --location --request PUT 'http://localhost:8080/newfile.txt' \ + --header 'Content-Type: text/plain' \ + --data-raw 'This is a new file!' +* Copy File: + curl --location --request COPY 'http://localhost:8080/test.txt' \ + --header 'Destination: newdir/test.txt' +* Create New Directory: + curl --location --request MKCOL 'http://localhost:8080/anewdir/' + +And e.t.c. +*/ diff --git a/file-server/webdav/newdir/.gitkeep b/file-server/webdav/newdir/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/file-server/webdav/test.txt b/file-server/webdav/test.txt new file mode 100644 index 00000000..af5626b4 --- /dev/null +++ b/file-server/webdav/test.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/graphql/schema-first/README.md b/graphql/schema-first/README.md new file mode 100644 index 00000000..18063fa5 --- /dev/null +++ b/graphql/schema-first/README.md @@ -0,0 +1,86 @@ +# outerbanks-api + +A graphql api where we can store and get information on characters in Outerbanks. + +> This example is an updated version (**2023**) of outerbanks-api and it is based on: https://www.apollographql.com/blog/graphql/golang/using-graphql-with-golang. + + + +## Getting Started + +```sh +$ go install github.com/99designs/gqlgen@latest +``` + +Add `gqlgen` to your project's `tools.go` file + +```sh +$ printf '// +build tools\npackage tools\nimport _ "github.com/99designs/gqlgen"' | gofmt > tools.go +$ go get github.com/kataras/iris/v12@latest +$ go mod tidy -compat=1.20 +``` + +Start the graphql server + +``` +$ go run . +``` + +## Mutation + +Open http://localhost:8080 + +On the editor panel paste: + +```graphql +mutation upsertCharacter($input:CharacterInput!){ + upsertCharacter(input:$input) { + name + id + } +} +``` + +And in the variables panel below, paste: + +```json +{ + "input":{ + "name": "kataras", + "cliqueType": "POGUES" + } +} +``` + +Hit Ctrl+Enter to apply the mutation. + + +## Query + +Query: + +```graphql +query character($id:ID!) { + character(id:$id) { + id + name + } +} +``` + +Variables: + +```json +{ + "id":1 +} +``` + +## Re-generate code + +```sh +$ cd graph +$ rm -f graph/schema.resolvers.go +$ touch schema.graphql # make your updates here +$ gqlgen generate +``` diff --git a/graphql/schema-first/go.mod b/graphql/schema-first/go.mod new file mode 100644 index 00000000..82466b3e --- /dev/null +++ b/graphql/schema-first/go.mod @@ -0,0 +1,66 @@ +module github.com/iris-contrib/outerbanks-api + +go 1.22 + +require ( + github.com/99designs/gqlgen v0.17.45 + github.com/kataras/iris/v12 v12.2.11 + github.com/vektah/gqlparser/v2 v2.5.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/agnivade/levenshtein v1.1.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sosodev/duration v1.2.0 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/urfave/cli/v2 v2.27.1 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.20.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/graphql/schema-first/go.sum b/graphql/schema-first/go.sum new file mode 100644 index 00000000..3f0a47f6 --- /dev/null +++ b/graphql/schema-first/go.sum @@ -0,0 +1,212 @@ +github.com/99designs/gqlgen v0.17.45 h1:bH0AH67vIJo8JKNKPJP+pOPpQhZeuVRQLf53dKIpDik= +github.com/99designs/gqlgen v0.17.45/go.mod h1:Bas0XQ+Jiu/Xm5E33jC8sES3G+iC2esHBMXcq0fUPs0= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= +github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= +github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= +github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/graphql/schema-first/gqlgen.yml b/graphql/schema-first/gqlgen.yml new file mode 100644 index 00000000..ab65d466 --- /dev/null +++ b/graphql/schema-first/gqlgen.yml @@ -0,0 +1,63 @@ +# Where are all the schema files located? globs are supported eg src/**/*.graphqls +schema: + - graph/*.graphqls + +# Where should the generated server code go? +exec: + filename: graph/generated.go + package: graph + +# Uncomment to enable federation +# federation: +# filename: graph/federation.go +# package: graph + +# Where should any generated models go? +model: + filename: graph/model/models_gen.go + package: model + +# Where should the resolver implementations go? +resolver: + layout: follow-schema + dir: graph + package: graph + +# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models +# struct_tag: json + +# Optional: turn on to use []Thing instead of []*Thing +# omit_slice_element_pointers: false + +# Optional: turn off to make struct-type struct fields not use pointers +# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing } +# struct_fields_always_pointers: true + +# Optional: turn off to make resolvers return values instead of pointers for structs +# resolvers_always_return_pointers: true + +# Optional: set to speed up generation time by not performing a final validation pass. +# skip_validation: true + +# gqlgen will search for any type names in the schema in these go packages +# if they match it will use them, otherwise it will generate them. +autobind: +# - "github.com/iris-contrib/outerbanks-api/graph/model" + +# This section declares type mapping between the GraphQL and go type systems +# +# The first line in each type will be used as defaults for resolver arguments and +# modelgen, the others will be allowed when binding to fields. Configure them to +# your liking +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 diff --git a/graphql/schema-first/graph/generated.go b/graphql/schema-first/graph/generated.go new file mode 100644 index 00000000..67a6e31b --- /dev/null +++ b/graphql/schema-first/graph/generated.go @@ -0,0 +1,3761 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graph + +import ( + "bytes" + "context" + "embed" + "errors" + "fmt" + "strconv" + "sync" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + "github.com/iris-contrib/outerbanks-api/graph/model" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" +) + +// region ************************** generated!.gotpl ************************** + +// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{ + resolvers: cfg.Resolvers, + directives: cfg.Directives, + complexity: cfg.Complexity, + } +} + +type Config struct { + Resolvers ResolverRoot + Directives DirectiveRoot + Complexity ComplexityRoot +} + +type ResolverRoot interface { + Mutation() MutationResolver + Query() QueryResolver +} + +type DirectiveRoot struct { +} + +type ComplexityRoot struct { + Character struct { + CliqueType func(childComplexity int) int + ID func(childComplexity int) int + IsHero func(childComplexity int) int + Name func(childComplexity int) int + } + + Mutation struct { + UpsertCharacter func(childComplexity int, input model.CharacterInput) int + } + + Query struct { + Character func(childComplexity int, id string) int + Characters func(childComplexity int, cliqueType model.CliqueType) int + } +} + +type MutationResolver interface { + UpsertCharacter(ctx context.Context, input model.CharacterInput) (*model.Character, error) +} +type QueryResolver interface { + Character(ctx context.Context, id string) (*model.Character, error) + Characters(ctx context.Context, cliqueType model.CliqueType) ([]*model.Character, error) +} + +type executableSchema struct { + resolvers ResolverRoot + directives DirectiveRoot + complexity ComplexityRoot +} + +func (e *executableSchema) Schema() *ast.Schema { + return parsedSchema +} + +func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { + ec := executionContext{nil, e} + _ = ec + switch typeName + "." + field { + + case "Character.cliqueType": + if e.complexity.Character.CliqueType == nil { + break + } + + return e.complexity.Character.CliqueType(childComplexity), true + + case "Character.id": + if e.complexity.Character.ID == nil { + break + } + + return e.complexity.Character.ID(childComplexity), true + + case "Character.isHero": + if e.complexity.Character.IsHero == nil { + break + } + + return e.complexity.Character.IsHero(childComplexity), true + + case "Character.name": + if e.complexity.Character.Name == nil { + break + } + + return e.complexity.Character.Name(childComplexity), true + + case "Mutation.upsertCharacter": + if e.complexity.Mutation.UpsertCharacter == nil { + break + } + + args, err := ec.field_Mutation_upsertCharacter_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.UpsertCharacter(childComplexity, args["input"].(model.CharacterInput)), true + + case "Query.character": + if e.complexity.Query.Character == nil { + break + } + + args, err := ec.field_Query_character_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Character(childComplexity, args["id"].(string)), true + + case "Query.characters": + if e.complexity.Query.Characters == nil { + break + } + + args, err := ec.field_Query_characters_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Characters(childComplexity, args["cliqueType"].(model.CliqueType)), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e} + inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputCharacterInput, + ) + first := true + + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data := ec._Query(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data := ec._Mutation(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } +} + +type executionContext struct { + *graphql.OperationContext + *executableSchema +} + +func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapSchema(parsedSchema), nil +} + +func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil +} + +//go:embed "schema.graphqls" +var sourcesFS embed.FS + +func sourceData(filename string) string { + data, err := sourcesFS.ReadFile(filename) + if err != nil { + panic(fmt.Sprintf("codegen problem: %s not available", filename)) + } + return string(data) +} + +var sources = []*ast.Source{ + {Name: "schema.graphqls", Input: sourceData("schema.graphqls"), BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) field_Mutation_upsertCharacter_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.CharacterInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNCharacterInput2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacterInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["name"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_character_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_characters_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.CliqueType + if tmp, ok := rawArgs["cliqueType"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cliqueType")) + arg0, err = ec.unmarshalNCliqueType2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCliqueType(ctx, tmp) + if err != nil { + return nil, err + } + } + args["cliqueType"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _Character_id(ctx context.Context, field graphql.CollectedField, obj *model.Character) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Character_id(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Character_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Character", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Character_name(ctx context.Context, field graphql.CollectedField, obj *model.Character) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Character_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Character_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Character", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Character_isHero(ctx context.Context, field graphql.CollectedField, obj *model.Character) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Character_isHero(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsHero, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Character_isHero(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Character", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Character_cliqueType(ctx context.Context, field graphql.CollectedField, obj *model.Character) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Character_cliqueType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CliqueType, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.CliqueType) + fc.Result = res + return ec.marshalNCliqueType2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCliqueType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Character_cliqueType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Character", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CliqueType does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Mutation_upsertCharacter(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_upsertCharacter(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().UpsertCharacter(rctx, fc.Args["input"].(model.CharacterInput)) + }) + if err != nil { + ec.Error(ctx, err) + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Character) + fc.Result = res + return ec.marshalNCharacter2ᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_upsertCharacter(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Character_id(ctx, field) + case "name": + return ec.fieldContext_Character_name(ctx, field) + case "isHero": + return ec.fieldContext_Character_isHero(ctx, field) + case "cliqueType": + return ec.fieldContext_Character_cliqueType(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Character", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_upsertCharacter_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) _Query_character(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_character(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Character(rctx, fc.Args["id"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Character) + fc.Result = res + return ec.marshalOCharacter2ᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_character(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Character_id(ctx, field) + case "name": + return ec.fieldContext_Character_name(ctx, field) + case "isHero": + return ec.fieldContext_Character_isHero(ctx, field) + case "cliqueType": + return ec.fieldContext_Character_cliqueType(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Character", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_character_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) _Query_characters(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_characters(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Characters(rctx, fc.Args["cliqueType"].(model.CliqueType)) + }) + if err != nil { + ec.Error(ctx, err) + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.Character) + fc.Result = res + return ec.marshalOCharacter2ᚕᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacterᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_characters(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Character_id(ctx, field) + case "name": + return ec.fieldContext_Character_name(ctx, field) + case "isHero": + return ec.fieldContext_Character_isHero(ctx, field) + case "cliqueType": + return ec.fieldContext_Character_cliqueType(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Character", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_characters_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectType(fc.Args["name"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query___type_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___schema(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectSchema() + }) + if err != nil { + ec.Error(ctx, err) + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Schema) + fc.Result = res + return ec.marshalO__Schema2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___schema(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "description": + return ec.fieldContext___Schema_description(ctx, field) + case "types": + return ec.fieldContext___Schema_types(ctx, field) + case "queryType": + return ec.fieldContext___Schema_queryType(ctx, field) + case "mutationType": + return ec.fieldContext___Schema_mutationType(ctx, field) + case "subscriptionType": + return ec.fieldContext___Schema_subscriptionType(ctx, field) + case "directives": + return ec.fieldContext___Schema_directives(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Schema", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_locations(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Locations, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]string) + fc.Result = res + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_locations(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __DirectiveLocation does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_args(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_isRepeatable(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsRepeatable, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_isDeprecated(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_deprecationReason(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_args(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Args, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_isDeprecated(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.IsDeprecated(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_deprecationReason(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_defaultValue(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.DefaultValue, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_types(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Types(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_queryType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.QueryType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_queryType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_mutationType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MutationType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_mutationType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_subscriptionType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SubscriptionType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_directives(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Directives(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]introspection.Directive) + fc.Result = res + return ec.marshalN__Directive2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_directives(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Directive_name(ctx, field) + case "description": + return ec.fieldContext___Directive_description(ctx, field) + case "locations": + return ec.fieldContext___Directive_locations(ctx, field) + case "args": + return ec.fieldContext___Directive_args(ctx, field) + case "isRepeatable": + return ec.fieldContext___Directive_isRepeatable(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Directive", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_kind(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Kind(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalN__TypeKind2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_kind(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __TypeKind does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_name(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Name(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_description(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_fields(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Fields(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Field) + fc.Result = res + return ec.marshalO__Field2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_fields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Field_name(ctx, field) + case "description": + return ec.fieldContext___Field_description(ctx, field) + case "args": + return ec.fieldContext___Field_args(ctx, field) + case "type": + return ec.fieldContext___Field_type(ctx, field) + case "isDeprecated": + return ec.fieldContext___Field_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___Field_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Field", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_fields_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_interfaces(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Interfaces(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_interfaces(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_possibleTypes(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PossibleTypes(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_possibleTypes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_enumValues(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EnumValues(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.EnumValue) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_enumValues(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___EnumValue_name(ctx, field) + case "description": + return ec.fieldContext___EnumValue_description(ctx, field) + case "isDeprecated": + return ec.fieldContext___EnumValue_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___EnumValue_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __EnumValue", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_enumValues_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_inputFields(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.InputFields(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_inputFields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_ofType(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_ofType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_specifiedByURL(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SpecifiedByURL(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputCharacterInput(ctx context.Context, obj interface{}) (model.CharacterInput, error) { + var it model.CharacterInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"name", "id", "isHero", "cliqueType"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "name": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + it.Name, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + case "isHero": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("isHero")) + it.IsHero, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "cliqueType": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cliqueType")) + it.CliqueType, err = ec.unmarshalNCliqueType2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCliqueType(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var characterImplementors = []string{"Character"} + +func (ec *executionContext) _Character(ctx context.Context, sel ast.SelectionSet, obj *model.Character) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, characterImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Character") + case "id": + + out.Values[i] = ec._Character_id(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": + + out.Values[i] = ec._Character_name(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "isHero": + + out.Values[i] = ec._Character_isHero(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "cliqueType": + + out.Values[i] = ec._Character_cliqueType(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "upsertCharacter": + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_upsertCharacter(ctx, field) + }) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + return out +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "character": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_character(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "characters": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_characters(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "__type": + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___type(ctx, field) + }) + + case "__schema": + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___schema(ctx, field) + }) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + return out +} + +var __DirectiveImplementors = []string{"__Directive"} + +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Directive") + case "name": + + out.Values[i] = ec.___Directive_name(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + + out.Values[i] = ec.___Directive_description(ctx, field, obj) + + case "locations": + + out.Values[i] = ec.___Directive_locations(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "args": + + out.Values[i] = ec.___Directive_args(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "isRepeatable": + + out.Values[i] = ec.___Directive_isRepeatable(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __EnumValueImplementors = []string{"__EnumValue"} + +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__EnumValue") + case "name": + + out.Values[i] = ec.___EnumValue_name(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + + out.Values[i] = ec.___EnumValue_description(ctx, field, obj) + + case "isDeprecated": + + out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + + out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __FieldImplementors = []string{"__Field"} + +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Field") + case "name": + + out.Values[i] = ec.___Field_name(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + + out.Values[i] = ec.___Field_description(ctx, field, obj) + + case "args": + + out.Values[i] = ec.___Field_args(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "type": + + out.Values[i] = ec.___Field_type(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "isDeprecated": + + out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + + out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __InputValueImplementors = []string{"__InputValue"} + +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__InputValue") + case "name": + + out.Values[i] = ec.___InputValue_name(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + + out.Values[i] = ec.___InputValue_description(ctx, field, obj) + + case "type": + + out.Values[i] = ec.___InputValue_type(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "defaultValue": + + out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __SchemaImplementors = []string{"__Schema"} + +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Schema") + case "description": + + out.Values[i] = ec.___Schema_description(ctx, field, obj) + + case "types": + + out.Values[i] = ec.___Schema_types(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "queryType": + + out.Values[i] = ec.___Schema_queryType(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "mutationType": + + out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) + + case "subscriptionType": + + out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) + + case "directives": + + out.Values[i] = ec.___Schema_directives(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __TypeImplementors = []string{"__Type"} + +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Type") + case "kind": + + out.Values[i] = ec.___Type_kind(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": + + out.Values[i] = ec.___Type_name(ctx, field, obj) + + case "description": + + out.Values[i] = ec.___Type_description(ctx, field, obj) + + case "fields": + + out.Values[i] = ec.___Type_fields(ctx, field, obj) + + case "interfaces": + + out.Values[i] = ec.___Type_interfaces(ctx, field, obj) + + case "possibleTypes": + + out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) + + case "enumValues": + + out.Values[i] = ec.___Type_enumValues(ctx, field, obj) + + case "inputFields": + + out.Values[i] = ec.___Type_inputFields(ctx, field, obj) + + case "ofType": + + out.Values[i] = ec.___Type_ofType(ctx, field, obj) + + case "specifiedByURL": + + out.Values[i] = ec.___Type_specifiedByURL(ctx, field, obj) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNCharacter2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx context.Context, sel ast.SelectionSet, v model.Character) graphql.Marshaler { + return ec._Character(ctx, sel, &v) +} + +func (ec *executionContext) marshalNCharacter2ᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx context.Context, sel ast.SelectionSet, v *model.Character) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Character(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNCharacterInput2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacterInput(ctx context.Context, v interface{}) (model.CharacterInput, error) { + res, err := ec.unmarshalInputCharacterInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNCliqueType2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCliqueType(ctx context.Context, v interface{}) (model.CliqueType, error) { + var res model.CliqueType + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCliqueType2githubᚗcomᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCliqueType(ctx context.Context, sel ast.SelectionSet, v model.CliqueType) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Type2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + return res +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalBoolean(*v) + return res +} + +func (ec *executionContext) marshalOCharacter2ᚕᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacterᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Character) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNCharacter2ᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalOCharacter2ᚖgithub.comᚋirisᚑcontribᚋouterbanksᚑapiᚋgraphᚋgraphᚋmodelᚐCharacter(ctx context.Context, sel ast.SelectionSet, v *model.Character) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Character(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(*v) + return res +} + +func (ec *executionContext) marshalO__EnumValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Field2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__InputValue2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Schema2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Schema(ctx, sel, v) +} + +func (ec *executionContext) marshalO__Type2ᚕgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Type2ᚖgithub.comᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/graphql/schema-first/graph/model/models_gen.go b/graphql/schema-first/graph/model/models_gen.go new file mode 100644 index 00000000..e36a7110 --- /dev/null +++ b/graphql/schema-first/graph/model/models_gen.go @@ -0,0 +1,66 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package model + +import ( + "fmt" + "io" + "strconv" +) + +type Character struct { + ID string `json:"id"` + Name string `json:"name"` + IsHero bool `json:"isHero"` + CliqueType CliqueType `json:"cliqueType"` +} + +type CharacterInput struct { + Name string `json:"name"` + ID *string `json:"id"` + IsHero *bool `json:"isHero"` + CliqueType CliqueType `json:"cliqueType"` +} + +type CliqueType string + +const ( + // People who are elite with parents having money + CliqueTypeKooks CliqueType = "KOOKS" + // People who desperate to move up the social ladder to become new versions of themselves and establish new beginnings + CliqueTypePogues CliqueType = "POGUES" +) + +var AllCliqueType = []CliqueType{ + CliqueTypeKooks, + CliqueTypePogues, +} + +func (e CliqueType) IsValid() bool { + switch e { + case CliqueTypeKooks, CliqueTypePogues: + return true + } + return false +} + +func (e CliqueType) String() string { + return string(e) +} + +func (e *CliqueType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CliqueType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CliqueType", str) + } + return nil +} + +func (e CliqueType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/graphql/schema-first/graph/resolver.go b/graphql/schema-first/graph/resolver.go new file mode 100644 index 00000000..6f3b077c --- /dev/null +++ b/graphql/schema-first/graph/resolver.go @@ -0,0 +1,11 @@ +package graph + +import "github.com/iris-contrib/outerbanks-api/graph/model" + +// This file will not be regenerated automatically. +// +// It serves as dependency injection for your app, add any dependencies you require here. + +type Resolver struct { + CharacterStore map[string]model.Character +} diff --git a/graphql/schema-first/graph/schema.graphqls b/graphql/schema-first/graph/schema.graphqls new file mode 100644 index 00000000..1e1e8392 --- /dev/null +++ b/graphql/schema-first/graph/schema.graphqls @@ -0,0 +1,33 @@ +# GraphQL schema example +# +# https://gqlgen.com/getting-started/ + +enum CliqueType { + "People who are elite with parents having money" + KOOKS + "People who desperate to move up the social ladder to become new versions of themselves and establish new beginnings" + POGUES +} + +type Character { + id: ID! + name: String! + isHero: Boolean! + cliqueType: CliqueType! +} + +input CharacterInput { + name: String! + id: String + isHero: Boolean + cliqueType: CliqueType! +} + +type Mutation { + upsertCharacter(input: CharacterInput!): Character! +} + +type Query { + character(id:ID!): Character + characters(cliqueType:CliqueType!): [Character!] +} \ No newline at end of file diff --git a/graphql/schema-first/graph/schema.resolvers.go b/graphql/schema-first/graph/schema.resolvers.go new file mode 100644 index 00000000..2244df75 --- /dev/null +++ b/graphql/schema-first/graph/schema.resolvers.go @@ -0,0 +1,77 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. + +import ( + "context" + "fmt" + "strconv" + + "github.com/iris-contrib/outerbanks-api/graph/model" +) + +func (r *mutationResolver) UpsertCharacter(ctx context.Context, input model.CharacterInput) (*model.Character, error) { + id := input.ID + var character model.Character + character.Name = input.Name + character.CliqueType = input.CliqueType + + n := len(r.Resolver.CharacterStore) + if n == 0 { + r.Resolver.CharacterStore = make(map[string]model.Character) + } + + if id != nil { + cs, ok := r.Resolver.CharacterStore[*id] + if !ok { + return nil, fmt.Errorf("not found") + } + if input.IsHero != nil { + character.IsHero = *input.IsHero + } else { + character.IsHero = cs.IsHero + } + r.Resolver.CharacterStore[*id] = character + } else { + // generate unique id + nid := strconv.Itoa(n + 1) + character.ID = nid + if input.IsHero != nil { + character.IsHero = *input.IsHero + } + r.Resolver.CharacterStore[nid] = character + } + + return &character, nil +} + +func (r *queryResolver) Character(ctx context.Context, id string) (*model.Character, error) { + character, ok := r.Resolver.CharacterStore[id] + if !ok { + return nil, fmt.Errorf("not found") + } + return &character, nil +} + +func (r *queryResolver) Characters(ctx context.Context, cliqueType model.CliqueType) ([]*model.Character, error) { + characters := make([]*model.Character, 0) + for idx := range r.Resolver.CharacterStore { + character := r.Resolver.CharacterStore[idx] + if character.CliqueType == cliqueType { + + characters = append(characters, &character) + } + } + + return characters, nil +} + +// Mutation returns generated.MutationResolver implementation. +func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } + +// Query returns generated.QueryResolver implementation. +func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } + +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/graphql/schema-first/server.go b/graphql/schema-first/server.go new file mode 100644 index 00000000..92306be8 --- /dev/null +++ b/graphql/schema-first/server.go @@ -0,0 +1,27 @@ +package main + +import ( + "os" + + "github.com/iris-contrib/outerbanks-api/graph" + + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + graphServer := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}})) + playgroundHandler := playground.Handler("GraphQL playground", "/query") + + app.Get("/", iris.FromStd(playgroundHandler)) // We use iris.FromStd to convert a standard http.Handler to an iris.Handler. + app.Any("/query", iris.FromStd(graphServer.ServeHTTP)) // GET, POST, PUT... + + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + app.Listen(":" + port) +} diff --git a/graphql/schema-first/tools.go b/graphql/schema-first/tools.go new file mode 100644 index 00000000..8e7c1b2a --- /dev/null +++ b/graphql/schema-first/tools.go @@ -0,0 +1,6 @@ +//go:build tools +// +build tools + +package tools + +import _ "github.com/99designs/gqlgen" diff --git a/hero/basic/README.md b/hero/basic/README.md deleted file mode 100644 index c039ce97..00000000 --- a/hero/basic/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# hero: basic - -## 1. Path Parameters - Built'n Dependencies - - - -## 2. Services - Static Dependencies - - - -## 3. Per-Request - Dynamic Dependencies - - \ No newline at end of file diff --git a/hero/basic/main.go b/hero/basic/main.go deleted file mode 100644 index 90015ed3..00000000 --- a/hero/basic/main.go +++ /dev/null @@ -1,67 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/hero" -) - -func main() { - - app := iris.New() - - // 1 - helloHandler := hero.Handler(hello) - app.Get("/{to:string}", helloHandler) - - // 2 - hero.Register(&myTestService{ - prefix: "Service: Hello", - }) - - helloServiceHandler := hero.Handler(helloService) - app.Get("/service/{to:string}", helloServiceHandler) - - // 3 - hero.Register(func(ctx iris.Context) (form LoginForm) { - // it binds the "form" with a - // x-www-form-urlencoded form data and returns it. - ctx.ReadForm(&form) - return - }) - - loginHandler := hero.Handler(login) - app.Post("/login", loginHandler) - - // http://localhost:8080/your_name - // http://localhost:8080/service/your_name - app.Run(iris.Addr(":8080")) -} - -func hello(to string) string { - return "Hello " + to -} - -type Service interface { - SayHello(to string) string -} - -type myTestService struct { - prefix string -} - -func (s *myTestService) SayHello(to string) string { - return s.prefix + " " + to -} - -func helloService(to string, service Service) string { - return service.SayHello(to) -} - -type LoginForm struct { - Username string `form:"username"` - Password string `form:"password"` -} - -func login(form LoginForm) string { - return "Hello " + form.Username -} diff --git a/hero/overview/main.go b/hero/overview/main.go deleted file mode 100644 index 98f120d7..00000000 --- a/hero/overview/main.go +++ /dev/null @@ -1,60 +0,0 @@ -// file: main.go - -package main - -import ( - "github.com/iris-contrib/examples/hero/overview/datasource" - "github.com/iris-contrib/examples/hero/overview/repositories" - "github.com/iris-contrib/examples/hero/overview/services" - "github.com/iris-contrib/examples/hero/overview/web/middleware" - "github.com/iris-contrib/examples/hero/overview/web/routes" - - "github.com/kataras/iris" - "github.com/kataras/iris/hero" -) - -func main() { - app := iris.New() - app.Logger().SetLevel("debug") - - // Load the template files. - app.RegisterView(iris.HTML("./web/views", ".html")) - - // Create our movie repository with some (memory) data from the datasource. - repo := repositories.NewMovieRepository(datasource.Movies) - // Create our movie service, we will bind it to the movie app's dependencies. - movieService := services.NewMovieService(repo) - hero.Register(movieService) - - // Serve our routes with hero handlers. - app.PartyFunc("/hello", func(r iris.Party) { - r.Get("/", hero.Handler(routes.Hello)) - r.Get("/{name}", hero.Handler(routes.HelloName)) - }) - - app.PartyFunc("/movies", func(r iris.Party) { - // Add the basic authentication(admin:password) middleware - // for the /movies based requests. - r.Use(middleware.BasicAuth) - - r.Get("/", hero.Handler(routes.Movies)) - r.Get("/{id:long}", hero.Handler(routes.MovieByID)) - r.Put("/{id:long}", hero.Handler(routes.UpdateMovieByID)) - r.Delete("/{id:long}", hero.Handler(routes.DeleteMovieByID)) - }) - - // http://localhost:8080/hello - // http://localhost:8080/hello/iris - // http://localhost:8080/movies - // http://localhost:8080/movies/1 - app.Run( - // Start the web server at localhost:8080 - iris.Addr("localhost:8080"), - // disables updates: - iris.WithoutVersionChecker, - // skip err server closed when CTRL/CMD+C pressed: - iris.WithoutServerError(iris.ErrServerClosed), - // enables faster json serialization and more: - iris.WithOptimizations, - ) -} diff --git a/hero/overview/web/middleware/basicauth.go b/hero/overview/web/middleware/basicauth.go deleted file mode 100644 index c9b6eacf..00000000 --- a/hero/overview/web/middleware/basicauth.go +++ /dev/null @@ -1,12 +0,0 @@ -// file: web/middleware/basicauth.go - -package middleware - -import "github.com/kataras/iris/middleware/basicauth" - -// BasicAuth middleware sample. -var BasicAuth = basicauth.New(basicauth.Config{ - Users: map[string]string{ - "admin": "password", - }, -}) diff --git a/http-client/weatherapi/client/client.go b/http-client/weatherapi/client/client.go new file mode 100644 index 00000000..9e518e0a --- /dev/null +++ b/http-client/weatherapi/client/client.go @@ -0,0 +1,46 @@ +package client + +import ( + "context" + "net/url" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/client" +) + +// The BaseURL of our API client. +const BaseURL = "https://api.weatherapi.com/v1" + +type ( + Options struct { + APIKey string `json:"api_key" yaml:"APIKey" toml:"APIKey"` + } + + Client struct { + *client.Client + } +) + +func NewClient(opts Options) *Client { + apiKeyParameterSetter := client.RequestParam("key", opts.APIKey) + + c := client.New( + client.Debug, + client.BaseURL(BaseURL), + client.PersistentRequestOptions(apiKeyParameterSetter), + ) + + return &Client{c} +} + +func (c *Client) GetCurrentByCity(ctx context.Context, city string) (resp Response, err error) { + urlpath := "/current.json" + // ?q=Athens&aqi=no + params := client.RequestQuery(url.Values{ + "q": []string{city}, + "aqi": []string{"no"}, + }) + + err = c.Client.ReadJSON(ctx, &resp, iris.MethodGet, urlpath, nil, params) + return +} diff --git a/http-client/weatherapi/client/response.go b/http-client/weatherapi/client/response.go new file mode 100644 index 00000000..ff624807 --- /dev/null +++ b/http-client/weatherapi/client/response.go @@ -0,0 +1,43 @@ +package client + +type Response struct { + Location struct { + Name string `json:"name"` + Region string `json:"region"` + Country string `json:"country"` + Lat float64 `json:"lat"` + Lon float64 `json:"lon"` + TzID string `json:"tz_id"` + LocaltimeEpoch int `json:"localtime_epoch"` + Localtime string `json:"localtime"` + } `json:"location"` + Current struct { + LastUpdatedEpoch int `json:"last_updated_epoch"` + LastUpdated string `json:"last_updated"` + TempC float64 `json:"temp_c"` + TempF float64 `json:"temp_f"` + IsDay int `json:"is_day"` + Condition struct { + Text string `json:"text"` + Icon string `json:"icon"` + Code int `json:"code"` + } `json:"condition"` + WindMph float64 `json:"wind_mph"` + WindKph float64 `json:"wind_kph"` + WindDegree int `json:"wind_degree"` + WindDir string `json:"wind_dir"` + PressureMb float64 `json:"pressure_mb"` + PressureIn float64 `json:"pressure_in"` + PrecipMm float64 `json:"precip_mm"` + PrecipIn float64 `json:"precip_in"` + Humidity int `json:"humidity"` + Cloud int `json:"cloud"` + FeelslikeC float64 `json:"feelslike_c"` + FeelslikeF float64 `json:"feelslike_f"` + VisKm float64 `json:"vis_km"` + VisMiles float64 `json:"vis_miles"` + Uv float64 `json:"uv"` + GustMph float64 `json:"gust_mph"` + GustKph float64 `json:"gust_kph"` + } `json:"current"` +} diff --git a/http-client/weatherapi/main.go b/http-client/weatherapi/main.go new file mode 100644 index 00000000..c6850466 --- /dev/null +++ b/http-client/weatherapi/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "context" + "fmt" + + "github.com/kataras/iris/v12/_examples/http-client/weatherapi/client" +) + +func main() { + c := client.NewClient(client.Options{ + APIKey: "{YOUR_API_KEY_HERE}", + }) + + resp, err := c.GetCurrentByCity(context.Background(), "Xanthi/GR") + if err != nil { + panic(err) + } + + fmt.Printf("Temp: %.2f(C), %.2f(F)\n", resp.Current.TempC, resp.Current.TempF) +} diff --git a/http-listening/custom-listener/unix-reuseport/main.go b/http-listening/custom-listener/unix-reuseport/main.go deleted file mode 100644 index e9bc96b6..00000000 --- a/http-listening/custom-listener/unix-reuseport/main.go +++ /dev/null @@ -1,44 +0,0 @@ -// +build linux darwin dragonfly freebsd netbsd openbsd rumprun - -package main - -import ( - // Package tcplisten provides customizable TCP net.Listener with various - // performance-related options: - // - // - SO_REUSEPORT. This option allows linear scaling server performance - // on multi-CPU servers. - // See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details. - // - // - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted - // connection before writing to them. - // - // - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details. - "github.com/valyala/tcplisten" - - "github.com/kataras/iris" -) - -// $ go get github.com/valyala/tcplisten -// $ go run main.go - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<b>Hello World!</b>") - }) - - listenerCfg := tcplisten.Config{ - ReusePort: true, - DeferAccept: true, - FastOpen: true, - } - - l, err := listenerCfg.NewListener("tcp", ":8080") - if err != nil { - panic(err) - } - - app.Run(iris.Listener(l)) -} diff --git a/http-listening/custom-listener/unix-reuseport/main_windows.go b/http-listening/custom-listener/unix-reuseport/main_windows.go deleted file mode 100644 index 91c9720f..00000000 --- a/http-listening/custom-listener/unix-reuseport/main_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build windows - -package main - -func main() { - panic("windows operating system does not support this feature") -} diff --git a/http-listening/iris-configurator-and-host-configurator/README.md b/http-listening/iris-configurator-and-host-configurator/README.md deleted file mode 100644 index 211dde7e..00000000 --- a/http-listening/iris-configurator-and-host-configurator/README.md +++ /dev/null @@ -1,2 +0,0 @@ -A silly example for this issue: https://github.com/kataras/iris/issues/688#issuecomment-318828259. -However it seems useful and therefore is being included in the examples for everyone else. \ No newline at end of file diff --git a/http-listening/iris-configurator-and-host-configurator/counter/configurator.go b/http-listening/iris-configurator-and-host-configurator/counter/configurator.go deleted file mode 100644 index 72988303..00000000 --- a/http-listening/iris-configurator-and-host-configurator/counter/configurator.go +++ /dev/null @@ -1,30 +0,0 @@ -package counter - -import ( - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/core/host" -) - -func Configurator(app *iris.Application) { - counterValue := 0 - - go func() { - ticker := time.NewTicker(time.Second) - - for range ticker.C { - counterValue++ - } - - app.ConfigureHost(func(h *host.Supervisor) { // <- HERE: IMPORTANT - h.RegisterOnShutdown(func() { - ticker.Stop() - }) - }) // or put the ticker outside of the gofunc and put the configurator before or after the app.Get, outside of this gofunc - }() - - app.Get("/counter", func(ctx iris.Context) { - ctx.Writef("Counter value = %d", counterValue) - }) -} diff --git a/http-listening/iris-configurator-and-host-configurator/main.go b/http-listening/iris-configurator-and-host-configurator/main.go deleted file mode 100644 index b86745ca..00000000 --- a/http-listening/iris-configurator-and-host-configurator/main.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "github.com/iris-contrib/examples/http-listening/iris-configurator-and-host-configurator/counter" - - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - app.Configure(counter.Configurator) - - app.Run(iris.Addr(":8080")) -} diff --git a/http-listening/listen-addr/main.go b/http-listening/listen-addr/main.go deleted file mode 100644 index aef4e86c..00000000 --- a/http-listening/listen-addr/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<h1>Hello World!</h1>") - }) - - // http://localhost:8080 - app.Run(iris.Addr(":8080")) -} diff --git a/http-listening/listen-addr/omit-server-errors/main.go b/http-listening/listen-addr/omit-server-errors/main.go deleted file mode 100644 index db2e01bf..00000000 --- a/http-listening/listen-addr/omit-server-errors/main.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<h1>Hello World!</h1>") - }) - - err := app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) - if err != nil { - // do something - } - // same as: - // err := app.Run(iris.Addr(":8080")) - // if err != nil && (err != iris.ErrServerClosed || err.Error() != iris.ErrServerClosed.Error()) { - // [...] - // } -} diff --git a/http-listening/listen-letsencrypt/main.go b/http-listening/listen-letsencrypt/main.go deleted file mode 100644 index bf325288..00000000 --- a/http-listening/listen-letsencrypt/main.go +++ /dev/null @@ -1,27 +0,0 @@ -// Package main provide one-line integration with letsencrypt.org -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("Hello from SECURE SERVER!") - }) - - app.Get("/test2", func(ctx iris.Context) { - ctx.Writef("Welcome to secure server from /test2!") - }) - - app.Get("/redirect", func(ctx iris.Context) { - ctx.Redirect("/test2") - }) - - // NOTE: This will not work on domains like this, - // use real whitelisted domain(or domains split by whitespaces) - // and a non-public e-mail instead. - app.Run(iris.AutoTLS(":443", "example.com", "mail@example.com")) -} diff --git a/http-listening/listen-tls/main.go b/http-listening/listen-tls/main.go deleted file mode 100644 index 04b57de6..00000000 --- a/http-listening/listen-tls/main.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "net/url" - - "github.com/kataras/iris" - - "github.com/kataras/iris/core/host" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("Hello from the SECURE server") - }) - - app.Get("/mypath", func(ctx iris.Context) { - ctx.Writef("Hello from the SECURE server on path /mypath") - }) - - // to start a new server listening at :80 and redirects - // to the secure address, then: - target, _ := url.Parse("https://127.0.1:443") - go host.NewProxy("127.0.0.1:80", target).ListenAndServe() - - // start the server (HTTPS) on port 443, this is a blocking func - app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key")) - -} diff --git a/http-listening/listen-tls/mycert.cert b/http-listening/listen-tls/mycert.cert deleted file mode 100644 index 39106262..00000000 --- a/http-listening/listen-tls/mycert.cert +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDAzCCAeugAwIBAgIJAPDsxtKV4v3uMA0GCSqGSIb3DQEBBQUAMBgxFjAUBgNV -BAMMDTEyNy4wLjAuMTo0NDMwHhcNMTYwNjI5MTMxMjU4WhcNMjYwNjI3MTMxMjU4 -WjAYMRYwFAYDVQQDDA0xMjcuMC4wLjE6NDQzMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA0KtAOHKrcbLwWJXgRX7XSFyu4HHHpSty4bliv8ET4sLJpbZH -XeVX05Foex7PnrurDP6e+0H5TgqqcpQM17/ZlFcyKrJcHSCgV0ZDB3Sb8RLQSLns -8a+MOSbn1WZ7TkC7d/cWlKmasQRHQ2V/cWlGooyKNEPoGaEz8MbY0wn2spyIJwsB -dciERC6317VTXbiZdoD8QbAsT+tBvEHM2m2A7B7PQmHNehtyFNbSV5uZNodvv1uv -ZTnDa6IqpjFLb1b2HNFgwmaVPmmkLuy1l9PN+o6/DUnXKKBrfPAx4JOlqTKEQpWs -pnfacTE3sWkkmOSSFltAXfkXIJFKdS/hy5J/KQIDAQABo1AwTjAdBgNVHQ4EFgQU -zr1df/c9+NyTpmyiQO8g3a8NswYwHwYDVR0jBBgwFoAUzr1df/c9+NyTpmyiQO8g -3a8NswYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEACG5shtMSDgCd -MNjOF+YmD+PX3Wy9J9zehgaDJ1K1oDvBbQFl7EOJl8lRMWITSws22Wxwh8UXVibL -sscKBp14dR3e7DdbwCVIX/JyrJyOaCfy2nNBdf1B06jYFsIHvP3vtBAb9bPNOTBQ -QE0Ztu9kCqgsmu0//sHuBEeA3d3E7wvDhlqRSxTLcLtgC1NSgkFvBw0JvwgpkX6s -M5WpSBZwZv8qpplxhFfqNy8Uf+xrpSW0pGfkHumehkQGC6/Ry7raganS0aHhDPK9 -Z1bEJ2com1bFFAQsm9yIXrRVMGGCtihB2Au0Q4jpEjUbzWYM+ItZyvRAGRM6Qex6 -s/jogMeRsw== ------END CERTIFICATE----- diff --git a/http-listening/listen-tls/mykey.key b/http-listening/listen-tls/mykey.key deleted file mode 100644 index 309569b4..00000000 --- a/http-listening/listen-tls/mykey.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA0KtAOHKrcbLwWJXgRX7XSFyu4HHHpSty4bliv8ET4sLJpbZH -XeVX05Foex7PnrurDP6e+0H5TgqqcpQM17/ZlFcyKrJcHSCgV0ZDB3Sb8RLQSLns -8a+MOSbn1WZ7TkC7d/cWlKmasQRHQ2V/cWlGooyKNEPoGaEz8MbY0wn2spyIJwsB -dciERC6317VTXbiZdoD8QbAsT+tBvEHM2m2A7B7PQmHNehtyFNbSV5uZNodvv1uv -ZTnDa6IqpjFLb1b2HNFgwmaVPmmkLuy1l9PN+o6/DUnXKKBrfPAx4JOlqTKEQpWs -pnfacTE3sWkkmOSSFltAXfkXIJFKdS/hy5J/KQIDAQABAoIBAQDCd+bo9I0s8Fun -4z3Y5oYSDTZ5O/CY0O5GyXPrSzCSM4Cj7EWEj1mTdb9Ohv9tam7WNHHLrcd+4NfK -4ok5hLVs1vqM6h6IksB7taKATz+Jo0PzkzrsXvMqzERhEBo4aoGMIv2rXIkrEdas -S+pCsp8+nAWtAeBMCn0Slu65d16vQxwgfod6YZfvMKbvfhOIOShl9ejQ+JxVZcMw -Ti8sgvYmFUrdrEH3nCgptARwbx4QwlHGaw/cLGHdepfFsVaNQsEzc7m61fSO70m4 -NYJv48ZgjOooF5AccbEcQW9IxxikwNc+wpFYy5vDGzrBwS5zLZQFpoyMWFhtWdjx -hbmNn1jlAoGBAPs0ZjqsfDrH5ja4dQIdu5ErOccsmoHfMMBftMRqNG5neQXEmoLc -Uz8WeQ/QDf302aTua6E9iSjd7gglbFukVwMndQ1Q8Rwxz10jkXfiE32lFnqK0csx -ltruU6hOeSGSJhtGWBuNrT93G2lmy23fSG6BqOzdU4rn/2GPXy5zaxM/AoGBANSm -/E96RcBUiI6rDVqKhY+7M1yjLB41JrErL9a0Qfa6kYnaXMr84pOqVN11IjhNNTgl -g1lwxlpXZcZh7rYu9b7EEMdiWrJDQV7OxLDHopqUWkQ+3MHwqs6CxchyCq7kv9Df -IKqat7Me6Cyeo0MqcW+UMxlCRBxKQ9jqC7hDfZuXAoGBAJmyS8ImerP0TtS4M08i -JfsCOY21qqs/hbKOXCm42W+be56d1fOvHngBJf0YzRbO0sNo5Q14ew04DEWLsCq5 -+EsDv0hwd7VKfJd+BakV99ruQTyk5wutwaEeJK1bph12MD6L4aiqHJAyLeFldZ45 -+TUzu8mA+XaJz+U/NXtUPvU9AoGBALtl9M+tdy6I0Fa50ujJTe5eEGNAwK5WNKTI -5D2XWNIvk/Yh4shXlux+nI8UnHV1RMMX++qkAYi3oE71GsKeG55jdk3fFQInVsJQ -APGw3FDRD8M4ip62ki+u+tEr/tIlcAyHtWfjNKO7RuubWVDlZFXqCiXmSdOMdsH/ -bxiREW49AoGACWev/eOzBoQJCRN6EvU2OV0s3b6f1QsPvcaH0zc6bgbBFOGmJU8v -pXhD88tsu9exptLkGVoYZjR0n0QT/2Kkyu93jVDW/80P7VCz8DKYyAJDa4CVwZxO -MlobQSunSDKx/CCJhWkbytCyh1bngAtwSAYLXavYIlJbAzx6FvtAIw4= ------END RSA PRIVATE KEY----- diff --git a/http-listening/README.md b/http-server/README.md similarity index 81% rename from http-listening/README.md rename to http-server/README.md index 7df06813..10608909 100644 --- a/http-listening/README.md +++ b/http-server/README.md @@ -11,6 +11,7 @@ we use the `iris.Addr` which is an `iris.Runner` type ```go // Listening on tcp with network address 0.0.0.0:8080 +// app.Listen(":8080") is just a shortcut of: app.Run(iris.Addr(":8080")) ``` @@ -41,7 +42,7 @@ import ( "os" "net" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -66,53 +67,6 @@ func main() { } ``` -UNIX and BSD hosts can take advantage of the reuse port feature - -```go -package main - -import ( - // Package tcplisten provides customizable TCP net.Listener with various - // performance-related options: - // - // - SO_REUSEPORT. This option allows linear scaling server performance - // on multi-CPU servers. - // See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details. - // - // - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted - // connection before writing to them. - // - // - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details. - "github.com/valyala/tcplisten" - - "github.com/kataras/iris" -) - -// go get github.com/valyala/tcplisten -// go run main.go - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.HTML("<h1>Hello World!</h1>") - }) - - listenerCfg := tcplisten.Config{ - ReusePort: true, - DeferAccept: true, - FastOpen: true, - } - - l, err := listenerCfg.NewListener("tcp", ":8080") - if err != nil { - app.Logger().Fatal(err) - } - - app.Run(iris.Listener(l)) -} -``` - ### HTTP/2 and Secure If you have signed file keys you can use the `iris.TLS` to serve `https` based on those certification keys @@ -166,7 +120,7 @@ app.ConfigureHost(func(h *iris.Supervisor) { println("server terminated") }) }) -app.Run(iris.Addr(":8080")) +app.Listen(":8080") ``` Access to all hosts that serve your application can be provided by @@ -201,7 +155,7 @@ app := iris.New() app.Get("/", indexHandler) // run in different goroutine in order to not block the main "goroutine". -go app.Run(iris.Addr(":8080")) +go app.Listen(":8080") // start a second server which is listening on tcp 0.0.0.0:9090, // without "go" keyword because we want to block at the last server-run. app.NewHost(&http.Server{Addr:":9090"}).ListenAndServe() @@ -227,7 +181,7 @@ import ( "context" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) @@ -235,7 +189,7 @@ func main() { app := iris.New() iris.RegisterOnInterrupt(func() { - timeout := 5 * time.Second + timeout := 10 * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() // close all hosts @@ -246,6 +200,6 @@ func main() { ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>") }) - app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler) + app.Listen(":8080", iris.WithoutInterruptHandler) } ``` diff --git a/http-listening/custom-httpserver/easy-way/main.go b/http-server/custom-httpserver/easy-way/main.go similarity index 76% rename from http-listening/custom-httpserver/easy-way/main.go rename to http-server/custom-httpserver/easy-way/main.go index ff260302..b6f71e8a 100644 --- a/http-listening/custom-httpserver/easy-way/main.go +++ b/http-server/custom-httpserver/easy-way/main.go @@ -3,7 +3,7 @@ package main import ( "net/http" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -17,12 +17,12 @@ func main() { ctx.Writef("Hello from %s", ctx.Path()) }) - // Any custom fields here. Handler and ErrorLog are setted to the server automatically + // Any custom fields here. Handler and ErrorLog are set to the server automatically srv := &http.Server{Addr: ":8080"} // http://localhost:8080/ // http://localhost:8080/mypath - app.Run(iris.Server(srv)) // same as app.Run(iris.Addr(":8080")) + app.Run(iris.Server(srv)) // same as app.Listen(":8080") // More: // see "multi" if you need to use more than one server at the same app. diff --git a/http-listening/custom-httpserver/multi/main.go b/http-server/custom-httpserver/multi/main.go similarity index 94% rename from http-listening/custom-httpserver/multi/main.go rename to http-server/custom-httpserver/multi/main.go index d7758dac..083e8e6c 100644 --- a/http-listening/custom-httpserver/multi/main.go +++ b/http-server/custom-httpserver/multi/main.go @@ -3,7 +3,7 @@ package main import ( "net/http" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -43,5 +43,5 @@ func main() { // you can just make a new http.Server instead. // http://localhost:8080/ // http://localhost:8080/mypath - app.Run(iris.Addr(":8080")) // Block here. + app.Listen(":8080") // Block here. } diff --git a/http-listening/custom-httpserver/std-way/main.go b/http-server/custom-httpserver/std-way/main.go similarity index 92% rename from http-listening/custom-httpserver/std-way/main.go rename to http-server/custom-httpserver/std-way/main.go index d3551836..b4817d2d 100644 --- a/http-listening/custom-httpserver/std-way/main.go +++ b/http-server/custom-httpserver/std-way/main.go @@ -3,7 +3,7 @@ package main import ( "net/http" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -25,7 +25,7 @@ func main() { // http://localhost:8080/ // http://localhost:8080/mypath println("Start a server listening on http://localhost:8080") - srv.ListenAndServe() // same as app.Run(iris.Addr(":8080")) + srv.ListenAndServe() // same as app.Listen(":8080") // Notes: // Banner is not shown at all. Same for the Interrupt Handler, even if app's configuration allows them. diff --git a/http-listening/custom-listener/main.go b/http-server/custom-listener/main.go similarity index 93% rename from http-listening/custom-listener/main.go rename to http-server/custom-listener/main.go index 90d86214..eb156fd4 100644 --- a/http-listening/custom-listener/main.go +++ b/http-server/custom-listener/main.go @@ -3,7 +3,7 @@ package main import ( "net" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { diff --git a/http-listening/graceful-shutdown/custom-notifier/main.go b/http-server/graceful-shutdown/custom-notifier/main.go similarity index 82% rename from http-listening/graceful-shutdown/custom-notifier/main.go rename to http-server/graceful-shutdown/custom-notifier/main.go index f1b38197..261a46f7 100644 --- a/http-listening/graceful-shutdown/custom-notifier/main.go +++ b/http-server/graceful-shutdown/custom-notifier/main.go @@ -7,7 +7,7 @@ import ( "syscall" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -17,6 +17,7 @@ func main() { ctx.HTML("<h1>hi, I just exist in order to see if the server is closed</h1>") }) + idleConnsClosed := make(chan struct{}) go func() { ch := make(chan os.Signal, 1) signal.Notify(ch, @@ -33,14 +34,16 @@ func main() { case <-ch: println("shutdown...") - timeout := 5 * time.Second + timeout := 10 * time.Second ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout) defer cancel() app.Shutdown(ctx) + close(idleConnsClosed) } }() // Start the server and disable the default interrupt handler in order to // handle it clear and simple by our own, without any issues. - app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler) + app.Listen(":8080", iris.WithoutInterruptHandler) + <-idleConnsClosed } diff --git a/http-listening/graceful-shutdown/default-notifier/main.go b/http-server/graceful-shutdown/default-notifier/main.go similarity index 75% rename from http-listening/graceful-shutdown/default-notifier/main.go rename to http-server/graceful-shutdown/default-notifier/main.go index 0c560136..930d4a26 100644 --- a/http-listening/graceful-shutdown/default-notifier/main.go +++ b/http-server/graceful-shutdown/default-notifier/main.go @@ -4,7 +4,7 @@ import ( stdContext "context" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // Before continue: @@ -17,12 +17,14 @@ import ( func main() { app := iris.New() + idleConnsClosed := make(chan struct{}) iris.RegisterOnInterrupt(func() { - timeout := 5 * time.Second + timeout := 10 * time.Second ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout) defer cancel() // close all hosts app.Shutdown(ctx) + close(idleConnsClosed) }) app.Get("/", func(ctx iris.Context) { @@ -30,5 +32,6 @@ func main() { }) // http://localhost:8080 - app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler) + app.Listen(":8080", iris.WithoutInterruptHandler, iris.WithoutServerError(iris.ErrServerClosed)) + <-idleConnsClosed } diff --git a/http-server/h2c/go.mod b/http-server/h2c/go.mod new file mode 100644 index 00000000..7fa43615 --- /dev/null +++ b/http-server/h2c/go.mod @@ -0,0 +1,53 @@ +module github.com/kataras/iris/_examples/http-server/h2c + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + golang.org/x/net v0.24.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/http-server/h2c/go.sum b/http-server/h2c/go.sum new file mode 100644 index 00000000..94127478 --- /dev/null +++ b/http-server/h2c/go.sum @@ -0,0 +1,178 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/http-server/h2c/main.go b/http-server/h2c/main.go new file mode 100644 index 00000000..9e120a3d --- /dev/null +++ b/http-server/h2c/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "net/http" + + "github.com/kataras/iris/v12" + + "golang.org/x/net/http2" +) + +/* + Serve HTTP/2 without TLS and keep support for HTTP/1.1 +*/ + +// $ go get golang.org/x/net/http2 +// # Take a look at the golang.org/x/net/http2/h2c package as well, +// # you may want to use it. +// $ go run main.go +// $ brew install curl-openssl +// # Add curl-openssl to the front of your path. +// Test with the following commands: +// $ curl -v --http2 http://localhost:8080 +// $ curl -v --http1.1 http://localhost:8080 +func main() { + // Initialize Iris Application. + app := iris.New() + + // Build the API. + app.Any("/", index) + + // Finally, listen and serve on port 8080 using h2c. + app.Run(iris.Raw(func() error { + host := app.NewHost(&http.Server{ + Addr: ":8080", + }) + + err := http2.ConfigureServer(host.Server, &http2.Server{ + MaxConcurrentStreams: 250, + PermitProhibitedCipherSuites: true, + }) + + if err != nil { + return err + } + + return host.ListenAndServe() + })) +} + +func index(ctx iris.Context) { + ctx.WriteString("Hello, World!\n") +} diff --git a/http-server/http3-quic/go.mod b/http-server/http3-quic/go.mod new file mode 100644 index 00000000..8150cfc0 --- /dev/null +++ b/http-server/http3-quic/go.mod @@ -0,0 +1,60 @@ +module github.com/kataras/iris/_examples/http-server/http3-quic + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/quic-go/quic-go v0.42.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/onsi/ginkgo/v2 v2.9.5 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + go.uber.org/mock v0.4.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.20.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/http-server/http3-quic/go.sum b/http-server/http3-quic/go.sum new file mode 100644 index 00000000..4e3577d7 --- /dev/null +++ b/http-server/http3-quic/go.sum @@ -0,0 +1,208 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM= +github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/http-server/http3-quic/localhost.cert b/http-server/http3-quic/localhost.cert new file mode 100644 index 00000000..f440f3f1 --- /dev/null +++ b/http-server/http3-quic/localhost.cert @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+zCCAeOgAwIBAgIJAI5gi8BzcdQgMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAeFw0xOTA3MDkxMjExNDBaFw0yOTA3MDYxMjExNDBaMBQx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAM1eSGwoYznwYtt+/hrv9o4FYxJFlxIMX6WN3c2y3rr8uOwExkz2RuU9SzgF +qn0ctP1DoIKWNO0/L5j5Bjy2do0k8wHYPbTqb9zG64NGZj1lhkHgYXWyCD9U41DX +V1DiJ2JiCRBadowFRRf3/KIPf3xnrCBSCoQwdfIeJJtAF9El2/TnTrGq9N98FJqR +dCNyi+zY/iuymcA3aDOyYNjxSiuV//7ONEql5dxvRlhkjCHgrQ/rIbH/lSFAS+NG +H/6ksEBX2+Q1LlQBaFiGeEnjVpCymrRfADw7bKyqMav39Nndw4UZ1r5MSG20YtXM +dE4lA6VfAKzIZs2n87WF7OO8Y2sCAwEAAaNQME4wHQYDVR0OBBYEFKYItamcYz4Z +NiDy3I2zflU4A7ywMB8GA1UdIwQYMBaAFKYItamcYz4ZNiDy3I2zflU4A7ywMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBACSoSrEArlgPJ1ftlSMkThUR +atTqJ/yB0rSyRxsct0C04qX880VP7avnKc0UhaDruXRjdAVn4X8KI+j6azQSKT40 +KRSVBinnonE0D4DBMCUVDFtkBW3FZJXAYyIYdF/6J3Khn/ksm7VDcVxYI1rjg87B +U6aJytOkoGA2WGQOB1L0HtnTsarg/SKP/LSDUFT+XK6zTE7uogAUrpbwlpIaxc+8 +3jXvgxEdPj9Rq9Nt8/zjCkCGB2EusPPnqxcbqZb5WcGPCIlg3ChKq7vpaQld6KqG +70jT7BZ2fqWSVJ5szRoS8WpKy1SZEx/+AA7VojMzkkw4RLb66zr1v7029b51ol4= +-----END CERTIFICATE----- diff --git a/http-server/http3-quic/localhost.key b/http-server/http3-quic/localhost.key new file mode 100644 index 00000000..ee1cdae6 --- /dev/null +++ b/http-server/http3-quic/localhost.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAzV5IbChjOfBi237+Gu/2jgVjEkWXEgxfpY3dzbLeuvy47ATG +TPZG5T1LOAWqfRy0/UOggpY07T8vmPkGPLZ2jSTzAdg9tOpv3Mbrg0ZmPWWGQeBh +dbIIP1TjUNdXUOInYmIJEFp2jAVFF/f8og9/fGesIFIKhDB18h4km0AX0SXb9OdO +sar033wUmpF0I3KL7Nj+K7KZwDdoM7Jg2PFKK5X//s40SqXl3G9GWGSMIeCtD+sh +sf+VIUBL40Yf/qSwQFfb5DUuVAFoWIZ4SeNWkLKatF8APDtsrKoxq/f02d3DhRnW +vkxIbbRi1cx0TiUDpV8ArMhmzafztYXs47xjawIDAQABAoIBADvaKok7DBAquuT1 +keEP5m9lqoX8uhaMfKOnQOleJAOi+9HtYk2zyN2ui2l8XT+xSh41w2XLmQk7zQds +LCEtnEduaVQ0TWeYm5lgb+sGbW2fVQ2F82F1zWmHt+grmkr8XjYSFEor0zjjoEtn +/rzMf38mR8fzoRT9eqJhnpGQkGBnfo0SyDKIDu9yYFM7yJ5s4KOTVsMGfavjQYgJ +ssQm0KQTo8HbYHieS6drEYFRwAgT8U1NFoVq24yU+Voyy7CR5rjfOsO9gSyStVSH +nTkePmSIcpeQBfpfT3jh+STSS12eqhFCx1SqAUptUehQpOJhnWAyeSGjVLlrHqDR +bCtSWCECgYEA62J2AC8bRQ8omoEOc5h1/kwPTcLYjhOCxwwU8ky7qve173MYZUeT +dxWZx3haahccPyUKtsiGBdKYyYKSOIJMSMmwkG4uy6r5nhwNV+btEIL6Npj+XKMe +PaATA4gBLRQNwcbUlZWLYc0Y6CXFnPA+atEa7EOEBfdgUqHOym1HsAUCgYEA31rU +GPyv8R7Z1UXmxu70M8RwxKS4XhlP7RRg3Zuuqx6WWX4M85Np3wS4UWgQjGKICwoM +D4XKZQOya5p+v7a1RUZt/OD6eJ0TjypW5fBmK2yvBUQkQCsVcFjBL3F+yv2Yk1sh +KlPky4wXpDcmWXGmesgmyhpKIwL+qXEAJEaL0K8CgYABWqKlI6A7iHfKU726ioD7 +QoLABsPqJVCWRoqETk6yEBS62OWmB4Bgqf4leJrEi3d9IYBrRsIGnIyGdDrVGmLH +9GkQm6GnSEeBUlX9UHXCp4467CxiagnNfvM9DPY8xSXDHJqydZbErEJda4I0gelK +AgPuogDLa/3g289tuK015QKBgQDKcj9Qrqiiur3jC8rTgX8i9OjptAvQbsz9LL1n +4FZ/j+fjEdeXZ4RMurB+SP7G4ABDUUYBQ9lhmeo8kfpUtryzH9VNonYkoOs7lrrR +DAbvUUGKWmspJmP2QtxHrm2ofBexaKY1AXmd7Ur4c2x1IggtvgE6qn2MIojE+EGS +n8bWzQKBgQClc/j4GYNNMUYOknxXMH/ec8PBDUtn098YuFL+s7DmRHimtkkjRo1A +BtV7F8KpLruWohxXWy4QZ6HsAO255gIJ8DCbEAFCj96EHNx8KADSm3qbslu2fIB0 +zCsVaETGNAjV/d5hAEdYmgynCY49gNXV55ehV1UqzFoEfZVM9j5hUg== +-----END RSA PRIVATE KEY----- diff --git a/http-server/http3-quic/main.go b/http-server/http3-quic/main.go new file mode 100644 index 00000000..d321139b --- /dev/null +++ b/http-server/http3-quic/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/quic-go/quic-go/http3" +) + +/* + $ go get github.com/quic-go/quic-go@master +*/ + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.Writef("Hello from Index") + }) + + // app.Configure(iris.WithOptimizations, or any other core config here) + // app.Build() + // http3.ListenAndServe(":443", "./localhost.cert", "./localhost.key", app) + // OR: + app.Run(iris.Raw(func() error { + return http3.ListenAndServe(":443", "./localhost.cert", "./localhost.key", app) + })) +} diff --git a/http-server/iris-configurator-and-host-configurator/main.go b/http-server/iris-configurator-and-host-configurator/main.go new file mode 100644 index 00000000..ddece844 --- /dev/null +++ b/http-server/iris-configurator-and-host-configurator/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.ConfigureHost(func(host *iris.Supervisor) { // <- HERE: IMPORTANT + // You can control the flow or defer something using some of the host's methods: + // host.RegisterOnError + // host.RegisterOnServe + host.RegisterOnShutdown(func() { + app.Logger().Infof("Application shutdown on signal") + }) + }) + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Hello</h1>\n") + }) + + app.Listen(":8080", iris.WithoutServerError(iris.ErrServerClosed)) + + /* There are more easy ways to notify for global shutdown using the `iris.RegisterOnInterrupt` for default signal interrupt events. + You can even go it even further by looking at the: "graceful-shutdown" example. + */ +} diff --git a/http-server/listen-addr-public/main.go b/http-server/listen-addr-public/main.go new file mode 100644 index 00000000..ceb823c9 --- /dev/null +++ b/http-server/listen-addr-public/main.go @@ -0,0 +1,37 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Hello World!</h1>") + + // Will print the ngrok public domain + // that your app is using to be served online. + ctx.Writef("From: %s", + ctx.Application().ConfigurationReadOnly().GetVHost()) + }) + + app.Listen(":8080", iris.WithTunneling, iris.WithLogLevel("debug")) + + /* The full configuration can be set as: + app.Listen(":8080", iris.WithConfiguration( + iris.Configuration{ + Tunneling: iris.TunnelingConfiguration{ + AuthToken: "my-ngrok-auth-client-token", + Bin: "/bin/path/for/ngrok", + Region: "eu", + WebInterface: "127.0.0.1:4040", + Tunnels: []iris.Tunnel{ + { + Name: "MyApp", + Addr: ":8080", + Hostname: "your-custom-sub-domain.ngrok.io", // optionally + }, + }, + }, + })) + */ +} diff --git a/http-server/listen-addr/main.go b/http-server/listen-addr/main.go new file mode 100644 index 00000000..9103f799 --- /dev/null +++ b/http-server/listen-addr/main.go @@ -0,0 +1,19 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Hello World!</h1>") + }) + + // http://localhost:8080 + // Identical to: app.Run(iris.Addr(":8080")) + + app.Listen(":8080") + // To listen using keep alive tcp connection listener, + // set the KeepAlive duration configuration instead: + // app.Listen(":8080", iris.WithKeepAlive(3*time.Minute)) +} diff --git a/http-server/listen-addr/omit-server-errors/main.go b/http-server/listen-addr/omit-server-errors/main.go new file mode 100644 index 00000000..d2a62a6e --- /dev/null +++ b/http-server/listen-addr/omit-server-errors/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Hello World!</h1>") + }) + + err := app.Listen(":8080", iris.WithoutServerError(iris.ErrServerClosed)) + if err != nil { + // do something + } + // same as: + // err := app.Listen(":8080") + // import "errors" + // if errors.Is(err, iris.ErrServerClosed) { + // [...] + // } +} diff --git a/http-listening/listen-addr/omit-server-errors/main_test.go b/http-server/listen-addr/omit-server-errors/main_test.go similarity index 86% rename from http-listening/listen-addr/omit-server-errors/main_test.go rename to http-server/listen-addr/omit-server-errors/main_test.go index a1915419..89bc6bf9 100644 --- a/http-listening/listen-addr/omit-server-errors/main_test.go +++ b/http-server/listen-addr/omit-server-errors/main_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func logger(app *iris.Application) *bytes.Buffer { @@ -34,7 +34,7 @@ func TestListenAddr(t *testing.T) { app.Shutdown(ctx) }() - err := app.Run(iris.Addr(":9829")) + err := app.Listen(":9829") // in this case the error should be logged and return as well. if err != iris.ErrServerClosed { t.Fatalf("expecting err to be `iris.ErrServerClosed` but got: %v", err) @@ -45,7 +45,6 @@ func TestListenAddr(t *testing.T) { if got := log.String(); !strings.Contains(got, expectedMessage) { t.Fatalf("expecting to log to contains the:\n'%s'\ninstead of:\n'%s'", expectedMessage, got) } - } func TestListenAddrWithoutServerErr(t *testing.T) { @@ -61,10 +60,9 @@ func TestListenAddrWithoutServerErr(t *testing.T) { app.Shutdown(ctx) }() - // we disable the ErrServerClosed, so the error should be nil when server is closed by `app.Shutdown`. - - // so in this case the iris/http.ErrServerClosed should be NOT logged and NOT return. - err := app.Run(iris.Addr(":9827"), iris.WithoutServerError(iris.ErrServerClosed)) + // we disable the ErrServerClosed, so the error should be nil when server is closed by `app.Shutdown` + // or by an external issue. + err := app.Listen(":9827", iris.WithoutServerError(iris.ErrServerClosed)) if err != nil { t.Fatalf("expecting err to be nil but got: %v", err) } diff --git a/http-server/listen-letsencrypt/main.go b/http-server/listen-letsencrypt/main.go new file mode 100644 index 00000000..6908082b --- /dev/null +++ b/http-server/listen-letsencrypt/main.go @@ -0,0 +1,42 @@ +// Package main provide one-line integration with letsencrypt.org +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.Writef("Hello from SECURE SERVER!") + }) + + app.Get("/test2", func(ctx iris.Context) { + ctx.Writef("Welcome to secure server from /test2!") + }) + + app.Get("/redirect", func(ctx iris.Context) { + ctx.Redirect("/test2") + }) + + // NOTE: This will not work on domains like this, + // use real whitelisted domain(or domains split by whitespaces) + // and a non-public e-mail instead or edit your hosts file. + app.Run(iris.AutoTLS(":443", "example.com", "mail@example.com")) + + // Note: to disable automatic "http://" to "https://" redirections pass + // the `iris.AutoTLSNoRedirect` host configurator to AutoTLS function, example: + /* + var fallbackServer = func(acme func(http.Handler) http.Handler) *http.Server { + // Use any http.Server and Handler, as long as it's wrapped by `acme` one. + // In that case we share the application through non-tls users too: + srv := &http.Server{Handler: acme(app)} + go srv.ListenAndServe() + return srv + } + + app.Run(iris.AutoTLS(":443", "example.com myip", "mail@example.com", + iris.AutoTLSNoRedirect(fallbackServer))) + */ +} diff --git a/http-server/listen-tls/main.go b/http-server/listen-tls/main.go new file mode 100644 index 00000000..50d56540 --- /dev/null +++ b/http-server/listen-tls/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.Writef("Hello from the SECURE server") + }) + + app.Get("/mypath", func(ctx iris.Context) { + ctx.Writef("Hello from the SECURE server on path /mypath") + }) + + // Start the server (HTTPS) on port 443, + // and a secondary of (HTTP) on port :80 which redirects requests to their HTTPS version. + // This is a blocking func. + app.Run(iris.TLS("127.0.0.1:443", "mycert.crt", "mykey.key")) + + // Note: to disable automatic "http://" to "https://" redirections pass the `iris.TLSNoRedirect` + // host configurator to TLS function, example: + // + // app.Run(iris.TLS("127.0.0.1:443", "mycert.crt", "mykey.key", iris.TLSNoRedirect)) +} diff --git a/http-server/listen-tls/mycert.crt b/http-server/listen-tls/mycert.crt new file mode 100644 index 00000000..9db93b09 --- /dev/null +++ b/http-server/listen-tls/mycert.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUfwMd9auWixp19UnXOmyxJ9Jkv7IwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA2MjUwOTUxNDdaFw0yMTA2 +MjUwOTUxNDdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDlVGyGAQ9uyfNbwZyrtYOSjLpxf5NpNToh2OzU7gy2 +OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwje+IjGZBw8x6E+8WoGdSzbrEZ6pUV +wKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO888dwK/mbIHrHTq4nO3o0gAdAJwu +amn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA0AT8eg544GyCdyteAH11oCDsHS8/ +DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8eJohddRTK6zHe9ixZTt/soayOF7OS +QQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po6bqDnUzdnkqAAwwymQapHMuHXZKN +rhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt+0AidLRH+dCY7MS9Ngga/sAK3vID +gSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat4y0VwSyysUy887vHr6lMK5CrAT/l +Ch8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bVGYsEYrrW+bCNN9wCGYTZEyX++os9 +v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w3wPf9K4Y40MNxeR90nyX4zjXGF1/ +91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L2UBwMacsfjBbN4djOc5IuYMar/VN +GQIDAQABo1MwUTAdBgNVHQ4EFgQUtkf+yAvqgZC8f22iJny9hFEDolMwHwYDVR0j +BBgwFoAUtkf+yAvqgZC8f22iJny9hFEDolMwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAE2QasBVru618rxupyJgEHw6r4iv7sz1Afz3Q5qJ4oSA9 +xVsrVCjr3iHRFSw8Rf670E8Ffk/JjzS65mHw6zeZj/ANBKQWLjRlqzYXeetq5HzG +SIgaG7p1RFvvzz3+leFGzjinZ6sKbfB4OB72o2YN+fO8DsDxgGKll0W4KAazizSe +HY9Pgu437tWnwF16rFO3IL47n5HzYlRoGIPOpzFoNX5+fyn9GlnKEtONF2QBKTjY +rdjvqFRByDiC74d8z/Yx8IiDRn1mTcG90JLR9+c6M7fruha9Y/rJfw+4AhVh5ZDz +Bl9rGPjwEs5zwutYvVAJzs7AVcighYP1lHKoJ7DxBDQeyBsYlUNk2l6bmZgLgGUZ ++2OyWlqc/jD2GdDsIaZ4i7QqhTI/6aYZIf5zUkblKV1aMSaDulKxRv//OwW28Jax +9EEoV7VaFb3sOkB/tZGhusXeQVtdrhahT3KkZLNwmNXoXWKJ5LjeUlFWJyV6JbDe +y/PIWWCwWqyuFCSZS+Cg3RDgAzfSxkI8uVZ+IKKJS3UluDX45lxXtbRrvTQ+oDrA +6ga5c1Vz9C4kn1K5yW4d7QIvg6vPiy7gvl+//sz9oxUM3yswInDBY0HKLgT0Uq9b +YzLDh2RSaHsgHMPy2BKqR+q2N+lpg7inAWuJM1Huq6eHFqhiyQkzsfscBd1Dpm8= +-----END CERTIFICATE----- diff --git a/http-server/listen-tls/mykey.key b/http-server/listen-tls/mykey.key new file mode 100644 index 00000000..39f7b3af --- /dev/null +++ b/http-server/listen-tls/mykey.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDlVGyGAQ9uyfNb +wZyrtYOSjLpxf5NpNToh2OzU7gy2OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwj +e+IjGZBw8x6E+8WoGdSzbrEZ6pUVwKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO +888dwK/mbIHrHTq4nO3o0gAdAJwuamn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA +0AT8eg544GyCdyteAH11oCDsHS8/DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8e +JohddRTK6zHe9ixZTt/soayOF7OSQQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po +6bqDnUzdnkqAAwwymQapHMuHXZKNrhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt ++0AidLRH+dCY7MS9Ngga/sAK3vIDgSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat +4y0VwSyysUy887vHr6lMK5CrAT/lCh8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bV +GYsEYrrW+bCNN9wCGYTZEyX++os9v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w +3wPf9K4Y40MNxeR90nyX4zjXGF1/91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L +2UBwMacsfjBbN4djOc5IuYMar/VNGQIDAQABAoICAQCtWx1SSxjkcerxsLEDKApW +zOTfiUXgoOjZz0ZwS6b2VWDfyWAPU1r4ps39KaU+F+lzDhWjpYQqhbMjG7G9QMTs +bQvkEQLAaQ5duU5NPgQG1oCUsj8rMSBpGGz4jBnm834QHMk7VTjYYbKu3WTyo8cU +U2/+UDEkfxRlC+IkCmMFv1FxgMZ5PbktC/eDnYMhP2Pq7Q5ZWAVHymk9IMK0LHwm +Kdg842K4A3zTXwGkGwetDCMm+YQpG5TxqX/w82BRcCuTR5h8fnYSsWLEIvKwWyIl +ppcjaUnrFPG2yhxLqWUIKPpehuEjjhQMt9rDNoh6MHsJZZY5Dp5eq91EIvLoLQ99 +hXBmD4P8LDop4r0jniPZJi/ACsaD0jBooA4525+Kouq7RP28Jp/pek7lVOOcBgRv +D3zyESbKfqoaOfyfQ2ff4sILnTAr4V2nq3ekphGEYJrWN0ZoADcLdnr1cZ8L+VBI +o/4mi5/3HID/UEDliHSa97hxxGBEqTto0ZuXuNwfwx5ho33uVT6zNwRgiJ62Bgu3 +Fhk/wVGuZxWvb1KHUNInG9cvsslhO4Vu9wJvYj91BnRq36rsyKKid5DrU+PNgmog +lw3IXQpTojyRCYPuG9TKqEZ6b+so7GTKhBOjiwaupMOletVRGSAdbE81VN6HtxNW +aj39+FnxzMAlsieib+PBAQKCAQEA+t1fOYSaZBo7pZUmo2S0zulUEJjrYRGKJlWJ +4psWSwFu/7/3UL4q0RBQaSRew9u/YSpaNlBYfcpnFVOjiLwHq5Hx46Eq0BuKsNlJ +1/qxw9qjHqcrOre6K4/7NaWLPuM9fEmV+3MhFVXgv+WC5BHOowRTlOG30vIcC1J2 +L5xsBUsxDDY13cD1bLKRmFcyMFM8y7wMZmo7H/WfVmyoPKQaC43pTcmIXH0Jr2Ws +Wsfh18mhjtamaOPEFx5K0x4d0PI8tW5ouiUUkVIDaue27XfS969qEChv768/44eX +WeqcekaG9jv2noMClt79rYd3Lne9HkgY6IT9FT+JqXfu+KYwuQKCAQEA6gYzUsGB +9GQO8DE8AYn7JwNOtg1X4zKakXiGxH+nuZb7wJjAeGdYqTHySxPBXg0A2nDwoyz5 +4sAdLAr3FZoIvTzo7M5KIKFDzfyDmQDavhroH1mBAEiqKGNniP+RND3nWBBqDK1R +qcqbhI3Kj5Ycany6a4nP+hZRBIyT9sfJ0S0YruSY8IGXgDwhlJrZ7bsWMZylrgD/ +1qnPL0KqVBY8YR8msRj88h72IlD5o0kwvisOIvyhA0YgwGBb6lg7A+DifiF03ZlS +2yELbIkKDVr+p3jC7MBh4B+OJY68AMl6wVjAaDM1AZnpjKE5YmZg5+Ks5823zILo +PrSB9hn0+DIPYQKCAQEAh9x+JuNmzhHa/dkiHNl8hpadHYQD7gUWwZ4P1/bQAv0a +xU2MvmDPRXxFYDv/SqlnI1NRmhq3YiDM5SLv7SyQJt4al4IAcsaHvTFgqaSuw3hU +YVR9uAYqwE7w6OPn3r4o3Xfoz05Ru4FP//1nfucZ9vVv4rC/4nGWuJcHRM+9PLy1 +KnztfVR0VlL7QPrwRnW99kS4nnqn3K4khiTAlF73cAyCLsuXmydoqGIzDtMzv68G +XRpo82NvHmoccevcj/2w3T2XYECWvAEjsrEdQ8xiKBwLIAcWYEOUIUCcumiyKBKs +IwzkioI/U8AeuO0lobfdZ1n6i2sCuZA4mNxIQseWmQKCAQEA5YkfXdQeuq5JWJ1x +1bCYfjNoSHfd9CH2KSimRqVOxWGpm8Y3QeFbvNgYZjsCNlVauOZ9oA7FKfp0onY+ +0xk56SKM83eCjW6fKrK6AKAt7LhHZDhNpxGek+6r5luE+FCfUGkJG1YD+x2WW/UW +8K6zQF8GGeQZ8Zlh7axUlIBxGpG43BGrUHpLNqPD7BXWGq6dnhufBYRFay8y34/r +sH3+yuPa92ki7/geQppZwCZRgLSKMRbIdoWaKhZZEQlpGOzCOiRmk9OGyRcoNVRU +X7UYgPqZdc1cMo/AxGWzULJNjMaYMZvIKcHkqOKZfkIcWlSictn7pMPhN1+k+NWM +yMORAQKCAQAyXl02h/c2ihx6cjKlnNeDr2ZfzkoiAvFuKaoAR+KVvb9F9X7ZgKSi +wudZyelTglIVCYXeRmG09uX3rNGCzFrweRwgn6x/8DnN5pMRJVZOXFdgR+V9uKep +K6F7DYbPyggvLOAsezB+09i9lwxM+XdA2whVpL5NFR1rGfFglnE1EQHcEvNONkcv +0h8x9cNSptJyRDLiTIKI9EhonuzwzkGpvjULQE8MLbT8PbjoLFINcE9ZWhwtyw0V +XO32KE8iLKt3KzHz9CfTRCI3M7DwD752AC6zRr8ZS/HXzs+5WTkdVVEtRC7Abd3y +W2TzuSMYNDu876twbTVQJED3mwOAQ3J7 +-----END PRIVATE KEY----- diff --git a/http-listening/listen-unix/main.go b/http-server/listen-unix/main.go similarity index 69% rename from http-listening/listen-unix/main.go rename to http-server/listen-unix/main.go index 6e8d69de..73096504 100644 --- a/http-listening/listen-unix/main.go +++ b/http-server/listen-unix/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/core/netutil" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/core/netutil" ) func main() { @@ -15,5 +15,3 @@ func main() { app.Run(iris.Listener(l)) } - -// Look "custom-listener/unix-reuseport" too. diff --git a/http-listening/notify-on-shutdown/main.go b/http-server/notify-on-shutdown/main.go similarity index 57% rename from http-listening/notify-on-shutdown/main.go rename to http-server/notify-on-shutdown/main.go index 67400aa8..b35a4818 100644 --- a/http-listening/notify-on-shutdown/main.go +++ b/http-server/notify-on-shutdown/main.go @@ -1,34 +1,33 @@ package main import ( - stdContext "context" + "context" "time" - "github.com/kataras/iris" - "github.com/kataras/iris/core/host" + "github.com/kataras/iris/v12" ) func main() { app := iris.New() app.Get("/", func(ctx iris.Context) { - ctx.HTML("<h1>Hello, try to refresh the page after ~10 secs</h1>") + ctx.HTML("<h1>Hello, try to refresh the page after ~5 secs</h1>") }) - // app.ConfigureHost(configureHost) -> or pass "configureHost" as `app.Addr` argument, same result. - - app.Logger().Info("Wait 10 seconds and check your terminal again") + app.Logger().Info("Wait 5 seconds and check your terminal again") // simulate a shutdown action here... go func() { - <-time.After(10 * time.Second) - timeout := 5 * time.Second - ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout) + <-time.After(5 * time.Second) + timeout := 10 * time.Second + ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() // close all hosts, this will notify the callback we had register // inside the `configureHost` func. app.Shutdown(ctx) }() + // app.ConfigureHost(configureHost) -> or pass "configureHost" as `app.Addr` argument, same result. + // start the server as usual, the only difference is that // we're adding a second (optional) function // to configure the just-created host supervisor. @@ -37,16 +36,24 @@ func main() { // wait 10 seconds and check your terminal. app.Run(iris.Addr(":8080", configureHost), iris.WithoutServerError(iris.ErrServerClosed)) + time.Sleep(500 * time.Millisecond) // give time to the separate go routine(`onServerShutdown`) to finish. + + /* See + iris.RegisterOnInterrupt(callback) for global catch of the CTRL/CMD+C and OS events. + Look at the "graceful-shutdown" example for more. + */ +} + +func onServerShutdown() { + println("server is closed") } -func configureHost(su *host.Supervisor) { +func configureHost(su *iris.Supervisor) { // here we have full access to the host that will be created // inside the `app.Run` function or `NewHost`. // // we're registering a shutdown "event" callback here: - su.RegisterOnShutdown(func() { - println("server is closed") - }) + su.RegisterOnShutdown(onServerShutdown) // su.RegisterOnError // su.RegisterOnServe } diff --git a/http-server/socket-sharding/main.go b/http-server/socket-sharding/main.go new file mode 100644 index 00000000..bd5d7e4a --- /dev/null +++ b/http-server/socket-sharding/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" +) + +func main() { + startup := time.Now() + + app := iris.New() + app.Get("/", func(ctx iris.Context) { + s := startup.Format(ctx.Application().ConfigurationReadOnly().GetTimeFormat()) + ctx.Writef("This server started at: %s\n", s) + }) + + // This option allows linear scaling server performance on multi-CPU servers. + // See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details. + app.Listen(":8080", iris.WithSocketSharding) +} diff --git a/http-server/timeout/main.go b/http-server/timeout/main.go new file mode 100644 index 00000000..11aa5dbd --- /dev/null +++ b/http-server/timeout/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "context" + "time" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/test", func(ctx iris.Context) { + w := new(worker) + result := w.Work(ctx) + ctx.WriteString(result) + }) + + app.Listen(":8080", iris.WithTimeout(4*time.Second)) +} + +type worker struct{} + +func (w *worker) Work(ctx context.Context) string { + t := time.Tick(time.Second) + times := 0 + for { + select { + case <-ctx.Done(): + println("context.Done: canceled") + return "Work canceled" + case <-t: + times++ + println("Doing some work...") + + if times > 5 { + return "Work is done with success" + } + } + } + + return "nothing to do here" +} diff --git a/http_request/README.md b/http_request/README.md deleted file mode 100644 index 98e7b09c..00000000 --- a/http_request/README.md +++ /dev/null @@ -1 +0,0 @@ -The `context.Request()` returns the same *http.Request you already know, the examples show some places where the Context uses this object. Besides that you can use it as you did before iris. \ No newline at end of file diff --git a/http_request/request-logger/main.go b/http_request/request-logger/main.go deleted file mode 100644 index 888de7a6..00000000 --- a/http_request/request-logger/main.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/logger" -) - -func main() { - app := iris.New() - - customLogger := logger.New(logger.Config{ - // Status displays status code - Status: true, - // IP displays request's remote address - IP: true, - // Method displays the http method - Method: true, - // Path displays the request path - Path: true, - // Query appends the url query to the Path. - Query: true, - - //Columns: true, - - // if !empty then its contents derives from `ctx.Values().Get("logger_message") - // will be added to the logs. - MessageContextKeys: []string{"logger_message"}, - - // if !empty then its contents derives from `ctx.GetHeader("User-Agent") - MessageHeaderKeys: []string{"User-Agent"}, - }) - - app.Use(customLogger) - - h := func(ctx iris.Context) { - ctx.Writef("Hello from %s", ctx.Path()) - } - app.Get("/", h) - - app.Get("/1", h) - - app.Get("/2", h) - - // http errors have their own handlers, therefore - // registering a middleare should be done manually. - /* - app.OnErrorCode(404 ,customLogger, func(ctx iris.Context) { - ctx.Writef("My Custom 404 error page ") - }) - */ - // or catch all http errors: - app.OnAnyErrorCode(customLogger, func(ctx iris.Context) { - // this should be added to the logs, at the end because of the `logger.Config#MessageContextKey` - ctx.Values().Set("logger_message", - "a dynamic message passed to the logs") - ctx.Writef("My Custom error page") - }) - - // http://localhost:8080 - // http://localhost:8080/1 - // http://localhost:8080/2 - // http://lcoalhost:8080/notfoundhere - // see the output on the console. - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) - -} diff --git a/http_request/request-logger/request-logger-file/main.go b/http_request/request-logger/request-logger-file/main.go deleted file mode 100644 index dc37f8a1..00000000 --- a/http_request/request-logger/request-logger-file/main.go +++ /dev/null @@ -1,108 +0,0 @@ -package main - -import ( - "os" - "strings" - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/logger" -) - -const deleteFileOnExit = true - -func main() { - app := iris.New() - r, close := newRequestLogger() - defer close() - - app.Use(r) - app.OnAnyErrorCode(r, func(ctx iris.Context) { - ctx.HTML("<h1> Error: Please try <a href ='/'> this </a> instead.</h1>") - }) - - h := func(ctx iris.Context) { - ctx.Writef("Hello from %s", ctx.Path()) - } - - app.Get("/", h) - - app.Get("/1", h) - - app.Get("/2", h) - - // http://localhost:8080 - // http://localhost:8080/1 - // http://localhost:8080/2 - // http://lcoalhost:8080/notfoundhere - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) -} - -// get a filename based on the date, file logs works that way the most times -// but these are just a sugar. -func todayFilename() string { - today := time.Now().Format("Jan 02 2006") - return today + ".txt" -} - -func newLogFile() *os.File { - filename := todayFilename() - // open an output file, this will append to the today's file if server restarted. - f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - panic(err) - } - - return f -} - -var excludeExtensions = [...]string{ - ".js", - ".css", - ".jpg", - ".png", - ".ico", - ".svg", -} - -func newRequestLogger() (h iris.Handler, close func() error) { - close = func() error { return nil } - - c := logger.Config{ - Status: true, - IP: true, - Method: true, - Path: true, - Columns: true, - } - - logFile := newLogFile() - close = func() error { - err := logFile.Close() - if deleteFileOnExit { - err = os.Remove(logFile.Name()) - } - return err - } - - c.LogFunc = func(now time.Time, latency time.Duration, status, ip, method, path string, message interface{}, headerMessage interface{}) { - output := logger.Columnize(now.Format("2006/01/02 - 15:04:05"), latency, status, ip, method, path, message, headerMessage) - logFile.Write([]byte(output)) - } - - // we don't want to use the logger - // to log requests to assets and etc - c.AddSkipper(func(ctx iris.Context) bool { - path := ctx.Path() - for _, ext := range excludeExtensions { - if strings.HasSuffix(path, ext) { - return true - } - } - return false - }) - - h = logger.New(c) - - return -} diff --git a/http_request/upload-files/main.go b/http_request/upload-files/main.go deleted file mode 100644 index 25058b6e..00000000 --- a/http_request/upload-files/main.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "crypto/md5" - "fmt" - "io" - "mime/multipart" - "strconv" - "strings" - "time" - - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.RegisterView(iris.HTML("./templates", ".html")) - - // Serve the upload_form.html to the client. - app.Get("/upload", func(ctx iris.Context) { - // create a token (optionally). - - now := time.Now().Unix() - h := md5.New() - io.WriteString(h, strconv.FormatInt(now, 10)) - token := fmt.Sprintf("%x", h.Sum(nil)) - - // render the form with the token for any use you'd like. - ctx.View("upload_form.html", token) - }) - - // Handle the post request from the upload_form.html to the server. - app.Post("/upload", func(ctx iris.Context) { - // - // UploadFormFiles - // uploads any number of incoming files (multiple property on the form input). - // - - // second argument is totally optionally, - // it can be used to change a file's name based on the request, - // at this example we will showcase how to use it - // by prefixing the uploaded file with the current user's ip. - ctx.UploadFormFiles("./uploads", beforeSave) - }) - - // start the server at http://localhost:8080 with post limit at 32 MB. - app.Run(iris.Addr(":8080"), iris.WithPostMaxMemory(32<<20)) -} - -func beforeSave(ctx iris.Context, file *multipart.FileHeader) { - ip := ctx.RemoteAddr() - // make sure you format the ip in a way - // that can be used for a file name (simple case): - ip = strings.Replace(ip, ".", "_", -1) - ip = strings.Replace(ip, ":", "_", -1) - - // you can use the time.Now, to prefix or suffix the files - // based on the current time as well, as an exercise. - // i.e unixTime := time.Now().Unix() - // prefix the Filename with the $IP- - // no need for more actions, internal uploader will use this - // name to save the file into the "./uploads" folder. - file.Filename = ip + "-" + file.Filename -} diff --git a/http_responsewriter/README.md b/http_responsewriter/README.md deleted file mode 100644 index 4e743060..00000000 --- a/http_responsewriter/README.md +++ /dev/null @@ -1 +0,0 @@ -The `context.ResponseWriter()` returns an enchament version of a http.ResponseWriter, the examples show some places where the Context uses this object. Besides that you can use it as you did before iris. \ No newline at end of file diff --git a/http_responsewriter/quicktemplate/controllers/execute_template.go b/http_responsewriter/quicktemplate/controllers/execute_template.go deleted file mode 100644 index f952db3c..00000000 --- a/http_responsewriter/quicktemplate/controllers/execute_template.go +++ /dev/null @@ -1,14 +0,0 @@ -package controllers - -import ( - "github.com/iris-contrib/examples/http_responsewriter/quicktemplate/templates" - - "github.com/kataras/iris" -) - -// ExecuteTemplate renders a "tmpl" partial template to the `context#ResponseWriter`. -func ExecuteTemplate(ctx iris.Context, tmpl templates.Partial) { - ctx.Gzip(true) - ctx.ContentType("text/html") - templates.WriteTemplate(ctx.ResponseWriter(), tmpl) -} diff --git a/http_responsewriter/stream-writer/main.go b/http_responsewriter/stream-writer/main.go deleted file mode 100644 index 6d6179f4..00000000 --- a/http_responsewriter/stream-writer/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "fmt" // just an optional helper - "io" - "time" // showcase the delay - - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.ContentType("text/html") - ctx.Header("Transfer-Encoding", "chunked") - i := 0 - ints := []int{1, 2, 3, 5, 7, 9, 11, 13, 15, 17, 23, 29} - // Send the response in chunks and wait for half a second between each chunk. - ctx.StreamWriter(func(w io.Writer) bool { - fmt.Fprintf(w, "Message number %d<br>", ints[i]) - time.Sleep(500 * time.Millisecond) // simulate delay. - if i == len(ints)-1 { - return false // close and flush - } - i++ - return true // continue write - }) - }) - - type messageNumber struct { - Number int `json:"number"` - } - - app.Get("/alternative", func(ctx iris.Context) { - ctx.ContentType("application/json") - ctx.Header("Transfer-Encoding", "chunked") - i := 0 - ints := []int{1, 2, 3, 5, 7, 9, 11, 13, 15, 17, 23, 29} - // Send the response in chunks and wait for half a second between each chunk. - for { - ctx.JSON(messageNumber{Number: ints[i]}) - ctx.WriteString("\n") - time.Sleep(500 * time.Millisecond) // simulate delay. - if i == len(ints)-1 { - break - } - i++ - ctx.ResponseWriter().Flush() - } - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/http_responsewriter/transactions/main.go b/http_responsewriter/transactions/main.go deleted file mode 100644 index ce8fcd9d..00000000 --- a/http_responsewriter/transactions/main.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/context" -) - -func main() { - app := iris.New() - - // subdomains works with all available routers, like other features too. - - app.Get("/", func(ctx context.Context) { - ctx.BeginTransaction(func(t *context.Transaction) { - // OPTIONAl STEP: , if true then the next transictions will not be executed if this transiction fails - // t.SetScope(context.RequestTransactionScope) - - // OPTIONAL STEP: - // create a new custom type of error here to keep track of the status code and reason message - err := context.NewTransactionErrResult() - - // we should use t.Context if we want to rollback on any errors lives inside this function clojure. - t.Context().Text("Blablabla this should not be sent to the client because we will fill the err with a message and status") - - // virtualize a fake error here, for the shake of the example - fail := true - if fail { - err.StatusCode = iris.StatusInternalServerError - // NOTE: if empty reason then the default or the custom http error will be fired (like ctx.FireStatusCode) - err.Reason = "Error: Virtual failure!!" - } - - // OPTIONAl STEP: - // but useful if we want to post back an error message to the client if the transaction failed. - // if the reason is empty then the transaction completed successfully, - // otherwise we rollback the whole response writer's body, - // headers and cookies, status code and everything lives inside this transaction - t.Complete(err) - }) - - ctx.BeginTransaction(func(t *context.Transaction) { - t.Context().HTML("<h1>This will sent at all cases because it lives on different transaction and it doesn't fails</h1>") - // * if we don't have any 'throw error' logic then no need of scope.Complete() - }) - - // OPTIONALLY, depends on the usage: - // at any case, what ever happens inside the context's transactions send this to the client - ctx.HTML("<h1>Let's add a second html message to the response, " + - "if the transaction was failed and it was request scoped then this message would " + - "not been shown. But it has a transient scope(default) so, it is visible as expected!</h1>") - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/http_responsewriter/write-gzip/main.go b/http_responsewriter/write-gzip/main.go deleted file mode 100644 index 2e16650e..00000000 --- a/http_responsewriter/write-gzip/main.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "github.com/kataras/iris" - -func main() { - app := iris.New() - app.Get("/", func(ctx iris.Context) { - ctx.WriteGzip([]byte("Hello World!")) - ctx.Header("X-Custom", - "Headers can be set here after WriteGzip as well, because the data are kept before sent to the client when using the context's GzipResponseWriter and ResponseRecorder.") - }) - - app.Get("/2", func(ctx iris.Context) { - // same as the `WriteGzip`. - // However GzipResponseWriter gives you more options, like - // reset data, disable and more, look its methods. - ctx.GzipResponseWriter().WriteString("Hello World!") - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/http_responsewriter/write-rest/main.go b/http_responsewriter/write-rest/main.go deleted file mode 100644 index 7527b1e8..00000000 --- a/http_responsewriter/write-rest/main.go +++ /dev/null @@ -1,94 +0,0 @@ -package main - -import ( - "encoding/xml" - - "github.com/kataras/iris" - "github.com/kataras/iris/context" -) - -// User bind struct -type User struct { - Firstname string `json:"firstname"` - Lastname string `json:"lastname"` - City string `json:"city"` - Age int `json:"age"` -} - -// ExampleXML just a test struct to view represents xml content-type -type ExampleXML struct { - XMLName xml.Name `xml:"example"` - One string `xml:"one,attr"` - Two string `xml:"two,attr"` -} - -func main() { - app := iris.New() - - // Read - app.Post("/decode", func(ctx iris.Context) { - var user User - ctx.ReadJSON(&user) - - ctx.Writef("%s %s is %d years old and comes from %s!", user.Firstname, user.Lastname, user.Age, user.City) - }) - - // Write - app.Get("/encode", func(ctx iris.Context) { - peter := User{ - Firstname: "John", - Lastname: "Doe", - City: "Neither FBI knows!!!", - Age: 25, - } - - // Manually setting a content type: ctx.ContentType("application/javascript") - ctx.JSON(peter) - }) - - // Other content types, - - app.Get("/binary", func(ctx iris.Context) { - // useful when you want force-download of contents of raw bytes form. - ctx.Binary([]byte("Some binary data here.")) - }) - - app.Get("/text", func(ctx iris.Context) { - ctx.Text("Plain text here") - }) - - app.Get("/json", func(ctx iris.Context) { - ctx.JSON(map[string]string{"hello": "json"}) // or myjsonStruct{hello:"json} - }) - - app.Get("/jsonp", func(ctx iris.Context) { - ctx.JSONP(map[string]string{"hello": "jsonp"}, context.JSONP{Callback: "callbackName"}) - }) - - app.Get("/xml", func(ctx iris.Context) { - ctx.XML(ExampleXML{One: "hello", Two: "xml"}) // or iris.Map{"One":"hello"...} - }) - - app.Get("/markdown", func(ctx iris.Context) { - ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris")) - }) - - // http://localhost:8080/decode - // http://localhost:8080/encode - // - // http://localhost:8080/binary - // http://localhost:8080/text - // http://localhost:8080/json - // http://localhost:8080/jsonp - // http://localhost:8080/xml - // http://localhost:8080/markdown - // - // `iris.WithOptimizations` is an optional configurator, - // if passed to the `Run` then it will ensure that the application - // response to the client as fast as possible. - // - // - // `iris.WithoutServerError` is an optional configurator, - // if passed to the `Run` then it will not print its passed error as an actual server error. - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations) -} diff --git a/i18n/basic/hosts b/i18n/basic/hosts new file mode 100644 index 00000000..fb394e4b --- /dev/null +++ b/i18n/basic/hosts @@ -0,0 +1,26 @@ +# Copyright (c) 1993-2009 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. +# +# This file contains the mappings of IP addresses to host names. Each +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding host name. +# The IP address and the host name should be separated by at least one +# space. +# +# Additionally, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host + +# localhost name resolution is handled within DNS itself. +# 127.0.0.1 localhost +# ::1 localhost +127.0.0.1 mydomain.com +127.0.0.1 en.mydomain.com +127.0.0.1 el.mydomain.com +127.0.0.1 el-gr.mydomain.com +127.0.0.1 zh.mydomain.com \ No newline at end of file diff --git a/i18n/basic/locales/el-GR/locale_el-GR.ini b/i18n/basic/locales/el-GR/locale_el-GR.ini new file mode 100644 index 00000000..31ac5689 --- /dev/null +++ b/i18n/basic/locales/el-GR/locale_el-GR.ini @@ -0,0 +1,2 @@ +hi = γεια, %s +userProfilePublicDescription = <a href="%s">περιγραφή προφιλ</a> \ No newline at end of file diff --git a/i18n/basic/locales/el-GR/locale_multi_first_el-GR.yml b/i18n/basic/locales/el-GR/locale_multi_first_el-GR.yml new file mode 100644 index 00000000..0228ac83 --- /dev/null +++ b/i18n/basic/locales/el-GR/locale_multi_first_el-GR.yml @@ -0,0 +1 @@ +key1: "αυτό είναι μια τιμή από το πρώτο αρχείο: locale_multi_first" \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_multi_second_el-GR.ini b/i18n/basic/locales/el-GR/locale_multi_second_el-GR.ini similarity index 100% rename from miscellaneous/i18n/locales/locale_multi_second_el-GR.ini rename to i18n/basic/locales/el-GR/locale_multi_second_el-GR.ini diff --git a/i18n/basic/locales/en-US/locale_en-US.ini b/i18n/basic/locales/en-US/locale_en-US.ini new file mode 100644 index 00000000..2c24e82a --- /dev/null +++ b/i18n/basic/locales/en-US/locale_en-US.ini @@ -0,0 +1,2 @@ +hi = hello, %s +userProfilePublicDescription = <a href="%s">profile description</a> \ No newline at end of file diff --git a/i18n/basic/locales/en-US/locale_multi_first_en-US.yml b/i18n/basic/locales/en-US/locale_multi_first_en-US.yml new file mode 100644 index 00000000..2bd37d5e --- /dev/null +++ b/i18n/basic/locales/en-US/locale_multi_first_en-US.yml @@ -0,0 +1 @@ +key1: "this is a value from the first file: locale_multi_first" \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_multi_second_en-US.ini b/i18n/basic/locales/en-US/locale_multi_second_en-US.ini similarity index 100% rename from miscellaneous/i18n/locales/locale_multi_second_en-US.ini rename to i18n/basic/locales/en-US/locale_multi_second_en-US.ini diff --git a/i18n/basic/locales/zh-CN/locale_zh-CN.ini b/i18n/basic/locales/zh-CN/locale_zh-CN.ini new file mode 100644 index 00000000..8ccd66fa --- /dev/null +++ b/i18n/basic/locales/zh-CN/locale_zh-CN.ini @@ -0,0 +1,2 @@ +hi = 您好,%s +userProfilePublicDescription = <a href="%s">个人资料描述</a> \ No newline at end of file diff --git a/i18n/basic/main.go b/i18n/basic/main.go new file mode 100644 index 00000000..6bdd77c7 --- /dev/null +++ b/i18n/basic/main.go @@ -0,0 +1,128 @@ +package main + +import ( + "fmt" + "html/template" + + "github.com/kataras/iris/v12" +) + +/* + See i18n-template for a more advanced translation key-values. +*/ + +func newApp() *iris.Application { + app := iris.New() + + // Configure i18n. + // + // app.I18n.Subdomain = false to disable resolve lang code from subdomain. + // app.I18n.LoadAssets for go-bindata. + + // Default values: + // app.I18n.URLParameter = "lang" + // app.I18n.Subdomain = true + // + // Set to false to disallow path (local) redirects, + // see https://github.com/kataras/iris/issues/1369. + // app.I18n.PathRedirect = true + // + // See `app.I18n.ExtractFunc = func(ctx iris.Context) string` or + // `ctx.SetLanguage(langCode string)` to change the extracted language from a request. + // + // Use DefaultMessageFunc to customize the return value of a not found key or lang. + // All language inputs fallback to the default locale if not matched. + // This is why this one accepts both input and matched languages, + // so the caller can be more expressful knowing those. + // Defaults to nil. + app.I18n.DefaultMessageFunc = func(langInput, langMatched, key string, args ...interface{}) string { + msg := fmt.Sprintf("user language input: %s: matched as: %s: not found key: %s: args: %v", langInput, langMatched, key, args) + app.Logger().Warn(msg) + return msg + } + // Load i18n when customizations are set in place. + // + // First parameter: Glob filpath patern, + // Second variadic parameter: Optional language tags, the first one is the default/fallback one. + err := app.I18n.Load("./locales/*/*", "en-US", "el-GR", "zh-CN") + if err != nil { + panic(err) + } + + app.Get("/not-matched", func(ctx iris.Context) { + text := ctx.Tr("not_found_key", "some", "values", 42) + ctx.WriteString(text) + // user language input: en-gb: matched as: en-US: not found key: not_found_key: args: [some values 42] + }) + + app.Get("/", func(ctx iris.Context) { + hi := ctx.Tr("hi", "iris") + locale := ctx.GetLocale() + + ctx.Writef("From the language %s translated output: %s", locale.Language(), hi) + }) + + app.Get("/some-path", func(ctx iris.Context) { + ctx.Writef("%s", ctx.Tr("hi", "iris")) + }) + + app.Get("/other", func(ctx iris.Context) { + language := ctx.GetLocale().Language() + + fromFirstFileValue := ctx.Tr("key1") + fromSecondFileValue := ctx.Tr("key2") + ctx.Writef("From the language: %s, translated output:\n%s=%s\n%s=%s", + language, "key1", fromFirstFileValue, + "key2", fromSecondFileValue) + }) + + // using in inside your views: + view := iris.HTML("./views", ".html") + app.RegisterView(view) + + app.Get("/templates", func(ctx iris.Context) { + if err := ctx.View("index.html", iris.Map{ + "tr": ctx.Tr, // word, arguments... {call .tr "hi" "iris"}} + "trUnsafe": func(message string, args ...interface{}) template.HTML { + return template.HTML(ctx.Tr(message, args...)) + }, + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + + // Note that, + // Iris automatically adds a "tr" global template function as well, + // the only difference is the way you call it inside your templates and + // that it accepts a language code as its first argument: {{ tr "el-GR" "hi" "iris"}} + }) + // + + return app +} + +func main() { + app := newApp() + + // go to http://localhost:8080/el-gr/some-path + // ^ (by path prefix) + // + // or http://el.mydomain.com8080/some-path + // ^ (by subdomain - test locally with the hosts file) + // + // or http://localhost:8080/zh-CN/templates + // ^ (by path prefix with uppercase) + // + // or http://localhost:8080/some-path?lang=el-GR + // ^ (by url parameter) + // + // or http://localhost:8080 (default is en-US) + // or http://localhost:8080/?lang=zh-CN + // + // go to http://localhost:8080/other?lang=el-GR + // or http://localhost:8080/other (default is en-US) + // or http://localhost:8080/other?lang=en-US + // + // or use cookies to set the language. + app.Listen(":8080", iris.WithSitemap("http://localhost:8080")) +} diff --git a/i18n/basic/main_test.go b/i18n/basic/main_test.go new file mode 100644 index 00000000..f25c4e2c --- /dev/null +++ b/i18n/basic/main_test.go @@ -0,0 +1,88 @@ +package main + +import ( + "fmt" + "strings" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestI18n(t *testing.T) { + app := newApp() + + const ( + expectedf = "From the language %s translated output: %s" + + enUS = "hello, iris" + elGR = "γεια, iris" + zhCN = "您好,iris" + ) + + var ( + tests = map[string]string{ + "en-US": fmt.Sprintf(expectedf, "en-US", enUS), + "el-GR": fmt.Sprintf(expectedf, "el-GR", elGR), + "zh-CN": fmt.Sprintf(expectedf, "zh-CN", zhCN), + } + + elgrMulti = fmt.Sprintf("From the language: %s, translated output:\n%s=%s\n%s=%s", "el-GR", + "key1", + "αυτό είναι μια τιμή από το πρώτο αρχείο: locale_multi_first", + "key2", + "αυτό είναι μια τιμή από το δεύτερο αρχείο μετάφρασης: locale_multi_second") + enusMulti = fmt.Sprintf("From the language: %s, translated output:\n%s=%s\n%s=%s", "en-US", + "key1", + "this is a value from the first file: locale_multi_first", + "key2", + "this is a value from the second file: locale_multi_second") + ) + + e := httptest.New(t, app) + // default should be en-US. + e.GET("/").Expect().Status(httptest.StatusOK).Body().IsEqual(tests["en-US"]) + + for lang, body := range tests { + e.GET("/").WithQueryString("lang=" + lang).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + + // test lowercase. + e.GET("/").WithQueryString("lang=" + strings.ToLower(lang)).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + + // test first part (e.g. en instead of en-US). + langFirstPart := strings.Split(lang, "-")[0] + e.GET("/").WithQueryString("lang=" + langFirstPart).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + + // test accept-language header prefix (i18n wrapper). + e.GET("/"+lang).WithHeader("Accept-Language", lang).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + + // test path prefix (i18n router wrapper). + e.GET("/" + lang).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + + // test path prefix with first part. + e.GET("/" + langFirstPart).Expect().Status(httptest.StatusOK). + Body().IsEqual(body) + } + + e.GET("/other").WithQueryString("lang=el-GR").Expect().Status(httptest.StatusOK). + Body().IsEqual(elgrMulti) + e.GET("/other").WithQueryString("lang=en-US").Expect().Status(httptest.StatusOK). + Body().IsEqual(enusMulti) + + // test path prefix (i18n router wrapper). + e.GET("/el-gr/other").Expect().Status(httptest.StatusOK). + Body().IsEqual(elgrMulti) + e.GET("/en/other").Expect().Status(httptest.StatusOK). + Body().IsEqual(enusMulti) + + e.GET("/el-GRtemplates").Expect().Status(httptest.StatusNotFound) + e.GET("/el-templates").Expect().Status(httptest.StatusNotFound) + + e.GET("/el/templates").Expect().Status(httptest.StatusOK).Body().Contains(elGR).Contains(zhCN) + + e.GET("/not-matched").WithQuery("lang", "en-gb").Expect().Status(httptest.StatusOK).Body().IsEqual("user language input: en-gb: matched as: en-US: not found key: not_found_key: args: [some values 42]") +} diff --git a/i18n/basic/views/index.html b/i18n/basic/views/index.html new file mode 100644 index 00000000..64b40e7f --- /dev/null +++ b/i18n/basic/views/index.html @@ -0,0 +1,13 @@ +<h3>Test translate current locale template function <i>[dynamic]</i> ("word", arguments...) <br/> <code>call .tr "hi" "iris"</code></h3> + +{{call .tr "hi" "iris"}} + +<hr/> + +<h3>Test translate of any language template function <i>[static]</i> ("language", "word", arguments...) <br/> <code>tr "zh-CN" "hi" "iris"</code></h3> + +{{tr "zh-CN" "hi" "iris"}} + +<h3>Test HTML link ("word", arguments...) <br/> <code>call .trUnsafe "trUnsafe" "userProfilePublicDescription" "https://iris-go.com"</code></h3> + +{{call .trUnsafe "userProfilePublicDescription" "https://iris-go.com"}} \ No newline at end of file diff --git a/i18n/plurals/locales/en-US/1648.ini b/i18n/plurals/locales/en-US/1648.ini new file mode 100644 index 00000000..91add17c --- /dev/null +++ b/i18n/plurals/locales/en-US/1648.ini @@ -0,0 +1,5 @@ +[message] +Encrypted = Encrypted +Message = Message +EncryptedMessage = {{tr "message.Encrypted"}} {{tr "message.Message"}} +HostResult = Store {{tr "message.EncryptedMessage"}} Online \ No newline at end of file diff --git a/i18n/plurals/locales/en-US/welcome.yml b/i18n/plurals/locales/en-US/welcome.yml new file mode 100644 index 00000000..f5dec55d --- /dev/null +++ b/i18n/plurals/locales/en-US/welcome.yml @@ -0,0 +1,89 @@ +# Locale variables +# +# Unlike normal keys, the variables +# have limitations of: no ">x", "zero", "two" and template functions are supported. +# This is done to force developers to use small and easy to read variables for easier maintain process. +Vars: + - Minutes: + # possible keys: + # one + # "=x" - where x is a number + # "<x" + # other + # format - to customize the format, which defaults to %d . + one: "minute" + other: "minutes" + format: "%d" # defaults to that. + - Dogs: + "=5": "dogsssss" + one: "dog" + other: "dogs" + - Houses: + one: "house" + other: "houses" + - Gender: + "=1": "She" # 1 for female + "=2": "He" # 2 for male + +# Using variables in raw string +YouLate: "You are %[1]d ${Minutes} late." +# Just a simple raw value +Classic: "classic" + +# Pluralization, translate based on the plural count +# including the variables and their counts +FreeDay: + # possible keys: + # zero + # one + # two + # "=x" + # "<x" + # ">x" + # other + "=3": "You have three days and %[2]d ${Minutes} off." # "FreeDay" 3, 15 (plurals + variable pluralization) + one: "You have a day off" # "FreeDay", 1 + other: "You have %[1]d free days" # "FreeDay", 5 + +# Sprintf-like raw translation +HeIsHome: "%s is home" + +# Value without plural of its self but variables except pluralization +HouseCount: "${Gender} (%[3]s) has %[2]d ${Houses}" +# Same as above but with a template instead +VarTemplate: (${Gender}) {{tr "HeIsHome" .Name}} +# Template and non template with variables in the same plural key +VarTemplatePlural: + one: "${Gender} is awesome" + other: "other (${Gender}) has %[3]d ${Houses}" + "=5": "{{call .InlineJoin .Names}} are awesome" +TemplatePlural: + one: "{{.Name}} is unique" + "=5": "{{call .InlineJoin .Names}} are awesome" +# Same as above but it takes the variable counting through the map argument +TemplateVarTemplatePlural: + other: "These {{.PluralCount}} are wonderful, feeding {{.DogsCount}} ${Dogs} in total!" + +# Local variables and section. +LocalVarsHouseCount: + Text: "${Gender} has %[2]d ${Houses}" + Vars: + - Gender: + "=3": "She" + "=4": "He" + - Houses: + one: "house" + other: "houses" + +# Sections: +root: + user: Account + +nav: + home: Home # nav.home + user: '{{tr "root.user"}}' # nav.user + more: + what: "this" # nav.more.what + even: + more: "yes" # nav.more.even.more + aplural: "You are %[1]d ${Minutes} late." # Tr("nav.more.even.aplural", 15) diff --git a/i18n/plurals/main.go b/i18n/plurals/main.go new file mode 100644 index 00000000..53c8a18a --- /dev/null +++ b/i18n/plurals/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "strings" + + "github.com/kataras/iris/v12" +) + +const ( + female = iota + 1 + male +) + +const tableStyle = ` +<style> +a { + padding: 8px 8px; + text-decoration:none; + cursor:pointer; + color: #10a2ff; +} +table { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + height: 100%; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + border: 1px solid #cbcbcb; +} + +table caption { + color: #000; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center; +} + +table td, +table th { + border-left: 1px solid #cbcbcb; + border-width: 0 0 0 1px; + font-size: inherit; + margin: 0; + overflow: visible; + padding: 0.5em 1em; +} + +table thead { + background-color: #10a2ff; + color: #fff; + text-align: left; + vertical-align: bottom; +} + +table td { + background-color: transparent; +} + +.table-odd td { + background-color: #f2f2f2; +} + +.table-bordered td { + border-bottom: 1px solid #cbcbcb; +} +.table-bordered tbody > tr:last-child > td { + border-bottom-width: 0; +} +</style> +` + +/* +$ go run . +Visit http://localhost:8080 +*/ +func main() { + app := iris.New() + err := app.I18n.Load("./locales/*/*", "en-US") + // ^ here we only use a single locale for the sake of the example, + // on a real app you can register as many languages as you want to support. + if err != nil { + panic(err) + } + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<html><body>\n") + ctx.WriteString(tableStyle) + ctx.WriteString(`<table class="table-bordered table-odd"> +<thead> + <tr> + <th>Key</th> + <th>Translation</th> + <th>Arguments</th> + </tr> +</thead><tbody> +`) + defer ctx.WriteString("</tbody></table></body></html>") + + tr(ctx, "Classic") + + tr(ctx, "YouLate", 1) + tr(ctx, "YouLate", 2) + + tr(ctx, "FreeDay", 1) + tr(ctx, "FreeDay", 5) + + tr(ctx, "FreeDay", 3, 15) + + tr(ctx, "HeIsHome", "Peter") + + tr(ctx, "HouseCount", female, 2, "Maria") + tr(ctx, "HouseCount", male, 1, "Peter") + + tr(ctx, "nav.home") + tr(ctx, "nav.user") + tr(ctx, "nav.more.what") + tr(ctx, "nav.more.even.more") + tr(ctx, "nav.more.even.aplural", 1) + tr(ctx, "nav.more.even.aplural", 15) + + tr(ctx, "VarTemplate", iris.Map{ + "Name": "Peter", + "GenderCount": male, + }) + + tr(ctx, "VarTemplatePlural", 1, female) + tr(ctx, "VarTemplatePlural", 2, female, 1) + tr(ctx, "VarTemplatePlural", 2, female, 5) + tr(ctx, "VarTemplatePlural", 1, male) + tr(ctx, "VarTemplatePlural", 2, male, 1) + tr(ctx, "VarTemplatePlural", 2, male, 2) + + tr(ctx, "VarTemplatePlural", iris.Map{ + "PluralCount": 5, + "Names": []string{"Makis", "Peter"}, + "InlineJoin": func(arr []string) string { + return strings.Join(arr, ", ") + }, + }) + + tr(ctx, "TemplatePlural", iris.Map{ + "PluralCount": 1, + "Name": "Peter", + }) + tr(ctx, "TemplatePlural", iris.Map{ + "PluralCount": 5, + "Names": []string{"Makis", "Peter"}, + "InlineJoin": func(arr []string) string { + return strings.Join(arr, ", ") + }, + }) + tr(ctx, "VarTemplatePlural", 2, male, 4) + + tr(ctx, "TemplateVarTemplatePlural", iris.Map{ + "PluralCount": 3, + "DogsCount": 5, + }) + + tr(ctx, "message.HostResult") + + tr(ctx, "LocalVarsHouseCount.Text", 3, 4) + }) + + app.Listen(":8080") +} + +func tr(ctx iris.Context, key string, args ...interface{}) { + translation := ctx.Tr(key, args...) + ctx.Writef("<tr><td>%s</td><td>%s</td><td>%v</td></tr>\n", key, translation, args) +} diff --git a/i18n/plurals/main_test.go b/i18n/plurals/main_test.go new file mode 100644 index 00000000..cc742638 --- /dev/null +++ b/i18n/plurals/main_test.go @@ -0,0 +1,131 @@ +package main_test + +import ( + "strings" + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +const ( + female = iota + 1 + male +) + +func TestI18nPlurals(t *testing.T) { + handler := func(ctx iris.Context) { + tr(ctx, "Classic") + + tr(ctx, "YouLate", 1) + tr(ctx, "YouLate", 2) + + tr(ctx, "FreeDay", 1) + tr(ctx, "FreeDay", 5) + + tr(ctx, "FreeDay", 3, 15) + + tr(ctx, "HeIsHome", "Peter") + + tr(ctx, "HouseCount", female, 2, "Maria") + tr(ctx, "HouseCount", male, 1, "Peter") + + tr(ctx, "nav.home") + tr(ctx, "nav.user") + tr(ctx, "nav.more.what") + tr(ctx, "nav.more.even.more") + tr(ctx, "nav.more.even.aplural", 1) + tr(ctx, "nav.more.even.aplural", 15) + + tr(ctx, "VarTemplate", iris.Map{ + "Name": "Peter", + "GenderCount": male, + }) + + tr(ctx, "VarTemplatePlural", 1, female) + tr(ctx, "VarTemplatePlural", 2, female, 1) + tr(ctx, "VarTemplatePlural", 2, female, 5) + tr(ctx, "VarTemplatePlural", 1, male) + tr(ctx, "VarTemplatePlural", 2, male, 1) + tr(ctx, "VarTemplatePlural", 2, male, 2) + + tr(ctx, "VarTemplatePlural", iris.Map{ + "PluralCount": 5, + "Names": []string{"Makis", "Peter"}, + "InlineJoin": func(arr []string) string { + return strings.Join(arr, ", ") + }, + }) + + tr(ctx, "TemplatePlural", iris.Map{ + "PluralCount": 1, + "Name": "Peter", + }) + tr(ctx, "TemplatePlural", iris.Map{ + "PluralCount": 5, + "Names": []string{"Makis", "Peter"}, + "InlineJoin": func(arr []string) string { + return strings.Join(arr, ", ") + }, + }) + tr(ctx, "VarTemplatePlural", 2, male, 4) + + tr(ctx, "TemplateVarTemplatePlural", iris.Map{ + "PluralCount": 3, + "DogsCount": 5, + }) + + tr(ctx, "message.HostResult") + + tr(ctx, "LocalVarsHouseCount.Text", 3, 4) + } + + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + defer r.Body.Close() + httptest.Do(w, r, handler, func(app *iris.Application) { + err := app.I18n.Load("./locales/*/*", "en-US", "el-GR") + if err != nil { + panic(err) + } + }) + + expected := `Classic=classic +YouLate=You are 1 minute late. +YouLate=You are 2 minutes late. +FreeDay=You have a day off +FreeDay=You have 5 free days +FreeDay=You have three days and 15 minutes off. +HeIsHome=Peter is home +HouseCount=She (Maria) has 2 houses +HouseCount=He (Peter) has 1 house +nav.home=Home +nav.user=Account +nav.more.what=this +nav.more.even.more=yes +nav.more.even.aplural=You are 1 minute late. +nav.more.even.aplural=You are 15 minutes late. +VarTemplate=(He) Peter is home +VarTemplatePlural=She is awesome +VarTemplatePlural=other (She) has 1 house +VarTemplatePlural=other (She) has 5 houses +VarTemplatePlural=He is awesome +VarTemplatePlural=other (He) has 1 house +VarTemplatePlural=other (He) has 2 houses +VarTemplatePlural=Makis, Peter are awesome +TemplatePlural=Peter is unique +TemplatePlural=Makis, Peter are awesome +VarTemplatePlural=other (He) has 4 houses +TemplateVarTemplatePlural=These 3 are wonderful, feeding 5 dogsssss in total! +message.HostResult=Store Encrypted Message Online +LocalVarsHouseCount.Text=She has 4 houses +` + if got := w.Body.String(); expected != got { + t.Fatalf("expected:\n'%s'\n\nbut got:\n'%s'", expected, got) + } +} + +func tr(ctx iris.Context, key string, args ...interface{}) { + translation := ctx.Tr(key, args...) + ctx.Writef("%s=%s\n", key, translation) +} diff --git a/i18n/template-embedded/embedded/locales/el-GR/other.ini b/i18n/template-embedded/embedded/locales/el-GR/other.ini new file mode 100644 index 00000000..8ebc6727 --- /dev/null +++ b/i18n/template-embedded/embedded/locales/el-GR/other.ini @@ -0,0 +1,10 @@ +[nav] +User = Λογαριασμός + +[debug] +Title = Μενού προγραμματιστή +AccessLog = Πρόσβαση στο αρχείο καταγραφής +AccessLogClear = Καθαρισμός {{ tr "debug.AccessLog" }} + +[user.connections] +Title = {{ tr "nav.User" }} Συνδέσεις \ No newline at end of file diff --git a/i18n/template-embedded/embedded/locales/el-GR/user.ini b/i18n/template-embedded/embedded/locales/el-GR/user.ini new file mode 100644 index 00000000..3a6c6409 --- /dev/null +++ b/i18n/template-embedded/embedded/locales/el-GR/user.ini @@ -0,0 +1,4 @@ +[forms] +member = μέλος +register = Γίνε {{ uppercase (tr "forms.member") }} +registered = εγγεγραμμένοι \ No newline at end of file diff --git a/i18n/template-embedded/embedded/locales/en-US/other.ini b/i18n/template-embedded/embedded/locales/en-US/other.ini new file mode 100644 index 00000000..f8c75336 --- /dev/null +++ b/i18n/template-embedded/embedded/locales/en-US/other.ini @@ -0,0 +1,12 @@ +# just an example of some more nested keys, +# see /other endpoint. +[nav] +User = Account + +[debug] +Title = Developer Menu +AccessLog = Access Log +AccessLogClear = Clear {{ tr "debug.AccessLog" }} + +[user.connections] +Title = {{ tr "nav.User" }} Connections \ No newline at end of file diff --git a/i18n/template-embedded/embedded/locales/en-US/user.ini b/i18n/template-embedded/embedded/locales/en-US/user.ini new file mode 100644 index 00000000..2498d029 --- /dev/null +++ b/i18n/template-embedded/embedded/locales/en-US/user.ini @@ -0,0 +1,4 @@ +[forms] +member = member +register = Become a {{ uppercase (tr "forms.member") }} +registered = registered \ No newline at end of file diff --git a/i18n/template-embedded/main.go b/i18n/template-embedded/main.go new file mode 100644 index 00000000..ff142ace --- /dev/null +++ b/i18n/template-embedded/main.go @@ -0,0 +1,63 @@ +package main + +import ( + "embed" + "strings" + "text/template" + + "github.com/kataras/iris/v12" +) + +//go:embed embedded/locales/* +var embeddedFS embed.FS + +func main() { + app := newApp() + // http://localhost:8080 + // http://localhost:8080?lang=el + // http://localhost:8080?lang=el + // http://localhost:8080?lang=el-GR + // http://localhost:8080?lang=en + // http://localhost:8080?lang=en-US + // + // http://localhost:8080/title + // http://localhost:8080/title?lang=el-GR + // ... + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + // Set custom functions per locale! + app.I18n.Loader.Funcs = func(current iris.Locale) template.FuncMap { + return template.FuncMap{ + "uppercase": func(word string) string { + return strings.ToUpper(word) + }, + } + } + + // Instead of: + // err := app.I18n.Load("./locales/*/*.ini", "en-US", "el-GR") + // apply the below in order to build with embedded locales inside your executable binary. + err := app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini", "en-US", "el-GR") + if err != nil { + panic(err) + } // OR to load all languages by filename: + // app.I18n.LoadFS(embeddedFS, "./embedded/locales/*/*.ini") + // Then set the default language using: + // app.I18n.SetDefault("en-US") + + app.Get("/", func(ctx iris.Context) { + text := ctx.Tr("forms.register") // en-US: prints "Become a MEMBER". + ctx.WriteString(text) + }) + + app.Get("/title", func(ctx iris.Context) { + text := ctx.Tr("user.connections.Title") // en-US: prints "Accounts Connections". + ctx.WriteString(text) + }) + + return app +} diff --git a/i18n/template-embedded/main_test.go b/i18n/template-embedded/main_test.go new file mode 100644 index 00000000..b23e2479 --- /dev/null +++ b/i18n/template-embedded/main_test.go @@ -0,0 +1,21 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestI18nLoaderFuncMap(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusOK). + Body().IsEqual("Become a MEMBER") + e.GET("/title").Expect().Status(httptest.StatusOK). + Body().IsEqual("Account Connections") + e.GET("/").WithHeader("Accept-Language", "el").Expect().Status(httptest.StatusOK). + Body().IsEqual("Γίνε ΜΈΛΟΣ") + e.GET("/title").WithHeader("Accept-Language", "el").Expect().Status(httptest.StatusOK). + Body().IsEqual("Λογαριασμός Συνδέσεις") +} diff --git a/i18n/template/locales/el-GR/other.ini b/i18n/template/locales/el-GR/other.ini new file mode 100644 index 00000000..5954cdd3 --- /dev/null +++ b/i18n/template/locales/el-GR/other.ini @@ -0,0 +1,10 @@ +[nav] +User = Λογαριασμός + +[debug] +Title = Μενού προγραμματιστή +AccessLog = Πρόσβαση στο αρχείο καταγραφής +AccessLogClear = Καθαρισμός {{tr "debug.AccessLog"}} + +[user.connections] +Title = {{tr "nav.User"}} Συνδέσεις \ No newline at end of file diff --git a/i18n/template/locales/el-GR/user.ini b/i18n/template/locales/el-GR/user.ini new file mode 100644 index 00000000..0a110cdc --- /dev/null +++ b/i18n/template/locales/el-GR/user.ini @@ -0,0 +1,4 @@ +[forms] +member = μέλος +register = Γίνε {{uppercase (tr "forms.member") }} +registered = εγγεγραμμένοι \ No newline at end of file diff --git a/i18n/template/locales/en-US/other.ini b/i18n/template/locales/en-US/other.ini new file mode 100644 index 00000000..31f1b182 --- /dev/null +++ b/i18n/template/locales/en-US/other.ini @@ -0,0 +1,12 @@ +# just an example of some more nested keys, +# see /other endpoint. +[nav] +User = Account + +[debug] +Title = Developer Menu +AccessLog = Access Log +AccessLogClear = Clear {{tr "debug.AccessLog"}} + +[user.connections] +Title = {{tr "nav.User"}} Connections \ No newline at end of file diff --git a/i18n/template/locales/en-US/user.ini b/i18n/template/locales/en-US/user.ini new file mode 100644 index 00000000..09d3e3e4 --- /dev/null +++ b/i18n/template/locales/en-US/user.ini @@ -0,0 +1,4 @@ +[forms] +member = member +register = Become a {{uppercase (tr "forms.member") }} +registered = registered \ No newline at end of file diff --git a/i18n/template/main.go b/i18n/template/main.go new file mode 100644 index 00000000..4d60aa81 --- /dev/null +++ b/i18n/template/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "strings" + "text/template" + + "github.com/kataras/iris/v12" +) + +/* + Iris I18n supports text/template inside the translation values. + Follow this example to learn how to use that feature. +*/ + +func main() { + app := newApp() + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + // Set custom functions per locale! + app.I18n.Loader.Funcs = func(current iris.Locale) template.FuncMap { + return template.FuncMap{ + "uppercase": func(word string) string { + return strings.ToUpper(word) + }, + } + } + + err := app.I18n.Load("./locales/*/*.ini", "en-US", "el-GR") + if err != nil { + panic(err) + } + + app.Get("/", func(ctx iris.Context) { + text := ctx.Tr("forms.register") // en-US: prints "Become a MEMBER". + ctx.WriteString(text) + }) + + app.Get("/title", func(ctx iris.Context) { + text := ctx.Tr("user.connections.Title") // en-US: prints "Accounts Connections". + ctx.WriteString(text) + }) + + return app +} diff --git a/i18n/template/main_test.go b/i18n/template/main_test.go new file mode 100644 index 00000000..b23e2479 --- /dev/null +++ b/i18n/template/main_test.go @@ -0,0 +1,21 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestI18nLoaderFuncMap(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusOK). + Body().IsEqual("Become a MEMBER") + e.GET("/title").Expect().Status(httptest.StatusOK). + Body().IsEqual("Account Connections") + e.GET("/").WithHeader("Accept-Language", "el").Expect().Status(httptest.StatusOK). + Body().IsEqual("Γίνε ΜΈΛΟΣ") + e.GET("/title").WithHeader("Accept-Language", "el").Expect().Status(httptest.StatusOK). + Body().IsEqual("Λογαριασμός Συνδέσεις") +} diff --git a/kafka-api/0_docs.png b/kafka-api/0_docs.png new file mode 100644 index 00000000..2c81a744 Binary files /dev/null and b/kafka-api/0_docs.png differ diff --git a/kafka-api/1_create_topic.png b/kafka-api/1_create_topic.png new file mode 100644 index 00000000..15f172d6 Binary files /dev/null and b/kafka-api/1_create_topic.png differ diff --git a/kafka-api/2_list_topics.png b/kafka-api/2_list_topics.png new file mode 100644 index 00000000..8ff6df54 Binary files /dev/null and b/kafka-api/2_list_topics.png differ diff --git a/kafka-api/3_store_to_topic.png b/kafka-api/3_store_to_topic.png new file mode 100644 index 00000000..c0fc8114 Binary files /dev/null and b/kafka-api/3_store_to_topic.png differ diff --git a/kafka-api/4_retrieve_from_topic_real_time.png b/kafka-api/4_retrieve_from_topic_real_time.png new file mode 100644 index 00000000..b336205b Binary files /dev/null and b/kafka-api/4_retrieve_from_topic_real_time.png differ diff --git a/kafka-api/Dockerfile b/kafka-api/Dockerfile new file mode 100644 index 00000000..dec864fe --- /dev/null +++ b/kafka-api/Dockerfile @@ -0,0 +1,17 @@ +# docker build -t myapp . +# docker run --rm -it -p 8080:8080 myapp:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/myapp . +ENTRYPOINT ["./myapp"] \ No newline at end of file diff --git a/kafka-api/README.md b/kafka-api/README.md new file mode 100644 index 00000000..ad82388f --- /dev/null +++ b/kafka-api/README.md @@ -0,0 +1,49 @@ +# Writing an API for Apache Kafka with Iris + +Read the [code](main.go). + +## Docker + +1. Open [docker-compose.yml](docker-compose.yml) and replace `KAFKA_ADVERTISED_HOST_NAME` with your own local address +2. Install [Docker](https://www.docker.com/) +3. Execute the command below to start kafka stack and the go application: + +```sh +$ docker-compose up +``` + +### Troubleshooting + +On windows, if you get an error of `An attempt was made to access a socket in a way forbidden by its access permissions` + +Solution: + +1. Stop Docker +2. Open CMD with Administrator privileges and execute the following commands: + +```sh +$ dism.exe /Online /Disable-Feature:Microsoft-Hyper-V +$ netsh int ipv4 add excludedportrange protocol=tcp startport=2181 numberofports=1 +$ dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All +$ docker-compose up --build +``` + +## Manually + +Install & run Kafka and Zookeper locally and then: + +```sh +go run main.go +``` + +## Screens + + + + + + + + + + diff --git a/kafka-api/docker-compose.yml b/kafka-api/docker-compose.yml new file mode 100644 index 00000000..e2e6dab6 --- /dev/null +++ b/kafka-api/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3.1' + +services: + zookeeper: + image: wurstmeister/zookeeper + ports: + - 2181:2181 + kafka: + image: wurstmeister/kafka + ports: + - 9092:9092 + environment: + KAFKA_ADVERTISED_HOST_NAME: 10.122.1.142 # replace that with your own local ipv4 addr. + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + # kafka: + # image: confluentinc/cp-kafka:5.5.0 + # hostname: kafka + # ports: + # - 9092:9092 + # environment: + # KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://kafka:19092,LISTENER_DOCKER_EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092 + app: + build: . + ports: + - 8080:8080 + environment: + KAFKA_1: kafka:9092 + depends_on: + - kafka \ No newline at end of file diff --git a/kafka-api/go.mod b/kafka-api/go.mod new file mode 100644 index 00000000..16a21b75 --- /dev/null +++ b/kafka-api/go.mod @@ -0,0 +1,69 @@ +module myapp + +go 1.22 + +require ( + github.com/IBM/sarama v1.43.1 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eapache/go-resiliency v1.6.0 // indirect + github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect + github.com/eapache/queue v1.1.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/jcmturner/aescts/v2 v2.0.0 // indirect + github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect + github.com/jcmturner/gofork v1.7.6 // indirect + github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect + github.com/jcmturner/rpc/v2 v2.0.3 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/kafka-api/go.sum b/kafka-api/go.sum new file mode 100644 index 00000000..820c0984 --- /dev/null +++ b/kafka-api/go.sum @@ -0,0 +1,245 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/IBM/sarama v1.43.1 h1:Z5uz65Px7f4DhI/jQqEm/tV9t8aU+JUdTyW/K/fCXpA= +github.com/IBM/sarama v1.43.1/go.mod h1:GG5q1RURtDNPz8xxJs3mgX6Ytak8Z9eLhAkJPObe2xE= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eapache/go-resiliency v1.6.0 h1:CqGDTLtpwuWKn6Nj3uNUdflaq+/kIPsg0gfNzHton30= +github.com/eapache/go-resiliency v1.6.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws= +github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0= +github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/kafka-api/main.go b/kafka-api/main.go new file mode 100644 index 00000000..de33f233 --- /dev/null +++ b/kafka-api/main.go @@ -0,0 +1,391 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "strings" + "time" + + "github.com/IBM/sarama" + "github.com/kataras/iris/v12" +) + +/* +First of all, read about Apache Kafka, install and run it, if you didn't already: https://kafka.apache.org/quickstart + +Secondly, install your favourite Go library for Apache Kafka communication. +I have chosen the shopify's one although I really loved the `segmentio/kafka-go` as well but it needs more to be done there +and you will be bored to read all the necessary code required to get started with it, so: + $ go get -u github.com/IBM/sarama + +The minimum Apache Kafka broker(s) version required is 0.10.0.0 but 0.11.x+ is recommended (tested with 2.5.0). + +Resources: + - https://github.com/apache/kafka + - https://github.com/IBM/sarama/blob/master/examples/http_server/http_server.go + - DIY +*/ + +// package-level variables for the sake of the example +// but you can define them inside your main func +// and pass around this config whenever you need to create a client or a producer or a consumer or use a cluster. +var ( + // The Kafka brokers to connect to, as a comma separated list. + brokers = []string{getenv("KAFKA_1", "localhost:9092")} + // The config which makes our live easier when passing around, it pre-mades a lot of things for us. + config *sarama.Config +) + +func getenv(key string, def string) string { + if value := os.Getenv(key); value != "" { + return value + } + + return def +} + +func init() { + config = sarama.NewConfig() + config.ClientID = "iris-example-client" + config.Version = sarama.V0_11_0_2 + // config.Producer.RequiredAcks = sarama.WaitForAll // Wait for all in-sync replicas to ack the message. + config.Producer.Compression = sarama.CompressionSnappy + config.Producer.Flush.Frequency = 500 * time.Millisecond + config.Producer.Retry.Max = 10 // Retry up to 10 times to produce the message. + config.Producer.Return.Successes = true + + // for SASL/basic plain text authentication: config.Net.SASL. + // config.Net.SASL.Enable = true + // config.Net.SASL.Handshake = false + // config.Net.SASL.User = "myuser" + // config.Net.SASL.Password = "mypass" + + config.Consumer.Return.Errors = true +} + +func main() { + app := iris.New() + app.OnErrorCode(iris.StatusNotFound, handleNotFound) + + v1 := app.Party("/api/v1") + { + topicsAPI := v1.Party("/topics") + { + topicsAPI.Post("/", postTopicsHandler) // create a topic. + topicsAPI.Get("/", getTopicsHandler) // list all topics. + + topicsAPI.Post("/{topic}/produce", postTopicProduceHandler) // store to a topic. + topicsAPI.Get("/{topic}/consume", getTopicConsumeSSEHandler) // retrieve all messages from a topic. + } + } + + app.Get("/", docsHandler) + + app.Logger().Infof("Brokers: %s", strings.Join(brokers, ", ")) + // GET : http://localhost:8080 + // POST, GET: http://localhost:8080/api/v1/topics + // POST : http://localhost:8080/api/v1/topics/{topic}/produce?key=my-key + // GET : http://localhost:8080/api/v1/topics/{topic}/consume?partition=0&offset=0 + app.Listen(":8080") +} + +// simple use-case, you can use templates and views obviously, see the "_examples/views" examples. +func docsHandler(ctx iris.Context) { + ctx.ContentType("text/html") // or ctx.HTML(fmt.Sprintf(...)) + ctx.Writef(`<!DOCTYPE html> + <html> + <head> + <style> + th, td { + border: 1px solid black; + padding: 15px; + text-align: left; + } + </style> + </head>`) + defer ctx.Writef("</html>") + + ctx.Writef("<body>") + defer ctx.Writef("</body>") + + ctx.Writef(` + <table> + <tr> + <th>Method</th> + <th>Path</th> + <th>Handler</th> + </tr> + `) + defer ctx.Writef(`</table>`) + + registeredRoutes := ctx.Application().GetRoutesReadOnly() + for _, r := range registeredRoutes { + if r.Path() == "/" { // don't list the root, current one. + continue + } + + ctx.Writef(` + <tr> + <td>%s</td> + <td>%s%s</td> + <td>%s</td> + </tr> + `, r.Method(), ctx.Host(), r.Path(), r.MainHandlerName()) + } +} + +type httpError struct { + Code int `json:"code"` + Reason string `json:"reason,omitempty"` +} + +func (h httpError) Error() string { + return fmt.Sprintf("Status Code: %d\nReason: %s", h.Code, h.Reason) +} + +func fail(ctx iris.Context, statusCode int, format string, a ...interface{}) { + reason := "unspecified" + if format != "" { + reason = fmt.Sprintf(format, a...) + } + + err := httpError{ + Code: statusCode, + Reason: reason, + } + + ctx.StopWithJSON(statusCode, err) +} + +func handleNotFound(ctx iris.Context) { + suggestPaths := ctx.FindClosest(3) + if len(suggestPaths) == 0 { + ctx.WriteString("not found") + return + } + + ctx.HTML("Did you mean?<ul>") + for _, s := range suggestPaths { + ctx.HTML(`<li><a href="%s">%s</a></li>`, s, s) + } + ctx.HTML("</ul>") +} + +// Topic the payload for a kafka topic creation. +type Topic struct { + Topic string `json:"topic"` + Partitions int32 `json:"partitions"` + ReplicationFactor int16 `json:"replication"` + Configs []kv `json:"configs,omitempty"` +} + +type kv struct { + Key string `json:"key"` + Value string `json:"value"` +} + +func createKafkaTopic(t Topic) error { + cluster, err := sarama.NewClusterAdmin(brokers, config) + if err != nil { + return err + } + defer cluster.Close() + + topicName := t.Topic + topicDetail := sarama.TopicDetail{ + NumPartitions: t.Partitions, + ReplicationFactor: t.ReplicationFactor, + } + + if len(t.Configs) > 0 { + topicDetail.ConfigEntries = make(map[string]*string, len(t.Configs)) + for _, c := range t.Configs { + topicDetail.ConfigEntries[c.Key] = &c.Value // generate a ptr, or fill a new(string) with it and use that. + } + } + + return cluster.CreateTopic(topicName, &topicDetail, false) +} + +func postTopicsHandler(ctx iris.Context) { + var t Topic + err := ctx.ReadJSON(&t) + if err != nil { + fail(ctx, iris.StatusBadRequest, + "received invalid topic payload: %v", err) + return + } + + // try to create the topic inside kafka. + err = createKafkaTopic(t) + if err != nil { + fail(ctx, iris.StatusInternalServerError, + "unable to create topic: %v", err) + return + } + + ctx.StatusCode(iris.StatusCreated) + ctx.Writef("Topic %q created", t.Topic) +} + +func getKafkaTopics() ([]string, error) { + client, err := sarama.NewClient(brokers, config) + if err != nil { + return nil, err + } + defer client.Close() + + return client.Topics() +} + +func getTopicsHandler(ctx iris.Context) { + topics, err := getKafkaTopics() + if err != nil { + fail(ctx, iris.StatusInternalServerError, + "unable to retrieve topics: %v", err) + return + } + + ctx.JSON(topics) +} + +func produceKafkaMessage(toTopic string, key string, value []byte) (partition int32, offset int64, err error) { + // On the broker side, you may want to change the following settings to get + // stronger consistency guarantees: + // - For your broker, set `unclean.leader.election.enable` to false + // - For the topic, you could increase `min.insync.replicas`. + + producer, err := sarama.NewSyncProducer(brokers, config) + if err != nil { + return -1, -1, err + } + defer producer.Close() + + // We are not setting a message key, which means that all messages will + // be distributed randomly over the different partitions. + return producer.SendMessage(&sarama.ProducerMessage{ + Topic: toTopic, + Key: sarama.StringEncoder(key), + Value: sarama.ByteEncoder(value), + }) +} + +func postTopicProduceHandler(ctx iris.Context) { + topicName := ctx.Params().Get("topic") + key := ctx.URLParamDefault("key", "default") + + // read the request data and store them as they are (not recommended in production ofcourse, do your own checks here). + body, err := ctx.GetBody() + if err != nil { + fail(ctx, iris.StatusUnprocessableEntity, "unable to read your data: %v", err) + return + } + + partition, offset, err := produceKafkaMessage(topicName, key, body) + if err != nil { + fail(ctx, iris.StatusInternalServerError, "failed to store your data: %v", err) + return + } + + // The tuple (topic, partition, offset) can be used as a unique identifier + // for a message in a Kafka cluster. + ctx.Writef("Your data is stored with unique identifier: %s/%d/%d", topicName, partition, offset) +} + +type message struct { + Time time.Time `json:"time"` + Key string `json:"key"` + // Value []byte/json.RawMessage(if you are sure that you are sending only JSON) `json:"value"` + // or: + Value string `json:"value"` // for simple key-value storage. +} + +func getTopicConsumeSSEHandler(ctx iris.Context) { + flusher, ok := ctx.ResponseWriter().Flusher() + if !ok { + ctx.StopWithText(iris.StatusHTTPVersionNotSupported, "streaming unsupported") + return + } + + ctx.ContentType("application/json, text/event-stream") + ctx.Header("Cache-Control", "no-cache") + ctx.Header("Connection", "keep-alive") + + master, err := sarama.NewConsumer(brokers, config) + if err != nil { + fail(ctx, iris.StatusInternalServerError, "unable to start master consumer: %v", err) + return + } + + fromTopic := ctx.Params().Get("topic") + // take the partition, defaults to the first found if not url query parameter "partition" passed. + var partition int32 + partitions, err := master.Partitions(fromTopic) + if err != nil { + master.Close() + fail(ctx, iris.StatusInternalServerError, "unable to get partitions for topic: '%s': %v", fromTopic, err) + return + } + + if len(partitions) > 0 { + partition = partitions[0] + } + + partition = ctx.URLParamInt32Default("partition", partition) + offset := ctx.URLParamInt64Default("offset", sarama.OffsetOldest) + + consumer, err := master.ConsumePartition(fromTopic, partition, offset) + if err != nil { + ctx.Application().Logger().Error(err) + master.Close() // close the master here to avoid any leaks, we will exit. + fail(ctx, iris.StatusInternalServerError, "unable to start partition consumer: %v", err) + return + } + + // `OnClose` fires when the request is finally done (all data read and handler exits) or interrupted by the user. + ctx.OnClose(func(_ iris.Context) { + ctx.Application().Logger().Warnf("a client left") + + // Close shuts down the consumer. It must be called after all child + // PartitionConsumers have already been closed. <-- That is what + // godocs says but it doesn't work like this. + // if err = consumer.Close(); err != nil { + // ctx.Application().Logger().Errorf("[%s] unable to close partition consumer: %v", ctx.RemoteAddr(), err) + // } + // so close the master only and omit the first ^ consumer.Close: + if err = master.Close(); err != nil { + ctx.Application().Logger().Errorf("[%s] unable to close master consumer: %v", ctx.RemoteAddr(), err) + } + }) + + for { + select { + case consumerErr, ok := <-consumer.Errors(): + if !ok { + return + } + ctx.Writef("data: error: {\"reason\": \"%s\"}\n\n", consumerErr.Error()) + flusher.Flush() + case incoming, ok := <-consumer.Messages(): + if !ok { + return + } + + msg := message{ + Time: incoming.Timestamp, + Key: string(incoming.Key), + Value: string(incoming.Value), + } + + b, err := json.Marshal(msg) + if err != nil { + ctx.Application().Logger().Error(err) + continue + } + + ctx.Writef("data: %s\n\n", b) + flusher.Flush() + } + } +} diff --git a/kafka-api/postman_collection.json b/kafka-api/postman_collection.json new file mode 100644 index 00000000..8f410573 --- /dev/null +++ b/kafka-api/postman_collection.json @@ -0,0 +1,137 @@ +{ + "info": { + "_postman_id": "8b135d95-ea8c-4dd5-a127-4b83cb735504", + "name": "iris-kafka-postman", + "description": "Postman API Requests for Iris + Kafka example", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Create Topic", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"topic\":\"mytopic\",\r\n \"partitions\": 1,\r\n \"replication\":1\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/topics", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics" + ] + }, + "description": "Create a new kafka topic" + }, + "response": [] + }, + { + "name": "List all Topics", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/topics", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics" + ] + }, + "description": "List all topics" + }, + "response": [] + }, + { + "name": "Store data to Topic", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\":\"kataras\",\r\n \"repo\":\"iris\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/topics/mytopic/produce?key=mykey", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics", + "mytopic", + "produce" + ], + "query": [ + { + "key": "key", + "value": "mykey" + } + ] + }, + "description": "Produce some data to a Topic" + }, + "response": [] + }, + { + "name": "(Open in Browser) Consume data from a Topic", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/topics/mytopic/consume?partition=0&offset=0", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics", + "mytopic", + "consume" + ], + "query": [ + { + "key": "partition", + "value": "0" + }, + { + "key": "offset", + "value": "0" + } + ] + }, + "description": "Note that, you have to open this one at your browser. Postman does not support SSE testing, see: https://github.com/postmanlabs/postman-app-support/issues/6682" + }, + "response": [] + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/logging/file-logger/main.go b/logging/file-logger/main.go new file mode 100644 index 00000000..a9cca07d --- /dev/null +++ b/logging/file-logger/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "os" + "time" + + "github.com/kataras/iris/v12" +) + +func main() { + f := newLogFile() + defer f.Close() + + app := iris.New() + // Attach the file as logger, remember, iris' app logger is just an io.Writer. + // Use the following code if you need to write the logs to file and console at the same time. + // app.Logger().SetOutput(io.MultiWriter(f, os.Stdout)) + app.Logger().SetOutput(f) + + app.Get("/ping", func(ctx iris.Context) { + // for the sake of simplicity, in order see the logs at the ./_today_.txt + ctx.Application().Logger().Infof("Request path: %s", ctx.Path()) + ctx.WriteString("pong") + }) + + // Navigate to http://localhost:8080/ping + // and open the ./logs{TODAY}.txt file. + if err := app.Listen(":8080", iris.WithoutBanner); err != nil { + app.Logger().Warn("Shutdown with error: " + err.Error()) + } +} + +// Get a filename based on the date, just for the sugar. +func todayFilename() string { + today := time.Now().Format("Jan 02 2006") + return today + ".txt" +} + +func newLogFile() *os.File { + filename := todayFilename() + // Open the file, this will append to the today's file if server restarted. + f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + panic(err) + } + + return f +} diff --git a/logging/json-logger/main.go b/logging/json-logger/main.go new file mode 100644 index 00000000..47f7a90c --- /dev/null +++ b/logging/json-logger/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/requestid" + + "github.com/kataras/golog" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + app.Logger().SetFormat("json", " ") + // to register a custom Formatter: + // app.Logger().RegisterFormatter(golog.Formatter...) + + // Also, see app.Logger().SetLevelOutput(level string, w io.Writer) + // to set a custom writer for a specific level. + + app.Use(requestid.New()) + + /* Example Output: + { + "timestamp": 1591422944, + "level": "debug", + "message": "This is a message with data", + "fields": { + "username": "kataras" + }, + "stacktrace": [ + { + "function": "main.main", + "source": "C:/mygopath/src/github.com/kataras/iris/_examples/logging/json-logger/main.go:16" + } + ] + } + */ + app.Logger().Debugf("This is a %s with data (debug prints the stacktrace too)", "message", golog.Fields{ + "username": "kataras", + }) + + /* Example Output: + { + "timestamp": 1591422944, + "level": "info", + "message": "An info message", + "fields": { + "home": "https://iris-go.com" + } + } + */ + app.Logger().Infof("An info message", golog.Fields{"home": "https://iris-go.com"}) + + app.Get("/ping", ping) + + // Navigate to http://localhost:8080/ping. + app.Listen(":8080" /*, iris.WithoutBanner*/) +} + +func ping(ctx iris.Context) { + /* Example Output: + { + "timestamp": 1591423046, + "level": "debug", + "message": "Request path: /ping", + "fields": { + "request_id": "fc12d88a-a338-4bb9-aa5e-126f2104365c" + }, + "stacktrace": [ + { + "function": "main.ping", + "source": "C:/mygopath/src/github.com/kataras/iris/_examples/logging/json-logger/main.go:82" + }, + ... + ] + } + */ + ctx.Application().Logger().Debugf("Request path: %s", ctx.Path(), golog.Fields{ + "request_id": ctx.GetID(), + }) + + ctx.WriteString("pong") +} diff --git a/logging/json-logger/main_test.go b/logging/json-logger/main_test.go new file mode 100644 index 00000000..f55376c3 --- /dev/null +++ b/logging/json-logger/main_test.go @@ -0,0 +1,72 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "path" + "runtime" + "strings" + "sync" + "testing" + + "github.com/kataras/golog" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +func TestJSONLogger(t *testing.T) { + iters := 500 + + out := new(bytes.Buffer) + + app := iris.New() + app.Logger().SetTimeFormat("") // disable timestamps. + app.Logger().SetStacktraceLimit(1) // limit debug stacktrace to 1, show only the first caller. + app.Logger().SetOutput(out) + + app.Logger().Handle(func(l *golog.Log) bool { + enc := json.NewEncoder(l.Logger.Printer) // you can change the output to a file as well. + err := enc.Encode(l) + return err == nil + }) + + app.Get("/ping", ping) + + expectedSourceDir := getSourceDirPath() + expectedLogStr := fmt.Sprintf(`{"level":"debug","message":"Request path: /ping","fields":{"request_id":null},"stacktrace":[{"function":"json-logger/ping","source":"%s/main.go:78"}]}`, expectedSourceDir) // gh actions-specific. + e := httptest.New(t, app, httptest.LogLevel("debug")) + wg := new(sync.WaitGroup) + wg.Add(iters) + for i := 0; i < iters; i++ { + go func() { + e.GET("/ping").Expect().Status(httptest.StatusOK).Body().IsEqual("pong") + wg.Done() + }() + } + + wg.Wait() + expected := "" + for i := 0; i < iters; i++ { + expected += expectedLogStr + "\n" + } + + got := out.String() + got = got[strings.Index(got, "{"):] // take only the json we care and after. + if expected != got { + if !strings.HasSuffix(got, expected) { + // C:/mygopath vs /home/travis vs any file system, + // pure check but it does the job. + t.Fatalf("expected:\n%s\nbut got:\n%s", expected, got) + } + } +} + +func getSourceDirPath() string { + _, file, _, ok := runtime.Caller(1) // get the caller's file. + if !ok { + return "unknown source" + } + + return path.Dir(file) // get the directory of the file (delimiter: /). +} diff --git a/logging/request-logger/accesslog-broker/main.go b/logging/request-logger/accesslog-broker/main.go new file mode 100644 index 00000000..7709153c --- /dev/null +++ b/logging/request-logger/accesslog-broker/main.go @@ -0,0 +1,114 @@ +package main + +import ( + "os" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/recover" +) + +func main() { + /* + On this example we will make use of the logs broker. + A handler will listen for any incoming logs and render + those logs as chunks of JSON to the client (e.g. browser) at real-time. + Note that this ^ can be done with Server-Sent Events but for the + sake of the example we'll do it using Transfer-Encoding: chunked. + */ + + ac := accesslog.File("./access.log") + defer ac.Close() + ac.AddOutput(os.Stdout) + + ac.RequestBody = true + // Set to false to print errors as one line: + // ac.KeepMultiLineError = false + // Set the "depth" of a panic trace: + ac.PanicLog = accesslog.LogHandler // or LogCallers or LogStack + + // Optionally run logging after response has sent: + // ac.Async = true + broker := ac.Broker() // <- IMPORTANT + + app := iris.New() + app.UseRouter(ac.Handler) + app.UseRouter(recover.New()) + + app.OnErrorCode(iris.StatusNotFound, notFoundHandler) + + app.Get("/panic", testPanic) + app.Get("/", indexHandler) + app.Get("/profile/{username}", profileHandler) + app.Post("/read_body", readBodyHandler) + + // register the /logs route, + // registers a listener and prints the incoming logs. + // Optionally, skip logging this handler. + app.Get("/logs", accesslog.SkipHandler, logsHandler(broker)) + + // http://localhost:8080/logs to see the logs at real-time. + app.Listen(":8080") +} + +func notFoundHandler(ctx iris.Context) { + // ctx.Application().Logger().Infof("Not Found Handler for: %s", ctx.Path()) + + suggestPaths := ctx.FindClosest(3) + if len(suggestPaths) == 0 { + ctx.WriteString("The page you're looking does not exist.") + return + } + + ctx.HTML("Did you mean?<ul>") + for _, s := range suggestPaths { + ctx.HTML(`<li><a href="%s">%s</a></li>`, s, s) + } + ctx.HTML("</ul>") +} + +func indexHandler(ctx iris.Context) { + ctx.HTML("<h1>Index</h1>") +} + +func profileHandler(ctx iris.Context) { + username := ctx.Params().Get("username") + ctx.HTML("Hello, <strong>%s</strong>!", username) +} + +func readBodyHandler(ctx iris.Context) { + var request interface{} + if err := ctx.ReadBody(&request); err != nil { + ctx.StopWithPlainError(iris.StatusBadRequest, err) + return + } + + ctx.JSON(iris.Map{"message": "OK", "data": request}) +} + +func testPanic(ctx iris.Context) { + panic("PANIC HERE") +} + +func logsHandler(b *accesslog.Broker) iris.Handler { + return func(ctx iris.Context) { + // accesslog.Skip(ctx) // or inline skip. + logs := b.NewListener() // <- IMPORTANT + + ctx.Header("Transfer-Encoding", "chunked") + notifyClose := ctx.Request().Context().Done() + for { + select { + case <-notifyClose: + b.CloseListener(logs) // <- IMPORTANT + + err := ctx.Request().Context().Err() + ctx.Application().Logger().Infof("Listener closed [%v], loop end.", err) + return + case log := <-logs: // <- IMPORTANT + ctx.JSON(log, iris.JSON{Indent: " ", UnescapeHTML: true}) + ctx.ResponseWriter().Flush() + } + } + } +} diff --git a/logging/request-logger/accesslog-csv/access_log.csv.sample b/logging/request-logger/accesslog-csv/access_log.csv.sample new file mode 100644 index 00000000..13fe5734 --- /dev/null +++ b/logging/request-logger/accesslog-csv/access_log.csv.sample @@ -0,0 +1,5 @@ +Timestamp,Latency,Code,Method,Path,IP,Req Values,In,Out,Request,Response +1599996265254,0s,200,GET,/,::1,a=1 b=2,0,5,,Index +1599996266138,0s,200,GET,/,::1,sleep=32ms,0,5,,Index +1599996266778,1s,200,GET,/,::1,sleep=1s,0,5,,Index +1599996267780,1s,200,GET,/,::1,sleep=1s,0,5,,Index diff --git a/logging/request-logger/accesslog-csv/main.go b/logging/request-logger/accesslog-csv/main.go new file mode 100644 index 00000000..c156d1a1 --- /dev/null +++ b/logging/request-logger/accesslog-csv/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" +) + +func main() { + app := iris.New() + ac := accesslog.File("access_log.csv") + ac.ResponseBody = true + ac.LatencyRound = time.Second + ac.SetFormatter(&accesslog.CSV{ + Header: true, + // DateScript: "FROM_UNIX", + }) + + app.UseRouter(ac.Handler) + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if sleepDur := ctx.URLParam("sleep"); sleepDur != "" { + if d, err := time.ParseDuration(sleepDur); err == nil { + time.Sleep(d) + } + } + + ctx.WriteString("Index") +} diff --git a/logging/request-logger/accesslog-formatter/main.go b/logging/request-logger/accesslog-formatter/main.go new file mode 100644 index 00000000..5e0bfe04 --- /dev/null +++ b/logging/request-logger/accesslog-formatter/main.go @@ -0,0 +1,129 @@ +// Package main shows how to create a quite fast custom Log Formatter. +// Note that, this example requires a little more knowledge about Go. +package main + +import ( + "bytes" + "fmt" + "io" + "strconv" + "sync" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/requestid" +) + +func logFields(ctx iris.Context, fields *accesslog.Fields) { + fields.Set("reqid", ctx.GetID()) +} + +func main() { + app := iris.New() + + ac := accesslog.File("./access.log"). + AddFields(logFields). + SetFormatter(newCustomFormatter(' ', "-\t\t\t\t\t")) + ac.RequestBody = false + ac.BytesReceivedBody = false + ac.BytesSentBody = false + defer ac.Close() + + app.UseRouter(ac.Handler) + app.UseRouter(requestid.New()) + + app.OnErrorCode(iris.StatusNotFound, notFound) + app.Get("/", index) + + app.Listen(":8080") +} + +func notFound(ctx iris.Context) { + ctx.WriteString("The page you're looking for does not exist!") +} + +func index(ctx iris.Context) { + ctx.WriteString("OK Index") +} + +type customFormatter struct { + w io.Writer + bufPool *sync.Pool + + delim byte + blank string +} + +var _ accesslog.Formatter = (*customFormatter)(nil) + +func newCustomFormatter(delim byte, blank string) *customFormatter { + return &customFormatter{delim: delim, blank: blank} +} + +func (f *customFormatter) SetOutput(dest io.Writer) { + f.w = dest + f.bufPool = &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + } + + if f.delim == 0 { + f.delim = ' ' + } +} + +const newLine = '\n' + +func (f *customFormatter) Format(log *accesslog.Log) (bool, error) { + buf := f.bufPool.Get().(*bytes.Buffer) + + buf.WriteString(log.Now.Format(log.TimeFormat)) + buf.WriteByte(f.delim) + + reqid := log.Fields.GetString("reqid") + f.writeTextOrBlank(buf, reqid) + + buf.WriteString(uniformDuration(log.Latency)) + buf.WriteByte(f.delim) + + buf.WriteString(log.IP) + buf.WriteByte(f.delim) + + buf.WriteString(strconv.Itoa(log.Code)) + buf.WriteByte(f.delim) + + buf.WriteString(log.Method) + buf.WriteByte(f.delim) + + buf.WriteString(log.Path) + + buf.WriteByte(newLine) + + // _, err := buf.WriteTo(f.w) + // or (to make sure that it resets on errors too): + _, err := f.w.Write(buf.Bytes()) + buf.Reset() + f.bufPool.Put(buf) + + return true, err +} + +func (f *customFormatter) writeTextOrBlank(buf *bytes.Buffer, s string) { + if len(s) == 0 { + if len(f.blank) == 0 { + return + } + + buf.WriteString(f.blank) + } else { + buf.WriteString(s) + } + + buf.WriteByte(f.delim) +} + +func uniformDuration(t time.Duration) string { + return fmt.Sprintf("%*s", 12, t.String()) +} diff --git a/logging/request-logger/accesslog-proxy/main.go b/logging/request-logger/accesslog-proxy/main.go new file mode 100644 index 00000000..51325504 --- /dev/null +++ b/logging/request-logger/accesslog-proxy/main.go @@ -0,0 +1,88 @@ +/* +Package main is a proxy + accesslog example. +In this example we will make a small proxy which listens requests on "/proxy/+path". +With two accesslog instances, one for the main application and one for the /proxy/ requests. +Of cource, you could a single accesslog for the whole application, but for the sake of the example +let's log them separately. + +We will make use of iris.StripPrefix and host.ProxyHandler. +*/ +package main + +import ( + "net/url" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/core/host" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/recover" +) + +func main() { + app := iris.New() + app.Get("/", index) + + ac := accesslog.File("access.log") + defer ac.Close() + ac.Async = true + ac.RequestBody = true + ac.ResponseBody = true + ac.BytesReceived = false + ac.BytesSent = false + + app.UseRouter(ac.Handler) + app.UseRouter(recover.New()) + + proxy := app.Party("/proxy") + { + acProxy := accesslog.File("proxy_access.log") + defer acProxy.Close() + acProxy.Async = true + acProxy.RequestBody = true + acProxy.ResponseBody = true + acProxy.BytesReceived = false + acProxy.BytesSent = false + + // Unlike Use, the UseRouter method replaces any duplications automatically. + // (see UseOnce for the same behavior on Use). + // Therefore, this statement removes the parent's accesslog and registers this new one. + proxy.UseRouter(acProxy.Handler) + proxy.UseRouter(recover.New()) + proxy.Use(func(ctx iris.Context) { + ctx.CompressReader(true) + ctx.Next() + }) + + /* Listen for specific proxy paths: + // Listen on "/proxy" for "http://localhost:9090/read-write" + proxy.Any("/", iris.StripPrefix("/proxy", + newProxyHandler("http://localhost:9090/read-write"))) + */ + + // You can register an access log only for proxied requests, e.g. proxy_access.log: + // proxy.UseRouter(ac2.Handler) + + // Listen for any proxy path. + // Proxies the "/proxy/+$path" to "http://localhost:9090/$path". + proxy.Any("/{p:path}", iris.StripPrefix("/proxy", + newProxyHandler("http://localhost:9090"))) + } + + // $ go run target/main.go + // open new terminal + // $ go run main.go + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.WriteString("OK") +} + +func newProxyHandler(proxyURL string) iris.Handler { + target, err := url.Parse(proxyURL) + if err != nil { + panic(err) + } + reverseProxy := host.ProxyHandler(target, nil) + return iris.FromStd(reverseProxy) +} diff --git a/logging/request-logger/accesslog-proxy/target/main.go b/logging/request-logger/accesslog-proxy/target/main.go new file mode 100644 index 00000000..b34007f2 --- /dev/null +++ b/logging/request-logger/accesslog-proxy/target/main.go @@ -0,0 +1,32 @@ +package main + +import "github.com/kataras/iris/v12" + +// The target server, can be written using any programming language and any web framework, of course. +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + // Just a test route which reads some data and responds back with json. + app.Post("/read-write", readWriteHandler) + + app.Get("/get", getHandler) + + // The target ip:port. + app.Listen(":9090") +} + +func readWriteHandler(ctx iris.Context) { + var req interface{} + ctx.ReadBody(&req) + + ctx.JSON(iris.Map{ + "message": "OK", + "request": req, + }) +} + +func getHandler(ctx iris.Context) { + // ctx.CompressWriter(true) + ctx.WriteString("Compressed data") +} diff --git a/logging/request-logger/accesslog-simple/access.log.sample b/logging/request-logger/accesslog-simple/access.log.sample new file mode 100644 index 00000000..dabdd4ac --- /dev/null +++ b/logging/request-logger/accesslog-simple/access.log.sample @@ -0,0 +1,2 @@ +{"timestamp":1599993744664,"latency":0,"code":404,"method":"GET","path":"/favicon.ico","ip":"::1","request":"","bytes_sent":9} +{"timestamp":1599993774018,"latency":0,"code":200,"method":"GET","path":"/","ip":"::1","query":[{"key":"a","value":"1"},{"key":"b","value":"2"}],"request":"","bytes_sent":2} diff --git a/logging/request-logger/accesslog-simple/main.go b/logging/request-logger/accesslog-simple/main.go new file mode 100644 index 00000000..b2d677d3 --- /dev/null +++ b/logging/request-logger/accesslog-simple/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" +) + +// Read the example and its comments carefully. +func makeAccessLog() *accesslog.AccessLog { + // Initialize a new access log middleware. + ac := accesslog.File("./access.log") + + // The default configuration: + ac.Delim = '|' + ac.TimeFormat = "2006-01-02 15:04:05" + ac.Async = false + ac.IP = true + ac.BytesReceivedBody = true + ac.BytesSentBody = true + ac.BytesReceived = false + ac.BytesSent = false + ac.BodyMinify = true + ac.RequestBody = true + ac.ResponseBody = false + ac.KeepMultiLineError = true + ac.PanicLog = accesslog.LogHandler + + // Default line format if formatter is missing: + // Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response| + // + // Set Custom Formatter: + ac.SetFormatter(&accesslog.JSON{ + Indent: " ", + HumanTime: true, + }) + // ac.SetFormatter(&accesslog.CSV{}) + // ac.SetFormatter(&accesslog.Template{Text: "{{.Code}}"}) + + return ac +} + +func main() { + ac := makeAccessLog() + defer ac.Close() // Close the underline file. + + app := iris.New() + // Register the middleware (UseRouter to catch http errors too). + app.UseRouter(ac.Handler) + + app.Get("/", indexHandler) + + app.Listen(":8080") +} + +func indexHandler(ctx iris.Context) { + ctx.WriteString("OK") +} diff --git a/logging/request-logger/accesslog-slack/go.mod b/logging/request-logger/accesslog-slack/go.mod new file mode 100644 index 00000000..4c481430 --- /dev/null +++ b/logging/request-logger/accesslog-slack/go.mod @@ -0,0 +1,58 @@ +module github.com/kataras/iris/_examples/logging/accesslog-slack + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/slack-go/slack v0.12.5 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/logging/request-logger/accesslog-slack/go.sum b/logging/request-logger/accesslog-slack/go.sum new file mode 100644 index 00000000..de5ceb5a --- /dev/null +++ b/logging/request-logger/accesslog-slack/go.sum @@ -0,0 +1,193 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= +github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/slack-go/slack v0.12.5 h1:ddZ6uz6XVaB+3MTDhoW04gG+Vc/M/X1ctC+wssy2cqs= +github.com/slack-go/slack v0.12.5/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/logging/request-logger/accesslog-slack/main.go b/logging/request-logger/accesslog-slack/main.go new file mode 100644 index 00000000..81483b8b --- /dev/null +++ b/logging/request-logger/accesslog-slack/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "os" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" +) + +var ( + // https://api.slack.com/apps/your_app_id/oauth + token = os.Getenv("SLACK_BOT_TOKEN") + // on slack app: right click on the channel -> view channel details -> on bottom, copy the channel id. + channelID = os.Getenv("SLACK_CHANNEL_ID") +) + +// $ go run . +func main() { + app := iris.New() + + ac := accesslog.New(os.Stdout) // or app.Logger().Printer + ac.LatencyRound = time.Second + ac.SetFormatter(&Slack{ + Token: token, + ChannelIDs: []string{channelID}, + HandleMessage: true, + }) + + app.UseRouter(ac.Handler) + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if sleepDur := ctx.URLParam("sleep"); sleepDur != "" { + if d, err := time.ParseDuration(sleepDur); err == nil { + time.Sleep(d) + } + } + + ctx.WriteString("Index") +} diff --git a/logging/request-logger/accesslog-slack/slack_formatter.go b/logging/request-logger/accesslog-slack/slack_formatter.go new file mode 100644 index 00000000..19e67a2f --- /dev/null +++ b/logging/request-logger/accesslog-slack/slack_formatter.go @@ -0,0 +1,75 @@ +package main + +import ( + "io" + + "github.com/kataras/iris/v12/middleware/accesslog" + + "github.com/slack-go/slack" +) + +type Slack struct { + // Client is the underline slack slack. + // This or Token are required. + Client *slack.Client + // Token is the oauth slack client token. + // Read more at: https://api.slack.com/web#authentication. + // + // If Client is not null then this is used to initialize the Slack.Client field. + Token string + + // ChannelIDs specifies one or more channel the request logs + // will be printed to. + ChannelIDs []string + + // HandleMessage set to true whether the slack formatter + // should just send the log to the slack channel(s) and + // stop printing the log to the accesslog's io.Writer output. + HandleMessage bool + + // Template is the underline text template format of the logs. + // Set to a custom one if you want to customize the template (how the text is rended). + Template *accesslog.Template +} + +func (f *Slack) SetOutput(dest io.Writer) { + if f.Client == nil && f.Token == "" { + panic("client or token fields must be provided") + } + + if len(f.ChannelIDs) == 0 { + panic("channel ids field is required") + } + + if f.Token != "" { + c := slack.New(f.Token) + f.Client = c + } + + if f.Template == nil { + f.Template = &accesslog.Template{} + } + + f.Template.SetOutput(dest) +} + +func (f *Slack) Format(log *accesslog.Log) (bool, error) { + text, err := f.Template.LogText(log) + if err != nil { + return false, err + } + + for _, channelID := range f.ChannelIDs { + _, _, err := f.Client.PostMessage( + channelID, + slack.MsgOptionText(text, false), + slack.MsgOptionAsUser(true), + ) + + if err != nil { + return false, err + } + } + + return f.HandleMessage, nil +} diff --git a/logging/request-logger/accesslog-template/main.go b/logging/request-logger/accesslog-template/main.go new file mode 100644 index 00000000..223e8a47 --- /dev/null +++ b/logging/request-logger/accesslog-template/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/requestid" +) + +func main() { + /* + This example will show you how you can + register custom fields and log them separately + with a custom format through the Template formatter. + */ + + app := iris.New() + ac := accesslog.File("./access.log").AddOutput(app.Logger().Printer) + defer ac.Close() + + // 1. Register a field. + ac.AddFields(func(ctx iris.Context, fields *accesslog.Fields) { + fields.Set("Request ID", ctx.GetID()) + }) + + // 2. Use Template formatter's `Text` value + // to define a log line format. + ac.SetFormatter(&accesslog.Template{ + Text: `{{.Now.Format .TimeFormat}} {{.Path}} {{.Code}} {{.IP}} {{.Fields.Get "Request ID" }} +`, /* 2020-09-11 09:30:10 / 200 ::1 050a0979-c5e4-4c2b-9f08-cb456628edb1 */ + }) + // 3. Register the middleware. That's all. + app.UseRouter(ac.Handler) + // Register the request id middleware, after the logger, this maps the Context.GetID(). + // Remember: the accesslog runs the next handlers before itself to provide some fields. + app.UseRouter(requestid.New()) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.WriteString("Index") +} + +/* Use a custom *template.Template: + +// 2.1 The log line format: +text := `{{.Now.Format .TimeFormat}} {{.Path}} {{.Code}} {{.IP}} {{.Fields.Get "Request ID" }} +` +// +// 2.2 Parse the template, optionally using custom Template Functions. +tmpl := template.Must(template.New("").Funcs(template.FuncMap{ + // Custom functions you may want to use inside "text", + // e.g. prefixFields .Fields "my_prefix" + // to get a slice of fields starts with "my_prefix" + // and later, in the template, loop through them and render their values. + // "key": func(input) string { return ... } +}).Parse(text)) +// +// 3. Use Template formatter's `Text` value +// or the `Tmpl` field to customize the look & feel of a log. +ac.SetFormatter(&accesslog.Template{ + Tmpl: tmpl, +}) + +*/ diff --git a/logging/request-logger/accesslog/access.log.sample b/logging/request-logger/accesslog/access.log.sample new file mode 100644 index 00000000..09a660b1 --- /dev/null +++ b/logging/request-logger/accesslog/access.log.sample @@ -0,0 +1,10 @@ +2020-09-13 13:37:42 2.0057ms 200 POST /read_body ::1 61 B 94 B {"name":"John","email":"example@example.com"} +2020-09-13 13:37:50 0s 400 POST /read_body ::1 0 B 0 B error(invalid character '\r' in string literal) +2020-09-13 13:38:03 0s 404 GET /favicon.ico ::1 0 B 9 B +2020-09-13 13:38:07 0s 404 GET /public ::1 0 B 9 B +2020-09-13 13:38:09 1.0021ms 200 GET /user/kataras ::1 username=kataras 0 B 15 B +2020-09-13 13:38:14 0s 200 GET /user/kataras ::1 username=kataras a_query_parameter=name 0 B 15 B +2020-09-13 13:38:18 0s 401 GET /admin ::1 0 B 0 B +2020-09-13 13:38:19 0s 200 GET /admin ::1 auth=admin:admin 0 B 48 B +2020-09-13 13:38:22 0s 200 GET /session ::1 session_id=23fe763f-c9d5-4d65-9e1a-2cc8d23d1aa3 session_test_key=session_test_value auth=admin:admin 0 B 2 B +2020-09-13 13:38:25 2.0001204s 200 GET /fields ::1 job_latency=2s auth=admin:admin user=user-id:user-name 0 B 2 B diff --git a/logging/request-logger/accesslog/main.go b/logging/request-logger/accesslog/main.go new file mode 100644 index 00000000..aebc1063 --- /dev/null +++ b/logging/request-logger/accesslog/main.go @@ -0,0 +1,191 @@ +package main // See https://github.com/kataras/iris/issues/1601 + +import ( + "bufio" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/basicauth" + "github.com/kataras/iris/v12/middleware/requestid" + "github.com/kataras/iris/v12/sessions" + + rotatelogs "github.com/iproj/file-rotatelogs" +) + +// Default line format: +// Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response| +// +// Read the example and its comments carefully. +func makeAccessLog() *accesslog.AccessLog { + // Optionally, let's Go with log rotation. + pathToAccessLog := "./access_log.%Y%m%d%H%M" + w, err := rotatelogs.New( + pathToAccessLog, + rotatelogs.WithMaxAge(24*time.Hour), + rotatelogs.WithRotationTime(time.Hour)) + if err != nil { + panic(err) + } + + // Initialize a new access log middleware. + // Accepts an `io.Writer`. + ac := accesslog.New(bufio.NewWriter(w)) + ac.Delim = ' ' // change the separator from '|' to space. + // ac.TimeFormat = "2006-01-02 15:04:05" // default + + // Example of adding more than one field to the logger. + // Here we logging all the session values this request has. + // + // You can also add fields per request handler, + // look below to the `fieldsHandler` function. + // Note that this method can override a key stored by a handler's fields. + ac.AddFields(func(ctx iris.Context, fields *accesslog.Fields) { + if sess := sessions.Get(ctx); sess != nil { + fields.Set("session_id", sess.ID()) + + sess.Visit(func(k string, v interface{}) { + fields.Set(k, v) + }) + } + }) + // Add a custom field of "auth" when basic auth is available. + ac.AddFields(func(ctx iris.Context, fields *accesslog.Fields) { + if username, password, ok := ctx.Request().BasicAuth(); ok { + fields.Set("auth", username+":"+password) + } + }) + + return ac + + /* + Use a file directly: + ac := accesslog.File("./access.log") + + Log after the response was sent (defaults to false): + ac.Async = true + + Force-protect writer with locks. + On this example this is not required: + ac.LockWriter = true" + + // To disable request and response calculations + // (enabled by default but slows down the whole operation if Async is false): + ac.RequestBody = false + ac.ResponseBody = false + ac.BytesReceived = false + ac.BytesSent = false + ac.BytesReceivedBody = false + ac.BytesSentBody = false + + Add second output: + ac.AddOutput(app.Logger().Printer) + OR: + accesslog.New(io.MultiWriter(w, os.Stdout)) + + Change format (after output was set): + ac.SetFormatter(&accesslog.JSON{Indent: " "}) + + Modify the output format and customize the order + with the Template formatter: + ac.SetFormatter(&accesslog.Template{ + Text: "{{.Now.Format .TimeFormat}}|{{.Latency}}|{{.Code}}|{{.Method}}|{{.Path}}|{{.IP}}|{{.RequestValuesLine}}|{{.BytesReceivedLine}}|{{.BytesSentLine}}|{{.Request}}|{{.Response}}|\n", + // Default ^ + }) + */ +} + +func main() { + ac := makeAccessLog() + defer ac.Close() + + app := iris.New() + // Register the middleware (UseRouter to catch http errors too). + app.UseRouter(ac.Handler) + // + + // Register other middlewares... + app.UseRouter(requestid.New()) + + // Register some routes... + app.HandleDir("/", iris.Dir("./public")) + + app.Get("/user/{username}", userHandler) + app.Post("/read_body", readBodyHandler) + app.Get("/html_response", htmlResponse) + + basicAuth := basicauth.Default(map[string]string{ + "admin": "admin", + }) + app.Get("/admin", basicAuth, adminHandler) + + sess := sessions.New(sessions.Config{Cookie: "my_session_id", AllowReclaim: true}) + app.Get("/session", sess.Handler(), sessionHandler) + + app.Get("/fields", fieldsHandler) + // + + app.Listen(":8080") +} + +func readBodyHandler(ctx iris.Context) { + var request interface{} + if err := ctx.ReadBody(&request); err != nil { + ctx.StopWithPlainError(iris.StatusBadRequest, err) + return + } + + ctx.JSON(iris.Map{"message": "OK", "data": request}) +} + +func userHandler(ctx iris.Context) { + ctx.Writef("Hello, %s!", ctx.Params().Get("username")) +} + +func htmlResponse(ctx iris.Context) { + ctx.HTML("<h1>HTML Response</h1>") +} + +func adminHandler(ctx iris.Context) { + username, password, _ := ctx.Request().BasicAuth() + // of course you don't want that in production: + ctx.HTML("<h2>Username: %s</h2><h3>Password: %s</h3>", username, password) +} + +func sessionHandler(ctx iris.Context) { + sess := sessions.Get(ctx) + sess.Set("session_test_key", "session_test_value") + + ctx.WriteString("OK") +} + +type user struct { + ID string + Username string +} + +// Log custom structs, they can implement the fmt.Stringer interface too. +func (u user) String() string { + return u.ID + ":" + u.Username +} + +func fieldsHandler(ctx iris.Context) { + start := time.Now() + // simulate a heavy job... + time.Sleep(2 * time.Second) + end := time.Since(start) + // Get the current fields instance + // and use it to set custom log values. + logFields := accesslog.GetFields(ctx) + logFields.Set("job_latency", end.Round(time.Second)) + + // Simulate a database fetch or anything + // to get a "user" and log it: + u := user{ + ID: "user-id", + Username: "user-name", + } + logFields.Set("user", u) + + ctx.WriteString("OK") +} diff --git a/logging/request-logger/accesslog/public/index.html b/logging/request-logger/accesslog/public/index.html new file mode 100644 index 00000000..06651a45 --- /dev/null +++ b/logging/request-logger/accesslog/public/index.html @@ -0,0 +1 @@ +<h1>Hello index</h1> \ No newline at end of file diff --git a/logging/rollbar/go.mod b/logging/rollbar/go.mod new file mode 100644 index 00000000..b2db7317 --- /dev/null +++ b/logging/rollbar/go.mod @@ -0,0 +1,54 @@ +module github.com/kataras/iris/examples/logging/rollbar + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/rollbar/rollbar-go v1.4.5 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/logging/rollbar/go.sum b/logging/rollbar/go.sum new file mode 100644 index 00000000..6f9eacff --- /dev/null +++ b/logging/rollbar/go.sum @@ -0,0 +1,180 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rollbar/rollbar-go v1.4.5 h1:Z+5yGaZdB7MFv7t759KUR3VEkGdwHjo7Avvf3ApHTVI= +github.com/rollbar/rollbar-go v1.4.5/go.mod h1:kLQ9gP3WCRGrvJmF0ueO3wK9xWocej8GRX98D8sa39w= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/logging/rollbar/main.go b/logging/rollbar/main.go new file mode 100644 index 00000000..0903f886 --- /dev/null +++ b/logging/rollbar/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "errors" + "fmt" + "os" + "runtime/debug" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/requestid" + + "github.com/rollbar/rollbar-go" +) + +// * https://rollbar.com/signup +// * https://docs.rollbar.com/docs/go +func init() { + token := os.Getenv("ROLLBAR_TOKEN") // replace that with your token. + if token == "" { + panic("ROLLBAR_TOKEN is missing") + } + + // rb := rollbar.NewAsync(token, "production", "", hostname, "github.com/kataras/iris") + // Or use the package-level instance: + rollbar.SetToken(token) + // defaults to "development" + rollbar.SetEnvironment("production") + // optional Git hash/branch/tag (required for GitHub integration) + // rollbar.SetCodeVersion("v2") + // optional override; defaults to hostname + // rollbar.SetServerHost("web.1") + // path of project (required for GitHub integration and non-project stacktrace collapsing) + rollbar.SetServerRoot("github.com/kataras/iris") + +} + +func main() { + app := iris.New() + // A middleware which sets the ctx.GetID (or requestid.Get(ctx)). + app.Use(requestid.New()) + // A recover middleware which sends the error trace to the rollbar. + app.Use(func(ctx iris.Context) { + defer func() { + if r := recover(); r != nil { + debug.PrintStack() + + file, line := ctx.HandlerFileLine() // the failed handler's source code position. + + // cause other info + rollbar.Critical(errors.New(fmt.Sprint(r)), iris.Map{ + "request_id": ctx.GetID(), + "request_ip": ctx.RemoteAddr(), + "request_uri": ctx.FullRequestURI(), + "handler": iris.Map{ + "name": ctx.HandlerName(), // the handler which failed. + "file": fmt.Sprintf("%s:%d", file, line), + }, + }) + + ctx.StopWithStatus(iris.StatusInternalServerError) + } + }() + + ctx.Next() + }) + + app.Get("/", index) + app.Get("/panic", panicMe) + + // http://localhost:8080 should add an info message to the rollbar's "Items" dashboard. + // http://localhost:8080/panic should add a critical message to the rollbar's "Items" dashboard, + // with the corresponding information appending on its "Occurrences" tab item, e.g: + // Timestamp (PDT) + // * 2020-06-08 04:47 pm + // + // server.host + // * DESKTOP-HOSTNAME + // + // trace_chain.0.exception.message + // * a critical error message here + // + // custom.handler.file + // * C:/mygopath/src/github.com/kataras/iris/_examples/logging/rollbar/main.go:76 + // + // custom.handler.name + // * main.panicMe + // + // custom.request_id + // * cce61665-0c1b-4fb5-8547-06a3537e477c + // + // custom.request_ip + // * ::1 + // + // custom.request_uri + // * http://localhost:8080/panic + app.Listen(":8080") +} + +func index(ctx iris.Context) { + rollbar.Info(fmt.Sprintf("Index page requested by %s", ctx.RemoteAddr())) + + ctx.HTML("<h1> Index Page </h1>") +} + +func panicMe(ctx iris.Context) { + panic("a critical error message here") +} diff --git a/miscellaneous/file-logger/main.go b/miscellaneous/file-logger/main.go deleted file mode 100644 index 59b98a1d..00000000 --- a/miscellaneous/file-logger/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "os" - "time" - - "github.com/kataras/iris" -) - -// get a filename based on the date, file logs works that way the most times -// but these are just a sugar. -func todayFilename() string { - today := time.Now().Format("Jan 02 2006") - return today + ".txt" -} - -func newLogFile() *os.File { - filename := todayFilename() - // open an output file, this will append to the today's file if server restarted. - f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - panic(err) - } - - return f -} - -func main() { - f := newLogFile() - defer f.Close() - - app := iris.New() - // attach the file as logger, remember, iris' app logger is just an io.Writer. - app.Logger().SetOutput(newLogFile()) - - app.Get("/", func(ctx iris.Context) { - // for the sake of simplicity, in order see the logs at the ./_today_.txt - ctx.Application().Logger().Info("Request path: " + ctx.Path()) - ctx.Writef("hello") - }) - - // navigate to http://localhost:8080 - // and open the ./logs.txt file - if err := app.Run(iris.Addr(":8080"), iris.WithoutBanner); err != nil { - if err != iris.ErrServerClosed { - app.Logger().Warn("Shutdown with error: " + err.Error()) - } - } -} diff --git a/miscellaneous/i18n/locales/locale_el-GR.ini b/miscellaneous/i18n/locales/locale_el-GR.ini deleted file mode 100644 index a99e7fcc..00000000 --- a/miscellaneous/i18n/locales/locale_el-GR.ini +++ /dev/null @@ -1 +0,0 @@ -hi = γεια, %s \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_en-US.ini b/miscellaneous/i18n/locales/locale_en-US.ini deleted file mode 100644 index b2a39433..00000000 --- a/miscellaneous/i18n/locales/locale_en-US.ini +++ /dev/null @@ -1 +0,0 @@ -hi = hello, %s \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_multi_first_el-GR.ini b/miscellaneous/i18n/locales/locale_multi_first_el-GR.ini deleted file mode 100644 index cf043c86..00000000 --- a/miscellaneous/i18n/locales/locale_multi_first_el-GR.ini +++ /dev/null @@ -1 +0,0 @@ -key1 = αυτό είναι μια τιμή από το πρώτο αρχείο: locale_multi_first \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_multi_first_en-US.ini b/miscellaneous/i18n/locales/locale_multi_first_en-US.ini deleted file mode 100644 index 9e264821..00000000 --- a/miscellaneous/i18n/locales/locale_multi_first_en-US.ini +++ /dev/null @@ -1 +0,0 @@ -key1 = this is a value from the first file: locale_multi_first \ No newline at end of file diff --git a/miscellaneous/i18n/locales/locale_zh-CN.ini b/miscellaneous/i18n/locales/locale_zh-CN.ini deleted file mode 100644 index 0a7c91b0..00000000 --- a/miscellaneous/i18n/locales/locale_zh-CN.ini +++ /dev/null @@ -1 +0,0 @@ -hi = 您好,%s \ No newline at end of file diff --git a/miscellaneous/i18n/main.go b/miscellaneous/i18n/main.go deleted file mode 100644 index ab7b53cc..00000000 --- a/miscellaneous/i18n/main.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/i18n" -) - -func newApp() *iris.Application { - app := iris.New() - - globalLocale := i18n.New(i18n.Config{ - Default: "en-US", - URLParameter: "lang", - Languages: map[string]string{ - "en-US": "./locales/locale_en-US.ini", - "el-GR": "./locales/locale_el-GR.ini", - "zh-CN": "./locales/locale_zh-CN.ini"}}) - app.Use(globalLocale) - - app.Get("/", func(ctx iris.Context) { - - // it tries to find the language by: - // ctx.Values().GetString("language") - // if that was empty then - // it tries to find from the URLParameter setted on the configuration - // if not found then - // it tries to find the language by the "language" cookie - // if didn't found then it it set to the Default setted on the configuration - - // hi is the key, 'iris' is the %s on the .ini file - // the second parameter is optional - - // hi := ctx.Translate("hi", "iris") - // or: - hi := i18n.Translate(ctx, "hi", "iris") - - language := ctx.Values().GetString(ctx.Application().ConfigurationReadOnly().GetTranslateLanguageContextKey()) - // return is form of 'en-US' - - // The first succeed language found saved at the cookie with name ("language"), - // you can change that by changing the value of the: iris.TranslateLanguageContextKey - ctx.Writef("From the language %s translated output: %s", language, hi) - }) - - multiLocale := i18n.New(i18n.Config{ - Default: "en-US", - URLParameter: "lang", - Languages: map[string]string{ - "en-US": "./locales/locale_multi_first_en-US.ini, ./locales/locale_multi_second_en-US.ini", - "el-GR": "./locales/locale_multi_first_el-GR.ini, ./locales/locale_multi_second_el-GR.ini"}}) - - app.Get("/multi", multiLocale, func(ctx iris.Context) { - language := ctx.Values().GetString(ctx.Application().ConfigurationReadOnly().GetTranslateLanguageContextKey()) - - fromFirstFileValue := i18n.Translate(ctx, "key1") - fromSecondFileValue := i18n.Translate(ctx, "key2") - ctx.Writef("From the language: %s, translated output:\n%s=%s\n%s=%s", - language, "key1", fromFirstFileValue, - "key2", fromSecondFileValue) - }) - - return app -} - -func main() { - app := newApp() - - // go to http://localhost:8080/?lang=el-GR - // or http://localhost:8080 (default is en-US) - // or http://localhost:8080/?lang=zh-CN - // - // go to http://localhost:8080/multi?lang=el-GR - // or http://localhost:8080/multi (default is en-US) - // or http://localhost:8080/multi?lang=en-US - // - // or use cookies to set the language. - app.Run(iris.Addr(":8080")) -} diff --git a/miscellaneous/i18n/main_test.go b/miscellaneous/i18n/main_test.go deleted file mode 100644 index 2594c2fa..00000000 --- a/miscellaneous/i18n/main_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "fmt" - "testing" - - "github.com/kataras/iris/httptest" -) - -func TestI18n(t *testing.T) { - app := newApp() - - expectedf := "From the language %s translated output: %s" - var ( - elgr = fmt.Sprintf(expectedf, "el-GR", "γεια, iris") - enus = fmt.Sprintf(expectedf, "en-US", "hello, iris") - zhcn = fmt.Sprintf(expectedf, "zh-CN", "您好,iris") - - elgrMulti = fmt.Sprintf("From the language: %s, translated output:\n%s=%s\n%s=%s", "el-GR", - "key1", - "αυτό είναι μια τιμή από το πρώτο αρχείο: locale_multi_first", - "key2", - "αυτό είναι μια τιμή από το δεύτερο αρχείο μετάφρασης: locale_multi_second") - enusMulti = fmt.Sprintf("From the language: %s, translated output:\n%s=%s\n%s=%s", "en-US", - "key1", - "this is a value from the first file: locale_multi_first", - "key2", - "this is a value from the second file: locale_multi_second") - ) - - e := httptest.New(t, app) - // default is en-US - e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal(enus) - // default is en-US if lang query unable to be found - e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal(enus) - - e.GET("/").WithQueryString("lang=el-GR").Expect().Status(httptest.StatusOK). - Body().Equal(elgr) - e.GET("/").WithQueryString("lang=en-US").Expect().Status(httptest.StatusOK). - Body().Equal(enus) - e.GET("/").WithQueryString("lang=zh-CN").Expect().Status(httptest.StatusOK). - Body().Equal(zhcn) - - e.GET("/multi").WithQueryString("lang=el-GR").Expect().Status(httptest.StatusOK). - Body().Equal(elgrMulti) - e.GET("/multi").WithQueryString("lang=en-US").Expect().Status(httptest.StatusOK). - Body().Equal(enusMulti) - -} diff --git a/monitor/monitor-middleware/main.go b/monitor/monitor-middleware/main.go new file mode 100644 index 00000000..79208853 --- /dev/null +++ b/monitor/monitor-middleware/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/v12/middleware/monitor" +) + +func main() { + app := iris.New() + + // Initialize and start the monitor middleware. + m := monitor.New(monitor.Options{ + RefreshInterval: 2 * time.Second, + ViewRefreshInterval: 2 * time.Second, + ViewTitle: "MyServer Monitor", + }) + // Manually stop monitoring on CMD/CTRL+C. + iris.RegisterOnInterrupt(m.Stop) + + // Serve the actual server's process and operating system statistics as JSON. + app.Post("/monitor", m.Stats) + // Render with the default page. + app.Get("/monitor", m.View) + + /* You can protect the /monitor under an /admin group of routes + with basic authentication or any type authorization and authentication system. + Example Code: + + app.Post("/monitor", myProtectMiddleware, m.Stats) + app.Get("/monitor", myProtectMiddleware, m.View) + */ + + /* You can also get the OS statistics using the Holder.GetStats method. + Example Code: + for { + stats := m.Holder.GetStats() + fmt.Printf("%#+v\n", stats) + time.Sleep(time.Second) + } + + Note that the same stats are also stored in the expvar metrics: + - pid_cpu + - pid_ram + - pid_conns + - os_cpu + - os_ram + - os_total_ram + - os_load_avg + - os_conns + Check https://github.com/iris-contrib/middleware/tree/master/expmetric + which can be integrated with datadog or other platforms. + */ + + app.Get("/", handler) + + app.Listen(":8080") +} + +func handler(ctx iris.Context) { + ctx.WriteString("Test Index Handler") +} diff --git a/monitor/statsviz/go.mod b/monitor/statsviz/go.mod new file mode 100644 index 00000000..e89e3463 --- /dev/null +++ b/monitor/statsviz/go.mod @@ -0,0 +1,55 @@ +module github.com/kataras/iris/_examples/statsviz + +go 1.22 + +require ( + github.com/arl/statsviz v0.6.0 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/monitor/statsviz/go.sum b/monitor/statsviz/go.sum new file mode 100644 index 00000000..9a9d5948 --- /dev/null +++ b/monitor/statsviz/go.sum @@ -0,0 +1,184 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/arl/statsviz v0.6.0 h1:jbW1QJkEYQkufd//4NDYRSNBpwJNrdzPahF7ZmoGdyE= +github.com/arl/statsviz v0.6.0/go.mod h1:0toboo+YGSUXDaS4g1D5TVS4dXs7S7YYT5J/qnW2h8s= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/monitor/statsviz/main.go b/monitor/statsviz/main.go new file mode 100644 index 00000000..6063b15d --- /dev/null +++ b/monitor/statsviz/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "strings" + "time" + + "github.com/kataras/iris/v12" + + "github.com/arl/statsviz" +) + +// $ go get github.com/arl/statsviz +func main() { + app := iris.New() + // Register a router wrapper for this one. + statsvizPath := "/debug/statsviz" + serveRoot := statsviz.IndexAtRoot(statsvizPath) + serveWS := statsviz.NewWsHandler(time.Second) + app.UseRouter(func(ctx iris.Context) { + // You can optimize this if branch, I leave it to you as an exercise. + if strings.HasPrefix(ctx.Path(), statsvizPath+"/ws") { + serveWS(ctx.ResponseWriter(), ctx.Request()) + } else if strings.HasPrefix(ctx.Path(), statsvizPath) { + serveRoot(ctx.ResponseWriter(), ctx.Request()) + } else { + ctx.Next() + } + }) + // + + // Register other routes. + app.Get("/", index) + + // Navigate to: http://localhost:8080/debug/statsviz/ + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.WriteString("Hello, World!") +} diff --git a/mvc/README.md b/mvc/README.md deleted file mode 100644 index 68733e39..00000000 --- a/mvc/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# MVC - - - -Iris has **first-class support for the MVC pattern**, you'll not find -these stuff anywhere else in the Go world. - -Iris supports Request data, Models, Persistence Data and Binding -with the fastest possible execution. - -## Characteristics - -All HTTP Methods are supported, for example if want to serve `GET` -then the controller should have a function named `Get()`, -you can define more than one method function to serve in the same Controller. - -Serve custom controller's struct's methods as handlers with custom paths(even with regex parametermized path) -via the `BeforeActivation` custom event callback, per-controller. Example: - -```go -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" -) - -func main() { - app := iris.New() - mvc.Configure(app.Party("/root"), myMVC) - app.Run(iris.Addr(":8080")) -} - -func myMVC(app *mvc.Application) { - // app.Register(...) - // app.Router.Use/UseGlobal/Done(...) - app.Handle(new(MyController)) -} - -type MyController struct {} - -func (m *MyController) BeforeActivation(b mvc.BeforeActivation) { - // b.Dependencies().Add/Remove - // b.Router().Use/UseGlobal/Done // and any standard API call you already know - - // 1-> Method - // 2-> Path - // 3-> The controller's function name to be parsed as handler - // 4-> Any handlers that should run before the MyCustomHandler - b.Handle("GET", "/something/{id:long}", "MyCustomHandler", anyMiddleware...) -} - -// GET: http://localhost:8080/root -func (m *MyController) Get() string { return "Hey" } - -// GET: http://localhost:8080/root/something/{id:long} -func (m *MyController) MyCustomHandler(id int64) string { return "MyCustomHandler says Hey" } -``` - -Persistence data inside your Controller struct (share data between requests) -by defining services to the Dependencies or have a `Singleton` controller scope. - -Share the dependencies between controllers or register them on a parent MVC Application, and ability -to modify dependencies per-controller on the `BeforeActivation` optional event callback inside a Controller, -i.e `func(c *MyController) BeforeActivation(b mvc.BeforeActivation) { b.Dependencies().Add/Remove(...) }`. - -Access to the `Context` as a controller's field(no manual binding is neede) i.e `Ctx iris.Context` or via a method's input argument, i.e `func(ctx iris.Context, otherArguments...)`. - -Models inside your Controller struct (set-ed at the Method function and rendered by the View). -You can return models from a controller's method or set a field in the request lifecycle -and return that field to another method, in the same request lifecycle. - -Flow as you used to, mvc application has its own `Router` which is a type of `iris/router.Party`, the standard iris api. -`Controllers` can be registered to any `Party`, including Subdomains, the Party's begin and done handlers work as expected. - -Optional `BeginRequest(ctx)` function to perform any initialization before the method execution, -useful to call middlewares or when many methods use the same collection of data. - -Optional `EndRequest(ctx)` function to perform any finalization after any method executed. - -Inheritance, recursively, see for example our `mvc.SessionController`, it has the `Session *sessions.Session` and `Manager *sessions.Sessions` as embedded fields -which are filled by its `BeginRequest`, [here](https://github.com/kataras/iris/blob/master/mvc/session_controller.go). -This is just an example, you could use the `sessions.Session` as a dependency to the MVC Application, i.e -`mvcApp.Register(sessions.New(sessions.Config{Cookie: "iris_session_id"}).Start)`. - -Access to the dynamic path parameters via the controller's methods' input arguments, no binding is needed. -When you use the Iris' default syntax to parse handlers from a controller, you need to suffix the methods -with the `By` word, uppercase is a new sub path. Example: - -If `mvc.New(app.Party("/user")).Handle(new(user.Controller))` - -- `func(*Controller) Get()` - `GET:/user`. -- `func(*Controller) Post()` - `POST:/user`. -- `func(*Controller) GetLogin()` - `GET:/user/login` -- `func(*Controller) PostLogin()` - `POST:/user/login` -- `func(*Controller) GetProfileFollowers()` - `GET:/user/profile/followers` -- `func(*Controller) PostProfileFollowers()` - `POST:/user/profile/followers` -- `func(*Controller) GetBy(id int64)` - `GET:/user/{param:long}` -- `func(*Controller) PostBy(id int64)` - `POST:/user/{param:long}` - -If `mvc.New(app.Party("/profile")).Handle(new(profile.Controller))` - -- `func(*Controller) GetBy(username string)` - `GET:/profile/{param:string}` - -If `mvc.New(app.Party("/assets")).Handle(new(file.Controller))` - -- `func(*Controller) GetByWildard(path string)` - `GET:/assets/{param:path}` - - Supported types for method functions receivers: int, int64, bool and string. - -Response via output arguments, optionally, i.e - -```go -func(c *ExampleController) Get() string | - (string, string) | - (string, int) | - int | - (int, string) | - (string, error) | - error | - (int, error) | - (any, bool) | - (customStruct, error) | - customStruct | - (customStruct, int) | - (customStruct, string) | - mvc.Result or (mvc.Result, error) -``` - -where [mvc.Result](https://github.com/kataras/iris/blob/master/mvc/func_result.go) is an interface which contains only that function: `Dispatch(ctx iris.Context)`. - -## Using Iris MVC for code reuse - -By creating components that are independent of one another, developers are able to reuse components quickly and easily in other applications. The same (or similar) view for one application can be refactored for another application with different data because the view is simply handling how the data is being displayed to the user. - -If you're new to back-end web development read about the MVC architectural pattern first, a good start is that [wikipedia article](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). - -## Examples - -- [Hello world](hello-world/main.go) **UPDATED** -- [Session Controller](session-controller/main.go) **UPDATED** -- [Overview - Plus Repository and Service layers](overview) **UPDATED** -- [Login showcase - Plus Repository and Service layers](login) **UPDATED** -- [Singleton](singleton) **NEW** -- [Websocket Controller](websocket) **NEW** -- [Register Middleware](middleware) **NEW** - -Folder structure guidelines can be found at the [_examples/#structuring](https://github.com/kataras/iris/tree/master/_examples/#structuring) section. \ No newline at end of file diff --git a/mvc/authenticated-controller/main.go b/mvc/authenticated-controller/main.go new file mode 100644 index 00000000..730d0c52 --- /dev/null +++ b/mvc/authenticated-controller/main.go @@ -0,0 +1,121 @@ +// Package main shows how to use a dependency to check if a user is logged in +// using a special custom Go type `Authenticated`, which when, +// present on a controller's method or a field then +// it limits the visibility to "authenticated" users only. +// +// The same result could be done through a middleware as well, however using a static type +// any person reads your code can see that an "X" controller or method +// should only be used by "authenticated" users. +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" +) + +func main() { + app := newApp() + // app.UseRouter(iris.Compression) + app.Logger().SetLevel("debug") + + // Open a client, e.g. Postman and visit the below endpoints. + // GET: http://localhost:8080/user (UnauthenticatedUserController.Get) + // POST: http://localhost:8080/user/login (UnauthenticatedUserController.PostLogin) + // GET: http://localhost:8080/user (UserController.Get) + // POST: http://localhost:8080/user/logout (UserController.PostLogout) + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + sess := sessions.New(sessions.Config{ + Cookie: "myapp_session_id", + AllowReclaim: true, + }) + app.Use(sess.Handler()) + + userRouter := app.Party("/user") + { + // Use that in order to be able to register a route twice, + // last one will be executed if the previous route's handler(s) stopped and the response can be reset-ed. + // See core/router/route_register_rule_test.go#TestRegisterRuleOverlap. + userRouter.SetRegisterRule(iris.RouteOverlap) + + // Initialize a new MVC application on top of the "userRouter". + userApp := mvc.New(userRouter) + // Register Dependencies. + userApp.Register(authDependency) + + // Register Controllers. + userApp.Handle(new(UserController)) + userApp.Handle(new(UnauthenticatedUserController)) + } + + return app +} + +// Authenticated is a custom type used as "annotation" for resources that requires authentication, +// its value should be the logged user ID. +type Authenticated uint64 + +func authDependency(ctx iris.Context, session *sessions.Session) Authenticated { + userID := session.GetUint64Default("user_id", 0) + if userID == 0 { + // If execution was stopped + // any controller's method will not be executed at all. + // + // Note that, the below will not fire the error to the user: + // ctx.StopWithStatus(iris.StatusUnauthorized) + // because of the imaginary: + // UnauthenticatedUserController.Get() (string, int) { + // return "...", iris.StatusOK + // } + // + // OR + // If you don't want to set a status code at all: + ctx.StopExecution() + return 0 + } + + return Authenticated(userID) +} + +// UnauthenticatedUserController serves the "public" Unauthorized User API. +type UnauthenticatedUserController struct{} + +// Get registers a route that will be executed when authentication is not passed +// (see UserController.Get) too. +func (c *UnauthenticatedUserController) Get() string { + return "custom action to redirect on authentication page" +} + +// PostLogin serves +// POST: /user/login +func (c *UnauthenticatedUserController) PostLogin(session *sessions.Session) mvc.Response { + session.Set("user_id", 1) + + // Redirect (you can still use the Context.Redirect if you want so). + return mvc.Response{ + Path: "/user", + Code: iris.StatusFound, + } +} + +// UserController serves the "public" User API. +type UserController struct { + CurrentUserID Authenticated +} + +// Get returns a message for the sake of the example. +// GET: /user +func (c *UserController) Get() string { + return `UserController.Get: The Authenticated type +can be used to secure a controller's method too.` +} + +// PostLogout serves +// POST: /user/logout +func (c *UserController) PostLogout(ctx iris.Context) { + sessions.Get(ctx).Man.Destroy(ctx) +} diff --git a/mvc/authenticated-controller/main_test.go b/mvc/authenticated-controller/main_test.go new file mode 100644 index 00000000..a65a9956 --- /dev/null +++ b/mvc/authenticated-controller/main_test.go @@ -0,0 +1,24 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestMVCOverlapping(t *testing.T) { + app := newApp() + + e := httptest.New(t, app, httptest.URL("http://example.com")) + // unauthenticated. + e.GET("/user").Expect().Status(httptest.StatusOK).Body().IsEqual("custom action to redirect on authentication page") + // login. + e.POST("/user/login").Expect().Status(httptest.StatusOK) + // authenticated. + e.GET("/user").Expect().Status(httptest.StatusOK).Body().IsEqual(`UserController.Get: The Authenticated type +can be used to secure a controller's method too.`) + // logout. + e.POST("/user/logout").Expect().Status(httptest.StatusOK) + // unauthenticated. + e.GET("/user").Expect().Status(httptest.StatusOK).Body().IsEqual("custom action to redirect on authentication page") +} diff --git a/mvc/basic/main.go b/mvc/basic/main.go index b5299221..f8ca0d6d 100644 --- a/mvc/basic/main.go +++ b/mvc/basic/main.go @@ -3,26 +3,42 @@ package main import ( "fmt" - "github.com/kataras/iris" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + "github.com/kataras/iris/v12/middleware/recover" + "github.com/kataras/iris/v12/sessions" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12/mvc" ) func main() { app := iris.New() app.Logger().SetLevel("debug") - mvc.Configure(app.Party("/basic"), basicMVC) - app.Run(iris.Addr(":8080")) + basic := app.Party("/basic") + { + // Register middlewares to run under the /basic path prefix. + ac := accesslog.File("./basic_access.log") + defer ac.Close() + + basic.UseRouter(ac.Handler) + basic.UseRouter(recover.New()) + + mvc.Configure(basic, basicMVC) + } + + app.Listen(":8080") } func basicMVC(app *mvc.Application) { - // You can use normal middlewares at MVC apps of course. - app.Router.Use(func(ctx iris.Context) { - ctx.Application().Logger().Infof("Path: %s", ctx.Path()) - ctx.Next() - }) + // Disable verbose logging of controllers for this and its children mvc apps + // when the log level is "debug": + app.SetControllersNoLog(true) + + // You can still register middlewares at MVC apps of course. + // The app.Router returns the Party that this MVC + // was registered on. + // app.Router.UseRouter/Use/.... // Register dependencies which will be binding to the controller(s), // can be either a function which accepts an iris.Context and returns a single value (dynamic binding) @@ -30,10 +46,12 @@ func basicMVC(app *mvc.Application) { app.Register( sessions.New(sessions.Config{}).Start, &prefixedLogger{prefix: "DEV"}, + accesslog.GetFields, // Set custom fields through a controller or controller's methods. ) // GET: http://localhost:8080/basic // GET: http://localhost:8080/basic/custom + // GET: http://localhost:8080/basic/custom2 app.Handle(new(basicController)) // All dependencies of the parent *mvc.Application @@ -65,13 +83,13 @@ func (s *prefixedLogger) Log(msg string) { } type basicController struct { - Logger LoggerService - - Session *sessions.Session + Logger LoggerService // the static logger service attached to this app. + Session *sessions.Session // current HTTP session. + LogFields *accesslog.Fields // accesslog middleware custom fields. } func (c *basicController) BeforeActivation(b mvc.BeforeActivation) { - b.Handle("GET", "/custom", "Custom") + b.HandleMany("GET", "/custom /custom2", "Custom") } func (c *basicController) AfterActivation(a mvc.AfterActivation) { @@ -82,6 +100,7 @@ func (c *basicController) AfterActivation(a mvc.AfterActivation) { func (c *basicController) Get() string { count := c.Session.Increment("count", 1) + c.LogFields.Set("count", count) body := fmt.Sprintf("Hello from basicController\nTotal visits from you: %d", count) c.Logger.Log(body) diff --git a/mvc/basic/wildcard/main.go b/mvc/basic/wildcard/main.go new file mode 100644 index 00000000..915d3e3d --- /dev/null +++ b/mvc/basic/wildcard/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + usersRouter := app.Party("/users") + mvc.New(usersRouter).Handle(new(myController)) + // Same as: + // usersRouter.Get("/{p:path}", func(ctx iris.Context) { + // wildcardPathParameter := ctx.Params().Get("p") + // ctx.JSON(response{ + // Message: "The path parameter is: " + wildcardPathParameter, + // }) + // }) + + /* + curl --location --request GET 'http://localhost:8080/users/path_segment_1/path_segment_2' + + Expected Output: + { + "message": "The wildcard is: path_segment_1/path_segment_2" + } + */ + app.Listen(":8080") +} + +type myController struct{} + +type response struct { + Message string `json:"message"` +} + +func (c *myController) GetByWildcard(wildcardPathParameter string) response { + return response{ + Message: "The path parameter is: " + wildcardPathParameter, + } +} diff --git a/mvc/error-handler-custom-result/main.go b/mvc/error-handler-custom-result/main.go new file mode 100644 index 00000000..e7e2618b --- /dev/null +++ b/mvc/error-handler-custom-result/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + + m := mvc.New(app) + m.Handle(new(controller)) + + app.Listen(":8080") +} + +type errorResponse struct { + Code int + Message string +} + +/* +// Note: if a struct implements the standard go error, so it's an error +// and its Error() is not empty, then its text will be rendered instead, +// override any Dispatch method. +func (e errorResponse) Error() string { + return e.Message +} +*/ + +// implements mvc.Result. +func (e errorResponse) Dispatch(ctx iris.Context) { + // If u want to use mvc.Result on any method without an output return value + // go for it: + // + view := mvc.View{Code: e.Code, Data: e} // use Code and Message as the template data. + switch e.Code { + case iris.StatusNotFound: + view.Name = "404" + default: + view.Name = "500" + } + view.Dispatch(ctx) + + // Otherwise use ctx methods: + // + // ctx.StatusCode(e.Code) + // switch e.Code { + // case iris.StatusNotFound: + // // use Code and Message as the template data. + // if err := ctx.View("404.html", e) + // default: + // if err := ctx.View("500.html", e) + // } +} + +type controller struct{} + +type user struct { + ID uint64 `json:"id"` +} + +func (c *controller) GetBy(userid uint64) mvc.Result { + if userid != 1 { + return errorResponse{ + Code: iris.StatusNotFound, + Message: "User Not Found", + } + } + + return mvc.Response{ + Object: user{ID: userid}, + } +} diff --git a/mvc/error-handler-custom-result/views/404.html b/mvc/error-handler-custom-result/views/404.html new file mode 100644 index 00000000..39b8326d --- /dev/null +++ b/mvc/error-handler-custom-result/views/404.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Client Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler-custom-result/views/500.html b/mvc/error-handler-custom-result/views/500.html new file mode 100644 index 00000000..38b44ab3 --- /dev/null +++ b/mvc/error-handler-custom-result/views/500.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Server Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler-hijack/main.go b/mvc/error-handler-hijack/main.go new file mode 100644 index 00000000..f471e371 --- /dev/null +++ b/mvc/error-handler-hijack/main.go @@ -0,0 +1,60 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + + // Hijack each output value of a method (can be used per-party too). + app.ConfigureContainer(). + UseResultHandler(func(next iris.ResultHandler) iris.ResultHandler { + return func(ctx iris.Context, v interface{}) error { + switch val := v.(type) { + case errorResponse: + return next(ctx, errorView(val)) + default: + return next(ctx, v) + } + } + }) + + m := mvc.New(app) + m.Handle(new(controller)) + + app.Listen(":8080") +} + +func errorView(e errorResponse) mvc.Result { + switch e.Code { + case iris.StatusNotFound: + return mvc.View{Code: e.Code, Name: "404.html", Data: e} + default: + return mvc.View{Code: e.Code, Name: "500.html", Data: e} + } +} + +type errorResponse struct { + Code int + Message string +} + +type controller struct{} + +type user struct { + ID uint64 `json:"id"` +} + +func (c *controller) GetBy(userid uint64) interface{} { + if userid != 1 { + return errorResponse{ + Code: iris.StatusNotFound, + Message: "User Not Found", + } + } + + return user{ID: userid} +} diff --git a/mvc/error-handler-hijack/views/404.html b/mvc/error-handler-hijack/views/404.html new file mode 100644 index 00000000..39b8326d --- /dev/null +++ b/mvc/error-handler-hijack/views/404.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Client Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler-hijack/views/500.html b/mvc/error-handler-hijack/views/500.html new file mode 100644 index 00000000..38b44ab3 --- /dev/null +++ b/mvc/error-handler-hijack/views/500.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Server Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler-http/main.go b/mvc/error-handler-http/main.go new file mode 100644 index 00000000..f37a19fc --- /dev/null +++ b/mvc/error-handler-http/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + + m := mvc.New(app) + m.Handle(new(controller)) + + return app +} + +type controller struct{} + +func (c *controller) Get() string { + return "Hello!" +} + +func (c *controller) GetError() mvc.Result { + return mvc.View{ + // Map to mvc.Code and mvc.Err respectfully on HandleHTTPError method. + Code: iris.StatusBadRequest, + Err: fmt.Errorf("custom error"), + } +} + +// The input parameter of mvc.Code is optional but a good practise to follow. +// You could register a Context and get its error code through ctx.GetStatusCode(). +// +// This can accept dependencies and output values like any other Controller Method, +// however be careful if your registered dependencies depend only on successful(200...) requests. +// +// Also note that, if you register more than one controller.HandleHTTPError +// in the same Party, you need to use the RouteOverlap feature as shown +// in the "authenticated-controller" example, and a dependency on +// a controller's field (or method's input argument) is required +// to select which, between those two controllers, is responsible +// to handle http errors. +func (c *controller) HandleHTTPError(statusCode mvc.Code, err mvc.Err) mvc.View { + if err != nil { + // Do something with that error, + // e.g. view.Data = MyPageData{Message: err.Error()} + } + + code := int(statusCode) // cast it to int. + + view := mvc.View{ + Code: code, + Name: "unexpected-error.html", + } + + switch code { + case 404: + view.Name = "404.html" + // [...] + case 500: + view.Name = "500.html" + } + + return view +} diff --git a/mvc/error-handler-http/main_test.go b/mvc/error-handler-http/main_test.go new file mode 100644 index 00000000..f1cd4fe2 --- /dev/null +++ b/mvc/error-handler-http/main_test.go @@ -0,0 +1,20 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestControllerHandleHTTPError(t *testing.T) { + const ( + expectedIndex = "Hello!" + expectedNotFound = "<h3>Not Found Custom Page Rendered through Controller's HandleHTTPError</h3>" + ) + + app := newApp() + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusOK).Body().IsEqual(expectedIndex) + e.GET("/a_notefound").Expect().Status(httptest.StatusNotFound).ContentType("text/html").Body().IsEqual(expectedNotFound) +} diff --git a/mvc/error-handler-http/views/404.html b/mvc/error-handler-http/views/404.html new file mode 100644 index 00000000..6175671a --- /dev/null +++ b/mvc/error-handler-http/views/404.html @@ -0,0 +1 @@ +<h3>Not Found Custom Page Rendered through Controller's HandleHTTPError</h3> \ No newline at end of file diff --git a/mvc/error-handler-http/views/500.html b/mvc/error-handler-http/views/500.html new file mode 100644 index 00000000..4228c29d --- /dev/null +++ b/mvc/error-handler-http/views/500.html @@ -0,0 +1 @@ +<h3>Internal Server Err</h3> \ No newline at end of file diff --git a/mvc/error-handler-http/views/unexpected-error.html b/mvc/error-handler-http/views/unexpected-error.html new file mode 100644 index 00000000..5da6be52 --- /dev/null +++ b/mvc/error-handler-http/views/unexpected-error.html @@ -0,0 +1 @@ +<h1>Unexpected Error</h1> \ No newline at end of file diff --git a/mvc/error-handler-preflight/main.go b/mvc/error-handler-preflight/main.go new file mode 100644 index 00000000..71359c7b --- /dev/null +++ b/mvc/error-handler-preflight/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "fmt" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + + m := mvc.New(app) + m.Handle(new(controller)) + + app.Listen(":8080") +} + +type controller struct{} + +// Generic response type for JSON results. +type response struct { + ID uint64 `json:"id,omitempty"` + Data interface{} `json:"data,omitempty"` // {data: result } on fetch actions. + Code int `json:"code,omitempty"` + Message string `json:"message,omitempty"` + Timestamp int64 `json:"timestamp,omitempty"` +} + +func (r *response) Preflight(ctx iris.Context) error { + if r.ID > 0 { + r.Timestamp = time.Now().Unix() + } + + if code := r.Code; code > 0 { + // You can call ctx.View or mvc.View{...}.Dispatch + // to render HTML on Code != 200 + // but in order to not proceed with the response resulting + // as JSON you MUST return the iris.ErrStopExecution error. + // Example: + if code != 200 { + mvc.View{ + /* calls the ctx.StatusCode */ + Code: code, + /* use any r.Data as the template data + OR the whole "response" as its data. */ + Data: r, + /* automatically pick the template per error (just for the sake of the example) */ + Name: fmt.Sprintf("%d", code), + }.Dispatch(ctx) + + return iris.ErrStopExecution + } + + ctx.StatusCode(r.Code) + } + + return nil +} + +type user struct { + ID uint64 `json:"id"` +} + +func (c *controller) GetBy(userid uint64) *response { + if userid != 1 { + return &response{ + Code: iris.StatusNotFound, + Message: "User Not Found", + } + } + + return &response{ + ID: userid, + Data: user{ID: userid}, + } +} + +/* + +You can use that `response` structure on non-mvc applications too, using handlers: + +c := app.ConfigureContainer() +c.Get("/{id:uint64}", getUserByID) +func getUserByID(id uint64) response { + if userid != 1 { + return response{ + Code: iris.StatusNotFound, + Message: "User Not Found", + } + } + + return response{ + ID: userid, + Data: user{ID: userid}, + } +} + +*/ diff --git a/mvc/error-handler-preflight/views/404.html b/mvc/error-handler-preflight/views/404.html new file mode 100644 index 00000000..39b8326d --- /dev/null +++ b/mvc/error-handler-preflight/views/404.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Client Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler-preflight/views/500.html b/mvc/error-handler-preflight/views/500.html new file mode 100644 index 00000000..38b44ab3 --- /dev/null +++ b/mvc/error-handler-preflight/views/500.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Server Error Page</title> +</head> +<body> + <h2>{{.Code}}</h2> + <h3>{{.Message}}</h3> +</body> +</html> \ No newline at end of file diff --git a/mvc/error-handler/main.go b/mvc/error-handler/main.go new file mode 100644 index 00000000..f22015d9 --- /dev/null +++ b/mvc/error-handler/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + mvcApp := mvc.New(app) + // To all controllers, it can optionally be overridden per-controller + // if the controller contains the `HandleError(ctx iris.Context, err error)` function. + // + mvcApp.HandleError(func(ctx iris.Context, err error) { + ctx.HTML(fmt.Sprintf("<b>%s</b>", err.Error())) + }) + // + mvcApp.Handle(new(myController)) + + // http://localhost:8080 + app.Listen(":8080") +} + +type myController struct { +} + +// overriddes the mvcApp.HandleError function. +func (c *myController) HandleError(ctx iris.Context, err error) { + ctx.HTML(fmt.Sprintf("<i>%s</i>", err.Error())) +} + +func (c *myController) Get() error { + return fmt.Errorf("error here") +} diff --git a/mvc/grpc-compatible-bidirectional-stream/client/main.go b/mvc/grpc-compatible-bidirectional-stream/client/main.go new file mode 100644 index 00000000..9df86d65 --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/client/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "context" + "time" + + pb "grpcexample/helloworld" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +func main() { + // Set up a connection to the server. + cred, err := credentials.NewClientTLSFromFile("../server.crt", "localhost") + if err != nil { + panic(err) + } + + conn, err := grpc.Dial("localhost:443", grpc.WithTransportCredentials(cred), grpc.WithBlock()) + defer conn.Close() + + client := pb.NewGreeterBidirectionalStreamClient(conn) + stream, err := client.SayHello(context.Background()) + if err != nil { + panic(err) + } + + waitCh := make(chan struct{}) + + // Implement the send channel. + // As an exercise you can implement the read channel one (reading from server, see the server/main.go). + go func() { + for { + println("Sleeping for 2 seconds...") + time.Sleep(2 * time.Second) + println("Sending a <test> msg...") + msg := &pb.HelloRequest{Name: "test"} + + err = stream.Send(msg) + if err != nil { + panic("stream.Send: " + err.Error()) + } + } + }() + + <-waitCh + stream.CloseSend() +} diff --git a/mvc/grpc-compatible-bidirectional-stream/go.mod b/mvc/grpc-compatible-bidirectional-stream/go.mod new file mode 100644 index 00000000..f6ad3d7e --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/go.mod @@ -0,0 +1,66 @@ +module grpcexample + +go 1.22 + +require ( + github.com/golang/protobuf v1.5.4 + github.com/kataras/iris/v12 v12.2.11 + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.33.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/mvc/grpc-compatible-bidirectional-stream/go.sum b/mvc/grpc-compatible-bidirectional-stream/go.sum new file mode 100644 index 00000000..b6f3bf32 --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/go.sum @@ -0,0 +1,206 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/mvc/grpc-compatible-bidirectional-stream/helloworld.proto b/mvc/grpc-compatible-bidirectional-stream/helloworld.proto new file mode 100644 index 00000000..b61240f9 --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/helloworld.proto @@ -0,0 +1,39 @@ +syntax = "proto3"; + +package helloworld; + +option go_package = ".;helloworld"; + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The greeting service definition. (Server-side streaming RPC) +service GreeterServerSideSStream { + // Sends a greeting + rpc SayHello (HelloRequest) returns (stream HelloReply) {} +} + +// The greeting service definition. (Client-side streaming RPC) +service GreeterClientSideStream { + // Sends a greeting + rpc SayHello (stream HelloRequest) returns (HelloReply) {} +} + +// The greeting service definition. (Bidirectional streaming RPC) +service GreeterBidirectionalStream { + // Sends a greeting + rpc SayHello (stream HelloRequest) returns (stream HelloReply) {} +} diff --git a/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld.pb.go b/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld.pb.go new file mode 100644 index 00000000..2c84aaeb --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld.pb.go @@ -0,0 +1,242 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.12.3 +// source: helloworld.proto + +package helloworld + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x22, 0x22, + 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x49, 0x0a, 0x07, 0x47, 0x72, + 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, + 0x6f, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, + 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x32, 0x5c, 0x0a, 0x18, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x69, 0x64, 0x65, 0x53, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x12, 0x40, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x18, 0x2e, + 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, + 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x00, 0x30, 0x01, 0x32, 0x5b, 0x0a, 0x17, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x53, 0x69, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x40, + 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, + 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, + 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, + 0x32, 0x60, 0x0a, 0x1a, 0x47, 0x72, 0x65, 0x65, 0x74, 0x65, 0x72, 0x42, 0x69, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x42, + 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, + 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, + 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, + 0x30, 0x01, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x3b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, + 0x6c, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: helloworld.HelloRequest + (*HelloReply)(nil), // 1: helloworld.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: helloworld.Greeter.SayHello:input_type -> helloworld.HelloRequest + 0, // 1: helloworld.GreeterServerSideSStream.SayHello:input_type -> helloworld.HelloRequest + 0, // 2: helloworld.GreeterClientSideStream.SayHello:input_type -> helloworld.HelloRequest + 0, // 3: helloworld.GreeterBidirectionalStream.SayHello:input_type -> helloworld.HelloRequest + 1, // 4: helloworld.Greeter.SayHello:output_type -> helloworld.HelloReply + 1, // 5: helloworld.GreeterServerSideSStream.SayHello:output_type -> helloworld.HelloReply + 1, // 6: helloworld.GreeterClientSideStream.SayHello:output_type -> helloworld.HelloReply + 1, // 7: helloworld.GreeterBidirectionalStream.SayHello:output_type -> helloworld.HelloReply + 4, // [4:8] is the sub-list for method output_type + 0, // [0:4] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 4, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld_grpc.pb.go b/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld_grpc.pb.go new file mode 100644 index 00000000..1d9a7a2a --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/helloworld/helloworld_grpc.pb.go @@ -0,0 +1,450 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package helloworld + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion7 + +// GreeterClient is the client API for Greeter service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&_Greeter_serviceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/helloworld.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Greeter_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} + +// GreeterServerSideSStreamClient is the client API for GreeterServerSideSStream service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GreeterServerSideSStreamClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (GreeterServerSideSStream_SayHelloClient, error) +} + +type greeterServerSideSStreamClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterServerSideSStreamClient(cc grpc.ClientConnInterface) GreeterServerSideSStreamClient { + return &greeterServerSideSStreamClient{cc} +} + +func (c *greeterServerSideSStreamClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (GreeterServerSideSStream_SayHelloClient, error) { + stream, err := c.cc.NewStream(ctx, &_GreeterServerSideSStream_serviceDesc.Streams[0], "/helloworld.GreeterServerSideSStream/SayHello", opts...) + if err != nil { + return nil, err + } + x := &greeterServerSideSStreamSayHelloClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GreeterServerSideSStream_SayHelloClient interface { + Recv() (*HelloReply, error) + grpc.ClientStream +} + +type greeterServerSideSStreamSayHelloClient struct { + grpc.ClientStream +} + +func (x *greeterServerSideSStreamSayHelloClient) Recv() (*HelloReply, error) { + m := new(HelloReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GreeterServerSideSStreamServer is the server API for GreeterServerSideSStream service. +// All implementations must embed UnimplementedGreeterServerSideSStreamServer +// for forward compatibility +type GreeterServerSideSStreamServer interface { + // Sends a greeting + SayHello(*HelloRequest, GreeterServerSideSStream_SayHelloServer) error + mustEmbedUnimplementedGreeterServerSideSStreamServer() +} + +// UnimplementedGreeterServerSideSStreamServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServerSideSStreamServer struct { +} + +func (UnimplementedGreeterServerSideSStreamServer) SayHello(*HelloRequest, GreeterServerSideSStream_SayHelloServer) error { + return status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServerSideSStreamServer) mustEmbedUnimplementedGreeterServerSideSStreamServer() { +} + +// UnsafeGreeterServerSideSStreamServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServerSideSStreamServer will +// result in compilation errors. +type UnsafeGreeterServerSideSStreamServer interface { + mustEmbedUnimplementedGreeterServerSideSStreamServer() +} + +func RegisterGreeterServerSideSStreamServer(s grpc.ServiceRegistrar, srv GreeterServerSideSStreamServer) { + s.RegisterService(&_GreeterServerSideSStream_serviceDesc, srv) +} + +func _GreeterServerSideSStream_SayHello_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(HelloRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GreeterServerSideSStreamServer).SayHello(m, &greeterServerSideSStreamSayHelloServer{stream}) +} + +type GreeterServerSideSStream_SayHelloServer interface { + Send(*HelloReply) error + grpc.ServerStream +} + +type greeterServerSideSStreamSayHelloServer struct { + grpc.ServerStream +} + +func (x *greeterServerSideSStreamSayHelloServer) Send(m *HelloReply) error { + return x.ServerStream.SendMsg(m) +} + +var _GreeterServerSideSStream_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.GreeterServerSideSStream", + HandlerType: (*GreeterServerSideSStreamServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "SayHello", + Handler: _GreeterServerSideSStream_SayHello_Handler, + ServerStreams: true, + }, + }, + Metadata: "helloworld.proto", +} + +// GreeterClientSideStreamClient is the client API for GreeterClientSideStream service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GreeterClientSideStreamClient interface { + // Sends a greeting + SayHello(ctx context.Context, opts ...grpc.CallOption) (GreeterClientSideStream_SayHelloClient, error) +} + +type greeterClientSideStreamClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClientSideStreamClient(cc grpc.ClientConnInterface) GreeterClientSideStreamClient { + return &greeterClientSideStreamClient{cc} +} + +func (c *greeterClientSideStreamClient) SayHello(ctx context.Context, opts ...grpc.CallOption) (GreeterClientSideStream_SayHelloClient, error) { + stream, err := c.cc.NewStream(ctx, &_GreeterClientSideStream_serviceDesc.Streams[0], "/helloworld.GreeterClientSideStream/SayHello", opts...) + if err != nil { + return nil, err + } + x := &greeterClientSideStreamSayHelloClient{stream} + return x, nil +} + +type GreeterClientSideStream_SayHelloClient interface { + Send(*HelloRequest) error + CloseAndRecv() (*HelloReply, error) + grpc.ClientStream +} + +type greeterClientSideStreamSayHelloClient struct { + grpc.ClientStream +} + +func (x *greeterClientSideStreamSayHelloClient) Send(m *HelloRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *greeterClientSideStreamSayHelloClient) CloseAndRecv() (*HelloReply, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(HelloReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GreeterClientSideStreamServer is the server API for GreeterClientSideStream service. +// All implementations must embed UnimplementedGreeterClientSideStreamServer +// for forward compatibility +type GreeterClientSideStreamServer interface { + // Sends a greeting + SayHello(GreeterClientSideStream_SayHelloServer) error + mustEmbedUnimplementedGreeterClientSideStreamServer() +} + +// UnimplementedGreeterClientSideStreamServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterClientSideStreamServer struct { +} + +func (UnimplementedGreeterClientSideStreamServer) SayHello(GreeterClientSideStream_SayHelloServer) error { + return status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterClientSideStreamServer) mustEmbedUnimplementedGreeterClientSideStreamServer() { +} + +// UnsafeGreeterClientSideStreamServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterClientSideStreamServer will +// result in compilation errors. +type UnsafeGreeterClientSideStreamServer interface { + mustEmbedUnimplementedGreeterClientSideStreamServer() +} + +func RegisterGreeterClientSideStreamServer(s grpc.ServiceRegistrar, srv GreeterClientSideStreamServer) { + s.RegisterService(&_GreeterClientSideStream_serviceDesc, srv) +} + +func _GreeterClientSideStream_SayHello_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GreeterClientSideStreamServer).SayHello(&greeterClientSideStreamSayHelloServer{stream}) +} + +type GreeterClientSideStream_SayHelloServer interface { + SendAndClose(*HelloReply) error + Recv() (*HelloRequest, error) + grpc.ServerStream +} + +type greeterClientSideStreamSayHelloServer struct { + grpc.ServerStream +} + +func (x *greeterClientSideStreamSayHelloServer) SendAndClose(m *HelloReply) error { + return x.ServerStream.SendMsg(m) +} + +func (x *greeterClientSideStreamSayHelloServer) Recv() (*HelloRequest, error) { + m := new(HelloRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _GreeterClientSideStream_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.GreeterClientSideStream", + HandlerType: (*GreeterClientSideStreamServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "SayHello", + Handler: _GreeterClientSideStream_SayHello_Handler, + ClientStreams: true, + }, + }, + Metadata: "helloworld.proto", +} + +// GreeterBidirectionalStreamClient is the client API for GreeterBidirectionalStream service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GreeterBidirectionalStreamClient interface { + // Sends a greeting + SayHello(ctx context.Context, opts ...grpc.CallOption) (GreeterBidirectionalStream_SayHelloClient, error) +} + +type greeterBidirectionalStreamClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterBidirectionalStreamClient(cc grpc.ClientConnInterface) GreeterBidirectionalStreamClient { + return &greeterBidirectionalStreamClient{cc} +} + +func (c *greeterBidirectionalStreamClient) SayHello(ctx context.Context, opts ...grpc.CallOption) (GreeterBidirectionalStream_SayHelloClient, error) { + stream, err := c.cc.NewStream(ctx, &_GreeterBidirectionalStream_serviceDesc.Streams[0], "/helloworld.GreeterBidirectionalStream/SayHello", opts...) + if err != nil { + return nil, err + } + x := &greeterBidirectionalStreamSayHelloClient{stream} + return x, nil +} + +type GreeterBidirectionalStream_SayHelloClient interface { + Send(*HelloRequest) error + Recv() (*HelloReply, error) + grpc.ClientStream +} + +type greeterBidirectionalStreamSayHelloClient struct { + grpc.ClientStream +} + +func (x *greeterBidirectionalStreamSayHelloClient) Send(m *HelloRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *greeterBidirectionalStreamSayHelloClient) Recv() (*HelloReply, error) { + m := new(HelloReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GreeterBidirectionalStreamServer is the server API for GreeterBidirectionalStream service. +// All implementations must embed UnimplementedGreeterBidirectionalStreamServer +// for forward compatibility +type GreeterBidirectionalStreamServer interface { + // Sends a greeting + SayHello(GreeterBidirectionalStream_SayHelloServer) error + mustEmbedUnimplementedGreeterBidirectionalStreamServer() +} + +// UnimplementedGreeterBidirectionalStreamServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterBidirectionalStreamServer struct { +} + +func (UnimplementedGreeterBidirectionalStreamServer) SayHello(GreeterBidirectionalStream_SayHelloServer) error { + return status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterBidirectionalStreamServer) mustEmbedUnimplementedGreeterBidirectionalStreamServer() { +} + +// UnsafeGreeterBidirectionalStreamServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterBidirectionalStreamServer will +// result in compilation errors. +type UnsafeGreeterBidirectionalStreamServer interface { + mustEmbedUnimplementedGreeterBidirectionalStreamServer() +} + +func RegisterGreeterBidirectionalStreamServer(s grpc.ServiceRegistrar, srv GreeterBidirectionalStreamServer) { + s.RegisterService(&_GreeterBidirectionalStream_serviceDesc, srv) +} + +func _GreeterBidirectionalStream_SayHello_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GreeterBidirectionalStreamServer).SayHello(&greeterBidirectionalStreamSayHelloServer{stream}) +} + +type GreeterBidirectionalStream_SayHelloServer interface { + Send(*HelloReply) error + Recv() (*HelloRequest, error) + grpc.ServerStream +} + +type greeterBidirectionalStreamSayHelloServer struct { + grpc.ServerStream +} + +func (x *greeterBidirectionalStreamSayHelloServer) Send(m *HelloReply) error { + return x.ServerStream.SendMsg(m) +} + +func (x *greeterBidirectionalStreamSayHelloServer) Recv() (*HelloRequest, error) { + m := new(HelloRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _GreeterBidirectionalStream_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.GreeterBidirectionalStream", + HandlerType: (*GreeterBidirectionalStreamServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "SayHello", + Handler: _GreeterBidirectionalStream_SayHello_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "helloworld.proto", +} diff --git a/mvc/grpc-compatible-bidirectional-stream/server.crt b/mvc/grpc-compatible-bidirectional-stream/server.crt new file mode 100644 index 00000000..ad21f14b --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/server.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICwzCCAaugAwIBAgIJANAsSlhuqzW/MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV +BAMTCWxvY2FsaG9zdDAeFw0yMDEwMzEwMjM4MTNaFw0zMDEwMjkwMjM4MTNaMBQx +EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKY8mFh0nvXa8V6Vx5TVVbfq9Zx81hiIKeXN977JaQGrPfCMRU61smaDJAzR +MBEFjHT37Zj5sZr6qvQmt3Dfst8bNcFBsZ7s3bBknuevD3gPJBy1r5KFwSkPZekH +T+0DF0Drq1/iIZQXE13udWzDnzxABUBOmIzEmn+rfp2j3xJJGLoO1O4Wu2YpXhtj +yNJfswoztGGie6u61mAN7Rw4JQUkDKa3hAKkYtfOoGHZBs6Y0RIKZQikjxlVpMMc +fCvUMHkY51GP8ycgZ8+0n/cjm13KkqfvoyRZ1rQqCd24YNIEl18t0FClpUAHkxD/ +aUPCqV3bqpFBbDPQcYybIGjfNIMCAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo +b3N0MA0GCSqGSIb3DQEBBQUAA4IBAQAd6F6tG/jcUu9pm/5XeH1Iof5PB9tFuBvv +w9HFjBI5S7ItnTepneoOP26lx2iOE0GwkvrhseZcHkGDZPdncBn12PuCHUbcO2Ux +bEDyDMsAHooKLvmAfAWeiOmeJAdFl8DOTgD/lTHK1n/mEwCUOtGozmfm/Y0pnfc7 +nMgbQ+yNsj1X7HVJHRUdOfOCGjiWofo6v7V7YyZJC2jpn3K7O4126jic2ibWYKQl +fLLjgS0N5Wcun117e1mRYV41jtPOkeAvxJbJGf0IP7Os0VfG1UQhodwjkV4s8GcG +naB5qC4Y508cB7Lq58kbGgZ0nfMCcpnrKobliIZVEpH7aa0Po1lm +-----END CERTIFICATE----- diff --git a/mvc/grpc-compatible-bidirectional-stream/server.key b/mvc/grpc-compatible-bidirectional-stream/server.key new file mode 100644 index 00000000..5b7681d7 --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEApjyYWHSe9drxXpXHlNVVt+r1nHzWGIgp5c33vslpAas98IxF +TrWyZoMkDNEwEQWMdPftmPmxmvqq9Ca3cN+y3xs1wUGxnuzdsGSe568PeA8kHLWv +koXBKQ9l6QdP7QMXQOurX+IhlBcTXe51bMOfPEAFQE6YjMSaf6t+naPfEkkYug7U +7ha7ZileG2PI0l+zCjO0YaJ7q7rWYA3tHDglBSQMpreEAqRi186gYdkGzpjREgpl +CKSPGVWkwxx8K9QweRjnUY/zJyBnz7Sf9yObXcqSp++jJFnWtCoJ3bhg0gSXXy3Q +UKWlQAeTEP9pQ8KpXduqkUFsM9BxjJsgaN80gwIDAQABAoIBACDVNwHBhuPoKmQU +ESdEO3nn3jraLS8LNbs9wwDbpvG9cK5iBg5VtLaqkCQ37NZv0h4IGdVs+7cwazNt +si2JATsvlJ5m6z4IaoC8XuZDnTqJQwiomdTGti/16prr5s1ZHu6jnWWCtD8bj6et +wWOJ/5lWy7K300l6S0mMBaX9B8IEfGR+YPGF/bfsIlf+9iuVulBjH5NPIozwl4c9 +VUafESEZX0DM/KDHqFvvWdMaw9e+3QNi+l0t3VJz6JuEcUfRztT6lbzYbRGBYqKr +DmUNxYUThd717NJklxr9D+GMm5FnfrzY8vcJ16SILBQyDthsz1s6gdT0yeRFgjJf +afDObAECgYEA1WQdayAeqT7sE0T0jHAWHdVhRd9sGUTZ4LjVuGbMjbJWJVUPn/fz +ahBQh77xutmNCbDSUD0srT+zHtRRJUVhl+ojFS1CMyyL/UAfH24gDwUnXIyq/DPA +heXKD8NwGoTPbHKjdmy+89qVbes3oxBc5tDKpzAuBoPY4iBMVwfqSmECgYEAx24Y +i1lhxuG+g2YSjiIhmD/ytZSXamP3+KmnqWWXbEjJd2oYmCPr9yBCfdk9jCUXZJsg +tYsRduMajTjmTNkYmGyZNVtmjXfrq/vaJgf7bZhhLOFxWoNmLlKQfmbuJW5fkV1b +hY8oid+YbBob4xseFzKvm5j0aKwufi3v7XLUEWMCgYEAs7rqKFNaX9SWhDhc/Xhe +uGwDzRU8eCAMnwEvSWyUN3iQpEr7qRHvXFM3cM47zdP0vcfHrDuKSLXRSVMssYa5 +h3l2aRzAmFeZ5Qk/7XoU2HHP0FzOmzN/oYeE5DgJUNyx1DbORS2cu8lMeNNX/ikH +BoWvWpfy/BvK7dKkWd1Z0aECgYEAm1+QKcjqX5ty5UZ6AFhhGhAAVS2+Rfo6sHXl +FRn8PjX7GFkFbkrWRUPR6eB9jhk7v3sIocgGRDytbAc/jfG5ss8xEhvyqxcZ+nUO +QYEIhxsn4mKGAMHMsxxKTOB+e5UhScyVSFn/eGNGijpRLb/r0qD/pdcl3AMBefbq +LXG//QcCgYBrYTCaKYDg/TSMt6fTSZgJRaui8PvvlLjZy63vrVCexVUibiCpbUt9 +sHe9gbSDPr/uCyNgKnZjDbVabmZboVYqHBDQnXPUYYx9dBSL2DzE3JXA6Q8RVnOY +zwCPzVxYbE9h02ishAgc6k9w61XUaDnASmBZAnlxt9/8cB7+IZAlfg== +-----END RSA PRIVATE KEY----- diff --git a/mvc/grpc-compatible-bidirectional-stream/server/main.go b/mvc/grpc-compatible-bidirectional-stream/server/main.go new file mode 100644 index 00000000..fc484b90 --- /dev/null +++ b/mvc/grpc-compatible-bidirectional-stream/server/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "io" + + pb "grpcexample/helloworld" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + + "google.golang.org/grpc" +) + +type Greeter struct { + pb.UnimplementedGreeterBidirectionalStreamServer +} + +// SayHello implements the proto Bidirectional Stream Greeter service. +func (g *Greeter) SayHello(stream pb.GreeterBidirectionalStream_SayHelloServer) error { + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + println("Received input: " + in.Name) + // On client side you can implement the 'read' operation too. + stream.Send(&pb.HelloReply{Message: "Hello " + in.Name}) + } +} + +func main() { + app := iris.New() + + grpcServer := grpc.NewServer() + + myService := &Greeter{} + pb.RegisterGreeterBidirectionalStreamServer(grpcServer, myService) + + rootApp := mvc.New(app) + rootApp.Handle(myService, mvc.GRPC{ + Server: grpcServer, // Required. + ServiceName: "helloworld.GreeterBidirectionalStream", // Required. + Strict: true, // Set it to true on gRPC streaming. + }) + + app.Run(iris.TLS(":443", "../server.crt", "../server.key")) +} diff --git a/mvc/grpc-compatible/README.md b/mvc/grpc-compatible/README.md new file mode 100644 index 00000000..94a84d4e --- /dev/null +++ b/mvc/grpc-compatible/README.md @@ -0,0 +1,20 @@ +# gRPC Iris Example + +## Generate TLS Keys + +```sh +$ openssl genrsa -out server.key 2048 +$ openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 +``` + +## Install the protoc Go plugin + +```sh +$ go get -u github.com/golang/protobuf/protoc-gen-go +``` + +## Generate proto + +```sh +$ protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld +``` diff --git a/mvc/grpc-compatible/grpc-client/main.go b/mvc/grpc-compatible/grpc-client/main.go new file mode 100644 index 00000000..e7925708 --- /dev/null +++ b/mvc/grpc-compatible/grpc-client/main.go @@ -0,0 +1,52 @@ +// Package main implements a client for Greeter service. +package main + +import ( + "context" + "crypto/tls" + "log" + "os" + "time" + + pb "github.com/kataras/iris/v12/_examples/mvc/grpc-compatible/helloworld" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +const ( + address = "localhost:443" + defaultName = "world" +) + +func main() { + // Set up a connection to the server. + // cred, err := credentials.NewClientTLSFromFile("../server.crt", "localhost") + // if err != nil { + // log.Fatal(err) + // } + cred := credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + Renegotiation: tls.RenegotiateNever, + }) + + conn, err := grpc.Dial(address, grpc.WithTransportCredentials(cred), grpc.WithBlock()) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + c := pb.NewGreeterClient(conn) + + // Contact the server and print out its response. + name := defaultName + if len(os.Args) > 1 { + name = os.Args[1] + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name}) + if err != nil { + log.Fatalf("could not greet: %v", err) + } + log.Printf("Greeting: %s", r.GetMessage()) +} diff --git a/mvc/grpc-compatible/helloworld/README.md b/mvc/grpc-compatible/helloworld/README.md new file mode 100644 index 00000000..61b3729c --- /dev/null +++ b/mvc/grpc-compatible/helloworld/README.md @@ -0,0 +1,3 @@ +# Helloworld gRPC Example + +https://github.com/grpc/grpc-go/tree/master/examples/helloworld \ No newline at end of file diff --git a/mvc/grpc-compatible/helloworld/helloworld.pb.go b/mvc/grpc-compatible/helloworld/helloworld.pb.go new file mode 100644 index 00000000..6be07b7c --- /dev/null +++ b/mvc/grpc-compatible/helloworld/helloworld.pb.go @@ -0,0 +1,315 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.21.0 +// protoc v3.11.1 +// source: helloworld.proto + +package helloworld + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x0a, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x22, 0x22, + 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x49, 0x0a, 0x07, 0x47, 0x72, + 0x65, 0x65, 0x74, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, + 0x6f, 0x12, 0x18, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x68, 0x65, + 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x30, 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, + 0x6f, 0x72, 0x6c, 0x64, 0x42, 0x0f, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: helloworld.HelloRequest + (*HelloReply)(nil), // 1: helloworld.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: helloworld.Greeter.SayHello:input_type -> helloworld.HelloRequest + 1, // 1: helloworld.Greeter.SayHello:output_type -> helloworld.HelloReply + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// GreeterClient is the client API for Greeter service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) +} + +// UnimplementedGreeterServer can be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (*UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} + +func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) { + s.RegisterService(&_Greeter_serviceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/helloworld.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Greeter_serviceDesc = grpc.ServiceDesc{ + ServiceName: "helloworld.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/mvc/grpc-compatible/helloworld/helloworld.proto b/mvc/grpc-compatible/helloworld/helloworld.proto new file mode 100644 index 00000000..abb62783 --- /dev/null +++ b/mvc/grpc-compatible/helloworld/helloworld.proto @@ -0,0 +1,33 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +syntax = "proto3"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/mvc/grpc-compatible/http-client/main.go b/mvc/grpc-compatible/http-client/main.go new file mode 100644 index 00000000..4766f1fb --- /dev/null +++ b/mvc/grpc-compatible/http-client/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "encoding/json" + "log" + "net/http" + "os" + + pb "github.com/kataras/iris/v12/_examples/mvc/grpc-compatible/helloworld" +) + +func main() { + b, err := os.ReadFile("../server.crt") + if err != nil { + log.Fatal(err) + } + cp := x509.NewCertPool() + if !cp.AppendCertsFromPEM(b) { + log.Fatal("credentials: failed to append certificates") + } + + transport := &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: cp, + }, + } + + client := http.Client{Transport: transport} + buf := new(bytes.Buffer) + err = json.NewEncoder(buf).Encode(pb.HelloRequest{Name: "world"}) + if err != nil { + log.Fatal(err) + } + + resp, err := client.Post("https://localhost/helloworld.Greeter/SayHello", "application/json", buf) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + + var reply pb.HelloReply + err = json.NewDecoder(resp.Body).Decode(&reply) + if err != nil { + log.Fatal(err) + } + log.Printf("Greeting: %s", reply.GetMessage()) +} diff --git a/mvc/grpc-compatible/main.go b/mvc/grpc-compatible/main.go new file mode 100644 index 00000000..3ef16174 --- /dev/null +++ b/mvc/grpc-compatible/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "context" + "log" + + pb "github.com/kataras/iris/v12/_examples/mvc/grpc-compatible/helloworld" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + + "google.golang.org/grpc" +) + +// See https://github.com/kataras/iris/issues/1449 +// Iris automatically binds the standard "context" context.Context to `iris.Context.Request().Context()` +// and any other structure that is not mapping to a registered dependency +// as a payload depends on the request, e.g XML, YAML, Query, Form, JSON. +// +// Useful to use gRPC services as Iris controllers fast and without wrappers. + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + + // The Iris server should ran under TLS (it's a gRPC requirement). + // POST: https://localhost:443/helloworld.Greeter/SayHello + // with request data: {"name": "John"} + // and expected output: {"message": "Hello John"} + app.Run(iris.TLS(":443", "server.crt", "server.key")) +} + +func newApp() *iris.Application { + app := iris.New() + // app.Configure(iris.WithLowercaseRouting) // OPTIONAL. + + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<h1>Index Page</h1>") + }) + + ctrl := &myController{} + // Register gRPC server. + grpcServer := grpc.NewServer() + pb.RegisterGreeterServer(grpcServer, ctrl) + + // serviceName := pb.File_helloworld_proto.Services().Get(0).FullName() + + // Register MVC application controller for gRPC services. + // You can bind as many mvc gRpc services in the same Party or app, + // as the ServiceName differs. + mvc.New(app). + Register(new(myService)). + Handle(ctrl, mvc.GRPC{ + Server: grpcServer, // Required. + ServiceName: "helloworld.Greeter", // Required. + Strict: false, + }) + + return app +} + +type service interface { + DoSomething() error +} + +type myService struct{} + +func (s *myService) DoSomething() error { + log.Println("service: DoSomething") + return nil +} + +type myController struct { + // Ctx iris.Context + + SingletonDependency service +} + +// SayHello implements helloworld.GreeterServer. +// See https://github.com/kataras/iris/issues/1449#issuecomment-625570442 +// for the comments below (https://github.com/iris-contrib/swagger). +// +// @Description greet service +// @Accept json +// @Produce json +// @Success 200 {string} string "Hello {name}" +// @Router /helloworld.Greeter/SayHello [post] +func (c *myController) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { + err := c.SingletonDependency.DoSomething() + if err != nil { + return nil, err + } + + return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/mvc/grpc-compatible/main_test.go b/mvc/grpc-compatible/main_test.go new file mode 100644 index 00000000..e525519b --- /dev/null +++ b/mvc/grpc-compatible/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestGRPCCompatible(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + e.POST("/helloworld.Greeter/SayHello").WithJSON(map[string]string{"name": "makis"}).Expect(). + Status(httptest.StatusOK). + JSON().IsEqual(map[string]string{"message": "Hello makis"}) +} diff --git a/mvc/grpc-compatible/server.crt b/mvc/grpc-compatible/server.crt new file mode 100644 index 00000000..a84671f1 --- /dev/null +++ b/mvc/grpc-compatible/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhICCQDpz77z0oyjCDANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQGEwJH +UjEPMA0GA1UECAwGQXRoZW5zMQ8wDQYDVQQHDAZBdGhlbnMxJjAkBgkqhkiG9w0B +CQEWF2thdGFyYXMyMDA2QGhvdG1haWwuY29tMB4XDTIyMDMwMzExMjczM1oXDTMy +MDIyOTExMjczM1owVzELMAkGA1UEBhMCR1IxDzANBgNVBAgMBkF0aGVuczEPMA0G +A1UEBwwGQXRoZW5zMSYwJAYJKoZIhvcNAQkBFhdrYXRhcmFzMjAwNkBob3RtYWls +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALu4Uqpcf0AnRDwW +QGDh//v2wDNQ2EP/jn2Y4YxYJXtvWZ7dWcoX4fPA03mOAEmEPXWGxkhe8DYFh8PY +0zpZW5sFY7ae0AcpcjvlyxjNvHsqjhnh7M1gKZuhfyxvvLv7afC5Gs64tyg+f4C3 +EqvwKHV+fjC8eKiASs4FsEEi89uv2AZdD9Vp0Zvbz6/1mRQQWBMpsPiIO7/WsaW4 +DPq/zUZVY15WaX5B0Fg57O5Uv8aHyV4A+AQN7XzadCpYBp8XUb/cVcN9Azj2F6d3 +WODyYT7y/RMuuih9HJQMxuAYPNB5UAkW6syTdfjbdyqbXe45z5iKPcotE4KaXYJf +hTkj6osCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAsb3QGQUGNGs8zv2y4QmsDCB9 ++mkzwH9BpqSo40Zs19kT35nH0u//UuXiNG3U8d2WH1J7kk64cdrETuVay5TwW9jJ +EagdJl4zAZbfLQuDUCI+cVpjbywbO//GXzi8Q/aO7viboU0OR+MPbabubtKE7f+X +THIjnMj3OhFM4zzrFyEL8gsRMLzRRCV18wTsiCl9bi4bZ1Ssvr6MwqyXHs3uK+fx +JpxQVb3MckoIgUKwwU4MlXwufDkOmslGFsRg4e1iiwlkJ0HgRdf5lSuDmnBjH4T+ +fWvRqCeHDTjOI09+7IAK1EF7rw4TZjHv+RbPl5+b1TJcanUC9EDg4z4/rR0XOg== +-----END CERTIFICATE----- diff --git a/mvc/grpc-compatible/server.key b/mvc/grpc-compatible/server.key new file mode 100644 index 00000000..48098867 --- /dev/null +++ b/mvc/grpc-compatible/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAu7hSqlx/QCdEPBZAYOH/+/bAM1DYQ/+OfZjhjFgle29Znt1Z +yhfh88DTeY4ASYQ9dYbGSF7wNgWHw9jTOllbmwVjtp7QBylyO+XLGM28eyqOGeHs +zWApm6F/LG+8u/tp8Lkazri3KD5/gLcSq/AodX5+MLx4qIBKzgWwQSLz26/YBl0P +1WnRm9vPr/WZFBBYEymw+Ig7v9axpbgM+r/NRlVjXlZpfkHQWDns7lS/xofJXgD4 +BA3tfNp0KlgGnxdRv9xVw30DOPYXp3dY4PJhPvL9Ey66KH0clAzG4Bg80HlQCRbq +zJN1+Nt3Kptd7jnPmIo9yi0Tgppdgl+FOSPqiwIDAQABAoIBAQCg0XM4cc+uVTV2 +yJVUqqjT4fucusjb0EbxQJUR174ctjMwD2/J25X+bhZ9z3JdiQXh9plODM97aFd8 +J/glx8Hb180p+Xo8eHxd5iqNUEwFtFpSwCNPeu+KXduGZR9qaCPFT78wlDyNJKW0 +zqIXXMI8jiZreDtiF65+O49Y7im97Lqwhw8fEABcr3rpOpjK79nPHkf0X3CKj1TC +IhW5Av4j41uv8+1BgObjVkeYFHK4O+vRWiSId9OiXzZT9ZaG56ntGOap9KuugTym +2ngbIBm2DdUDmbY3vL9eUzhfY75VIjFrgnf/EYN+7kymbymo3vnv5OmB3OByX7iw +bXTmxQgxAoGBAOLLx6EzcQJ83g85Gtd3WNiNW414ynDPyIB/XAEcyygZGYqrVfsH +HfGhxI787WqzjIZxl987HTPOkrX5Xc/GhHNeTVa1+neyUUqx46DxessU3/s53Vg4 +X1AmnmL6+Wl1qrlTJiUQINDyOZkHsbycR8okDlrzSS1rwO90wW6K5snDAoGBANPk +a/NH2t+KrAboPtXZk2DCUMkCoyDhzXnPU4HARO0BRa3Qhul8keV8u54MtNsej1y+ +TcatUQYpuT4Pgpl1kdtyHrLNiEhd0ThBgy5RmS/rLk9XnuWgfeth5bGxbEIlHXMN +HvoxL34UhGxwWFCHKr5vV2OYVcPLkbdDBhLneweZAoGAaL6tCGp1uyxocqdxGipo +wjsnGYO8G7YbaB1qJKljurU88qqHH1T+I2cPHOr7y9f5Au7bsaHfrtmtMJZnGVsa +OR5Ioc+SSk309YaLFv3wNHMDr0feTqxaeO4dIKHBJ0/M9aLNbzivr1DwARlooS+c +iGN2rdLG7U9i4DUQUTmdtXkCgYEAllEJM8DZyJN7jjrbuKFtJ8sxvCeeygjl12/4 +8acQPoIUiEXSL3krlv1xq6Gf+4ImeciXLEZvoEuhGiGuqGb7Xg4LMRUVhSDo91ui +UA2a+p+AbtDd7FB6g60jYXdYMWRbC+9W9m5GHs83UiYwwI/jBs291O2QiiGz8aoe +ePK2GKECgYEAg7PYp1uOWEuA39gqrKmuLA5f/i2bGgBrajk90m+9kgNwZ9RqeZJG +V97hRwO86EwBBqhMUjaFv/zwSjKhCZUE8vOt5DF4sH5Ppa9j/kqrzsZjlKjajj/U +tH1iFSXz/+PwQVeNssfjFMUPwWWsGSN5pvqx/5Ru/DIvPLHOg3YbEQc= +-----END RSA PRIVATE KEY----- diff --git a/mvc/hello-world/main.go b/mvc/hello-world/main.go index 6f2ec963..ba205705 100644 --- a/mvc/hello-world/main.go +++ b/mvc/hello-world/main.go @@ -1,15 +1,16 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "strings" - "github.com/kataras/iris/middleware/logger" - "github.com/kataras/iris/middleware/recover" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/logger" + "github.com/kataras/iris/v12/middleware/recover" + "github.com/kataras/iris/v12/mvc" ) // This example is equivalent to the -// https://github.com/kataras/iris/blob/master/_examples/hello-world/main.go +// https://github.com/kataras/iris/blob/main/_examples/hello-world/main.go // // It seems that additional code you // have to write doesn't worth it @@ -32,7 +33,7 @@ import ( // for the main_test.go. func newApp() *iris.Application { app := iris.New() - // Optionally, add two built'n handlers + // Optionally, add two builtin handlers // that can recover from any http-relative panics // and log the requests to the terminal. app.Use(recover.New()) @@ -40,6 +41,16 @@ func newApp() *iris.Application { // Serve a controller based on the root Router, "/". mvc.New(app).Handle(new(ExampleController)) + // Add custom path func + mvc.New(app).SetCustomPathWordFunc(func(path, w string, wordIndex int) string { + + if wordIndex == 0 { + w = strings.ToLower(w) + } + path += w + return path + + }).Handle(new(ExampleControllerCustomPath)) return app } @@ -50,7 +61,7 @@ func main() { // http://localhost:8080/ping // http://localhost:8080/hello // http://localhost:8080/custom_path - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } // ExampleController serves the "/", "/ping" and "/hello". @@ -80,6 +91,13 @@ func (c *ExampleController) GetHello() interface{} { return map[string]string{"message": "Hello Iris!"} } +// GetHelloWorld serves +// Method: GET +// Resource: http://localhost:8080/hello/world +func (c *ExampleController) GetHelloWorld() interface{} { + return map[string]string{"message": "Hello Iris! DefaultPath"} +} + // BeforeActivation called once, before the controller adapted to the main application // and of course before the server ran. // After version 9 you can also add custom routes for a specific controller's methods. @@ -105,6 +123,15 @@ func (c *ExampleController) CustomHandlerWithoutFollowingTheNamingGuide() string return "hello from the custom handler without following the naming guide" } +type ExampleControllerCustomPath struct{} + +// GetHelloWorld serves +// Method: GET +// Resource: http://localhost:8080/helloWorld +func (c *ExampleControllerCustomPath) GetHelloWorld() interface{} { + return map[string]string{"message": "Hello Iris! CustomPath"} +} + // GetUserBy serves // Method: GET // Resource: http://localhost:8080/user/{username:string} diff --git a/mvc/hello-world/main_test.go b/mvc/hello-world/main_test.go index 5c8e2719..22c1df91 100644 --- a/mvc/hello-world/main_test.go +++ b/mvc/hello-world/main_test.go @@ -3,21 +3,21 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestMVCHelloWorld(t *testing.T) { e := httptest.New(t, newApp()) e.GET("/").Expect().Status(httptest.StatusOK). - ContentType("text/html", "utf-8").Body().Equal("<h1>Welcome</h1>") + ContentType("text/html", "utf-8").Body().IsEqual("<h1>Welcome</h1>") e.GET("/ping").Expect().Status(httptest.StatusOK). - Body().Equal("pong") + Body().IsEqual("pong") e.GET("/hello").Expect().Status(httptest.StatusOK). JSON().Object().Value("message").Equal("Hello Iris!") e.GET("/custom_path").Expect().Status(httptest.StatusOK). - Body().Equal("hello from the custom handler without following the naming guide") + Body().IsEqual("hello from the custom handler without following the naming guide") } diff --git a/structuring/login-mvc-single-responsibility-package/folder_structure.png b/mvc/login-mvc-single-responsibility/folder_structure.png similarity index 100% rename from structuring/login-mvc-single-responsibility-package/folder_structure.png rename to mvc/login-mvc-single-responsibility/folder_structure.png diff --git a/mvc/login-mvc-single-responsibility/main.go b/mvc/login-mvc-single-responsibility/main.go new file mode 100644 index 00000000..c64a120f --- /dev/null +++ b/mvc/login-mvc-single-responsibility/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12/_examples/mvc/login-mvc-single-responsibility/user" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" +) + +func main() { + app := iris.New() + // You got full debug messages, useful when using MVC and you want to make + // sure that your code is aligned with the Iris' MVC Architecture. + app.Logger().SetLevel("debug") + + app.RegisterView(iris.HTML("./views", ".html").Layout("shared/layout.html")) + + app.HandleDir("/public", iris.Dir("./public")) + + userRouter := app.Party("/user") + { + manager := sessions.New(sessions.Config{ + Cookie: "sessioncookiename", + Expires: 24 * time.Hour, + }) + userRouter.Use(manager.Handler()) + mvc.Configure(userRouter, configureUserMVC) + } + + // http://localhost:8080/user/register + // http://localhost:8080/user/login + // http://localhost:8080/user/me + // http://localhost:8080/user/logout + // http://localhost:8080/user/1 + app.Listen(":8080", configure) +} + +func configureUserMVC(userApp *mvc.Application) { + userApp.Register( + user.NewDataSource(), + ) + userApp.Handle(new(user.Controller)) +} + +func configure(app *iris.Application) { + app.Configure( + iris.WithOptimizations, + iris.WithFireMethodNotAllowed, + iris.WithLowercaseRouting, + iris.WithPathIntelligence, + iris.WithTunneling, + ) +} diff --git a/structuring/login-mvc-single-responsibility-package/public/css/site.css b/mvc/login-mvc-single-responsibility/public/css/site.css similarity index 100% rename from structuring/login-mvc-single-responsibility-package/public/css/site.css rename to mvc/login-mvc-single-responsibility/public/css/site.css diff --git a/structuring/login-mvc-single-responsibility-package/user/auth.go b/mvc/login-mvc-single-responsibility/user/auth.go similarity index 96% rename from structuring/login-mvc-single-responsibility-package/user/auth.go rename to mvc/login-mvc-single-responsibility/user/auth.go index 0300f035..64ded5df 100644 --- a/structuring/login-mvc-single-responsibility-package/user/auth.go +++ b/mvc/login-mvc-single-responsibility/user/auth.go @@ -5,9 +5,9 @@ import ( "strconv" "strings" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" ) const sessionIDKey = "UserID" diff --git a/structuring/login-mvc-single-responsibility-package/user/controller.go b/mvc/login-mvc-single-responsibility/user/controller.go similarity index 95% rename from structuring/login-mvc-single-responsibility-package/user/controller.go rename to mvc/login-mvc-single-responsibility/user/controller.go index 38330c7d..b4777e4b 100644 --- a/structuring/login-mvc-single-responsibility-package/user/controller.go +++ b/mvc/login-mvc-single-responsibility/user/controller.go @@ -1,8 +1,8 @@ package user import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) var ( @@ -21,7 +21,7 @@ var ( // GET /user/login // POST /user/login // GET /user/me -// GET /user/{id:long} | long is a new param type, it's the int64. +// GET /user/{id:int64} // All HTTP Methods /user/logout type Controller struct { AuthController @@ -35,7 +35,7 @@ type formValue func(string) string func (c *Controller) BeforeActivation(b mvc.BeforeActivation) { // bind the context's `FormValue` as well in order to be // acceptable on the controller or its methods' input arguments (NEW feature as well). - b.Dependencies().Add(func(ctx iris.Context) formValue { return ctx.FormValue }) + b.Dependencies().Register(func(ctx iris.Context) formValue { return ctx.FormValue }) } type page struct { @@ -162,7 +162,7 @@ func (u Model) Dispatch(ctx iris.Context) { ctx.JSON(u) } -// GetBy handles GET:/user/{id:long}, +// GetBy handles GET:/user/{id:int64}, // i.e http://localhost:8080/user/1 func (c *Controller) GetBy(userID int64) mvc.Result { // we have /user/{id} diff --git a/structuring/login-mvc-single-responsibility-package/user/datasource.go b/mvc/login-mvc-single-responsibility/user/datasource.go similarity index 100% rename from structuring/login-mvc-single-responsibility-package/user/datasource.go rename to mvc/login-mvc-single-responsibility/user/datasource.go diff --git a/structuring/login-mvc-single-responsibility-package/user/model.go b/mvc/login-mvc-single-responsibility/user/model.go similarity index 100% rename from structuring/login-mvc-single-responsibility-package/user/model.go rename to mvc/login-mvc-single-responsibility/user/model.go diff --git a/structuring/login-mvc-single-responsibility-package/views/shared/error.html b/mvc/login-mvc-single-responsibility/views/shared/error.html similarity index 100% rename from structuring/login-mvc-single-responsibility-package/views/shared/error.html rename to mvc/login-mvc-single-responsibility/views/shared/error.html diff --git a/structuring/login-mvc-single-responsibility-package/views/shared/layout.html b/mvc/login-mvc-single-responsibility/views/shared/layout.html similarity index 89% rename from structuring/login-mvc-single-responsibility-package/views/shared/layout.html rename to mvc/login-mvc-single-responsibility/views/shared/layout.html index 1e02677b..d6b50dcf 100644 --- a/structuring/login-mvc-single-responsibility-package/views/shared/layout.html +++ b/mvc/login-mvc-single-responsibility/views/shared/layout.html @@ -6,7 +6,7 @@ </head> <body> - {{ yield }} + {{ yield . }} </body> </html> \ No newline at end of file diff --git a/structuring/login-mvc-single-responsibility-package/views/user/login.html b/mvc/login-mvc-single-responsibility/views/user/login.html similarity index 100% rename from structuring/login-mvc-single-responsibility-package/views/user/login.html rename to mvc/login-mvc-single-responsibility/views/user/login.html diff --git a/structuring/login-mvc-single-responsibility-package/views/user/me.html b/mvc/login-mvc-single-responsibility/views/user/me.html similarity index 100% rename from structuring/login-mvc-single-responsibility-package/views/user/me.html rename to mvc/login-mvc-single-responsibility/views/user/me.html diff --git a/structuring/login-mvc-single-responsibility-package/views/user/notfound.html b/mvc/login-mvc-single-responsibility/views/user/notfound.html similarity index 100% rename from structuring/login-mvc-single-responsibility-package/views/user/notfound.html rename to mvc/login-mvc-single-responsibility/views/user/notfound.html diff --git a/structuring/login-mvc-single-responsibility-package/views/user/register.html b/mvc/login-mvc-single-responsibility/views/user/register.html similarity index 100% rename from structuring/login-mvc-single-responsibility-package/views/user/register.html rename to mvc/login-mvc-single-responsibility/views/user/register.html diff --git a/mvc/login/datamodels/user.go b/mvc/login/datamodels/user.go index a648deb9..fdcb63f9 100644 --- a/mvc/login/datamodels/user.go +++ b/mvc/login/datamodels/user.go @@ -10,7 +10,7 @@ import ( // Keep note that the tags for public-use (for our web app) // should be kept in other file like "web/viewmodels/user.go" // which could wrap by embedding the datamodels.User or -// define completely new fields instead but for the shake +// define completely new fields instead but for the sake // of the example, we will use this datamodel // as the only one User model in our application. type User struct { diff --git a/mvc/login/datasource/users.go b/mvc/login/datasource/users.go index 39d12536..1c3fb74a 100644 --- a/mvc/login/datasource/users.go +++ b/mvc/login/datasource/users.go @@ -5,7 +5,7 @@ package datasource import ( "errors" - "github.com/iris-contrib/examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" ) // Engine is from where to fetch the data, in this case the users. @@ -21,10 +21,10 @@ const ( MySQL ) -// LoadUsers returns all users(empty map) from the memory, for the shake of simplicty. +// LoadUsers returns all users(empty map) from the memory, for the sake of simplicty. func LoadUsers(engine Engine) (map[int64]datamodels.User, error) { if engine != Memory { - return nil, errors.New("for the shake of simplicity we're using a simple map as the data source") + return nil, errors.New("for the sake of simplicity we're using a simple map as the data source") } return make(map[int64]datamodels.User), nil diff --git a/mvc/login/main.go b/mvc/login/main.go index 06804996..ebda0367 100644 --- a/mvc/login/main.go +++ b/mvc/login/main.go @@ -5,15 +5,15 @@ package main import ( "time" - "github.com/iris-contrib/examples/mvc/login/datasource" - "github.com/iris-contrib/examples/mvc/login/repositories" - "github.com/iris-contrib/examples/mvc/login/services" - "github.com/iris-contrib/examples/mvc/login/web/controllers" - "github.com/iris-contrib/examples/mvc/login/web/middleware" + "github.com/kataras/iris/v12/_examples/mvc/login/datasource" + "github.com/kataras/iris/v12/_examples/mvc/login/repositories" + "github.com/kataras/iris/v12/_examples/mvc/login/services" + "github.com/kataras/iris/v12/_examples/mvc/login/web/controllers" + "github.com/kataras/iris/v12/_examples/mvc/login/web/middleware" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" ) func main() { @@ -28,12 +28,15 @@ func main() { Reload(true) app.RegisterView(tmpl) - app.StaticWeb("/public", "./web/public") + app.HandleDir("/public", iris.Dir("./web/public")) app.OnAnyErrorCode(func(ctx iris.Context) { ctx.ViewData("Message", ctx.Values(). GetStringDefault("message", "The page you're looking for doesn't exist")) - ctx.View("shared/error.html") + if err := ctx.View("shared/error.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) // ---- Serve our controllers. ---- @@ -76,14 +79,8 @@ func main() { // http://localhost:8080/user/me // http://localhost:8080/user/logout // basic auth: "admin", "password", see "./middleware/basicauth.go" source file. - app.Run( - // Starts the web server at localhost:8080 - iris.Addr("localhost:8080"), - // Disables the updater. - iris.WithoutVersionChecker, - // Ignores err server closed log when CTRL/CMD+C pressed. - iris.WithoutServerError(iris.ErrServerClosed), - // Enables faster json serialization and more. - iris.WithOptimizations, - ) + + // Starts the web server at localhost:8080 + // Enables faster json serialization and more. + app.Listen(":8080", iris.WithOptimizations) } diff --git a/mvc/login/repositories/user_repository.go b/mvc/login/repositories/user_repository.go index 347a32fa..71f9deff 100644 --- a/mvc/login/repositories/user_repository.go +++ b/mvc/login/repositories/user_repository.go @@ -4,7 +4,7 @@ import ( "errors" "sync" - "github.com/iris-contrib/examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" ) // Query represents the visitor and action queries. diff --git a/mvc/login/services/user_service.go b/mvc/login/services/user_service.go index 5ef61e68..32ebf5c7 100644 --- a/mvc/login/services/user_service.go +++ b/mvc/login/services/user_service.go @@ -3,8 +3,8 @@ package services import ( "errors" - "github.com/iris-contrib/examples/mvc/login/datamodels" - "github.com/iris-contrib/examples/mvc/login/repositories" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/repositories" ) // UserService handles CRUID operations of a user datamodel, @@ -51,7 +51,7 @@ func (s *userService) GetByID(id int64) (datamodels.User, bool) { }) } -// GetByUsernameAndPassword returns a user based on its username and passowrd, +// GetByUsernameAndPassword returns a user based on its username and password, // used for authentication. func (s *userService) GetByUsernameAndPassword(username, userPassword string) (datamodels.User, bool) { if username == "" || userPassword == "" { diff --git a/mvc/login/web/controllers/user_controller.go b/mvc/login/web/controllers/user_controller.go index 8dc915ee..56686619 100644 --- a/mvc/login/web/controllers/user_controller.go +++ b/mvc/login/web/controllers/user_controller.go @@ -3,12 +3,12 @@ package controllers import ( - "github.com/iris-contrib/examples/mvc/login/datamodels" - "github.com/iris-contrib/examples/mvc/login/services" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/services" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" ) // UserController is our /user controller. @@ -96,7 +96,6 @@ func (c *UserController) PostRegister() mvc.Result { // but it's good to know you can set a custom code; // Code: 303, } - } var loginStaticView = mvc.View{ diff --git a/mvc/login/web/controllers/users_controller.go b/mvc/login/web/controllers/users_controller.go index a4fe14af..24720b41 100644 --- a/mvc/login/web/controllers/users_controller.go +++ b/mvc/login/web/controllers/users_controller.go @@ -1,17 +1,17 @@ package controllers import ( - "github.com/iris-contrib/examples/mvc/login/datamodels" - "github.com/iris-contrib/examples/mvc/login/services" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/services" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // UsersController is our /users API controller. // GET /users | get all -// GET /users/{id:long} | get by id -// PUT /users/{id:long} | update by id -// DELETE /users/{id:long} | delete by id +// GET /users/{id:int64} | get by id +// PUT /users/{id:int64} | update by id +// DELETE /users/{id:int64} | delete by id // Requires basic authentication. type UsersController struct { // Optionally: context is auto-binded by Iris on each request, @@ -30,14 +30,16 @@ type UsersController struct { // curl -i -u admin:password http://localhost:8080/users // // The correct way if you have sensitive data: -// func (c *UsersController) Get() (results []viewmodels.User) { -// data := c.Service.GetAll() // -// for _, user := range data { -// results = append(results, viewmodels.User{user}) -// } -// return -// } +// func (c *UsersController) Get() (results []viewmodels.User) { +// data := c.Service.GetAll() +// +// for _, user := range data { +// results = append(results, viewmodels.User{user}) +// } +// return +// } +// // otherwise just return the datamodels. func (c *UsersController) Get() (results []datamodels.User) { return c.Service.GetAll() diff --git a/mvc/login/web/middleware/basicauth.go b/mvc/login/web/middleware/basicauth.go index b8a5355b..093bdb54 100644 --- a/mvc/login/web/middleware/basicauth.go +++ b/mvc/login/web/middleware/basicauth.go @@ -2,11 +2,9 @@ package middleware -import "github.com/kataras/iris/middleware/basicauth" +import "github.com/kataras/iris/v12/middleware/basicauth" // BasicAuth middleware sample. -var BasicAuth = basicauth.New(basicauth.Config{ - Users: map[string]string{ - "admin": "password", - }, +var BasicAuth = basicauth.Default(map[string]string{ + "admin": "password", }) diff --git a/mvc/login/web/viewmodels/README.md b/mvc/login/web/viewmodels/README.md index 0a2e6f00..3682b41b 100644 --- a/mvc/login/web/viewmodels/README.md +++ b/mvc/login/web/viewmodels/README.md @@ -6,9 +6,10 @@ Example: ```go import ( - "github.com/iris-contrib/examples/mvc/login/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/login/datamodels" - "github.com/kataras/iris/context" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" ) type User struct { @@ -41,7 +42,7 @@ so theoretically, something like the following is permitted if it's really neces // This is called where the return value from a controller's method functions // is type of `User`. // For example the `controllers/user_controller.go#GetBy`. -func (m User) Dispatch(ctx context.Context) { +func (m User) Dispatch(ctx iris.Context) { if !m.IsValid() { ctx.NotFound() return diff --git a/mvc/login/web/views/shared/layout.html b/mvc/login/web/views/shared/layout.html index 1e02677b..d6b50dcf 100644 --- a/mvc/login/web/views/shared/layout.html +++ b/mvc/login/web/views/shared/layout.html @@ -6,7 +6,7 @@ </head> <body> - {{ yield }} + {{ yield . }} </body> </html> \ No newline at end of file diff --git a/mvc/middleware/main.go b/mvc/middleware/main.go index bc081531..230079ab 100644 --- a/mvc/middleware/main.go +++ b/mvc/middleware/main.go @@ -5,29 +5,31 @@ package main import ( "time" - "github.com/kataras/iris" - "github.com/kataras/iris/cache" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/cache" + "github.com/kataras/iris/v12/mvc" ) var cacheHandler = cache.Handler(10 * time.Second) func main() { app := iris.New() + app.Logger().SetLevel("debug") + mvc.Configure(app, configure) // http://localhost:8080 // http://localhost:8080/other // // refresh every 10 seconds and you'll see different time output. - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func configure(m *mvc.Application) { m.Router.Use(cacheHandler) m.Handle(&exampleController{ timeFormat: "Mon, Jan 02 2006 15:04:05", - }) + } /* ,mvc.IgnoreEmbedded --- Can be used to ignore any embedded struct method handlers */) } type exampleController struct { diff --git a/mvc/middleware/per-method/main.go b/mvc/middleware/per-method/main.go index 56a61b6b..83392a23 100644 --- a/mvc/middleware/per-method/main.go +++ b/mvc/middleware/per-method/main.go @@ -9,9 +9,11 @@ else as well, otherwise I am going with the first one: ```go // 1 -mvc.Configure(app.Party("/user"), func(m *mvc.Application) { - m.Router.Use(cache.Handler(10*time.Second)) -}) + + mvc.Configure(app.Party("/user"), func(m *mvc.Application) { + m.Router.Use(cache.Handler(10*time.Second)) + }) + ``` ```go @@ -32,10 +34,12 @@ mvc.Configure(userRouter, ...) ```go // 4 // same: -app.PartyFunc("/user", func(r iris.Party){ - r.Use(cache.Handler(10*time.Second)) - mvc.Configure(r, ...) -}) + + app.PartyFunc("/user", func(r iris.Party){ + r.Use(cache.Handler(10*time.Second)) + mvc.Configure(r, ...) + }) + ``` If you want to use a middleware for a single route, @@ -48,16 +52,18 @@ then you just call it on the method: var myMiddleware := myMiddleware.New(...) // this should return an iris/context.Handler type UserController struct{} -func (c *UserController) GetSomething(ctx iris.Context) { - // ctx.Proceed checks if myMiddleware called `ctx.Next()` - // inside it and returns true if so, otherwise false. - nextCalled := ctx.Proceed(myMiddleware) - if !nextCalled { - return - } - - // else do the job here, it's allowed -} + + func (c *UserController) GetSomething(ctx iris.Context) { + // ctx.Proceed checks if myMiddleware called `ctx.Next()` + // inside it and returns true if so, otherwise false. + nextCalled := ctx.Proceed(myMiddleware) + if !nextCalled { + return + } + + // else do the job here, it's allowed + } + ``` And last, if you want to add a middleware on a specific method @@ -69,9 +75,9 @@ package main import ( "time" - "github.com/kataras/iris" - "github.com/kataras/iris/cache" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/cache" + "github.com/kataras/iris/v12/mvc" ) var cacheHandler = cache.Handler(10 * time.Second) @@ -84,7 +90,7 @@ func main() { m := mvc.New(app) m.Handle(&exampleController{}) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } type exampleController struct{} diff --git a/mvc/middleware/without-ctx-next/main.go b/mvc/middleware/without-ctx-next/main.go index baa983b0..aae02aeb 100644 --- a/mvc/middleware/without-ctx-next/main.go +++ b/mvc/middleware/without-ctx-next/main.go @@ -1,57 +1,34 @@ -/*Package main is a simple example of the behavior change of the execution flow of the handlers, -normally we need the `ctx.Next()` to call the next handler in a route's handler chain, -but with the new `ExecutionRules` we can change this default behavior. -Please read below before continue. +/* +Package main shows how to add done handlers in an MVC application without +the necessity of `ctx.Next()` inside the controller's methods. -The `Party#SetExecutionRules` alters the execution flow of the route handlers outside of the handlers themselves. - -For example, if for some reason the desired result is the (done or all) handlers to be executed no matter what -even if no `ctx.Next()` is called in the previous handlers, including the begin(`Use`), -the main(`Handle`) and the done(`Done`) handlers themselves, then: -Party#SetExecutionRules(iris.ExecutionRules { - Begin: iris.ExecutionOptions{Force: true}, - Main: iris.ExecutionOptions{Force: true}, - Done: iris.ExecutionOptions{Force: true}, -}) - -Note that if `true` then the only remained way to "break" the handler chain is by `ctx.StopExecution()` now that `ctx.Next()` does not matter. - -These rules are per-party, so if a `Party` creates a child one then the same rules will be applied to that as well. -Reset of these rules (before `Party#Handle`) can be done with `Party#SetExecutionRules(iris.ExecutionRules{})`. - -The most common scenario for its use can be found inside Iris MVC Applications; -when we want the `Done` handlers of that specific mvc app's `Party` -to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest`*/ +When we want the `Done` handlers of that specific mvc app's `Party` +to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest` +*/ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) func main() { app := iris.New() app.Get("/", func(ctx iris.Context) { ctx.Redirect("/example") }) - // example := app.Party("/example") - // example.SetExecutionRules && mvc.New(example) or... - m := mvc.New(app.Party("/example")) + exampleRouter := app.Party("/example") + { + exampleRouter.SetExecutionRules(iris.ExecutionRules{ + Done: iris.ExecutionOptions{Force: true}, + }) - // IMPORTANT - // All options can be filled with Force:true, they all play nice together. - m.Router.SetExecutionRules(iris.ExecutionRules{ - // Begin: <- from `Use[all]` to `Handle[last]` future route handlers, execute all, execute all even if `ctx.Next()` is missing. - // Main: <- all `Handle` future route handlers, execute all >> >>. - Done: iris.ExecutionOptions{Force: true}, // <- from `Handle[last]` to `Done[all]` future route handlers, execute all >> >>. - }) - m.Router.Done(doneHandler) - // m.Router.Done(...) - // ... - // + exampleRouter.Done(doneHandler) - m.Handle(&exampleController{}) + m := mvc.New(exampleRouter) + m.Handle(&exampleController{}) + } - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func doneHandler(ctx iris.Context) { @@ -64,7 +41,8 @@ func (c *exampleController) Get() string { return "From Main Handler" // Note that here we don't binding the `Context`, and we don't call its `Next()` // function in order to call the `doneHandler`, - // this is done automatically for us because we changed the execution rules with the `SetExecutionRules`. + // this is done automatically for us because we changed the execution rules with the + // `SetExecutionRules`. // // Therefore the final output is: // From Main Handler diff --git a/mvc/overview/Dockerfile b/mvc/overview/Dockerfile new file mode 100644 index 00000000..16c9113d --- /dev/null +++ b/mvc/overview/Dockerfile @@ -0,0 +1,17 @@ +# docker build -t app . +# docker run --rm -it -p 8080:8080 app:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/app . +ENTRYPOINT ["./app"] \ No newline at end of file diff --git a/mvc/overview/README.md b/mvc/overview/README.md new file mode 100644 index 00000000..8b7c19eb --- /dev/null +++ b/mvc/overview/README.md @@ -0,0 +1,378 @@ +# Quick start + +The following guide is just a simple example of usage of some of the **Iris MVC** features. You are not limited to that data structure or code flow. + +Create a folder, let's assume its path is `app`. The structure should look like that: + +``` +│ main.go +│ go.mod +│ go.sum +└───environment +│ environment.go +└───model +│ request.go +│ response.go +└───database +│ database.go +│ mysql.go +│ sqlite.go +└───service +│ greet_service.go +└───controller + greet_controller.go +``` + +Navigate to that `app` folder and execute the following command: + +```sh +$ go init app +$ go get github.com/kataras/iris/v12@main +# or @latest for the latest official release. +``` + +## Environment + +Let's start by defining the available environments that our web-application can behave on. + +We'll just work on two available environments, the "development" and the "production", as they define the two most common scenarios. The `ReadEnv` will read from the `Env` type of a system's environment variable (see `main.go` in the end of the page). + +Create a `environment/environment.go` file and put the following contents: + +```go +package environment + +import ( + "os" + "strings" +) + +const ( + PROD Env = "production" + DEV Env = "development" +) + +type Env string + +func (e Env) String() string { + return string(e) +} + +func ReadEnv(key string, def Env) Env { + v := Getenv(key, def.String()) + if v == "" { + return def + } + + env := Env(strings.ToLower(v)) + switch env { + case PROD, DEV: // allowed. + default: + panic("unexpected environment " + v) + } + + return env +} + +func Getenv(key string, def string) string { + if v := os.Getenv(key); v != "" { + return v + } + + return def +} +``` + +## Database + +We will use two database management systems, the `MySQL` and the `SQLite`. The first one for "production" use and the other for "development". + +Create a `database/database.go` file and copy-paste the following: + +```go +package database + +import "app/environment" + +type DB interface { + Exec(q string) error +} + +func NewDB(env environment.Env) DB { + switch env { + case environment.PROD: + return &mysql{} + case environment.DEV: + return &sqlite{} + default: + panic("unknown environment") + } +} +``` + +Let's simulate our MySQL and SQLite `DB` instances. Create a `database/mysql.go` file which looks like the following one: + +```go +package database + +import "fmt" + +type mysql struct{} + +func (db *mysql) Exec(q string) error { + return fmt.Errorf("mysql: not implemented <%s>", q) +} +``` + +And a `database/sqlite.go` file. + +```go +package database + +type sqlite struct{} + +func (db *sqlite) Exec(q string) error { return nil } +``` + +The `DB` depends on the `Environment. + +> A practical and operational database example, including Docker images, can be found at the following guide: https://github.com/kataras/iris/tree/main/_examples/database/mysql + +## Service + +We'll need a service that will communicate with a database instance in behalf of our Controller(s). + +In our case we will only need a single service, the Greet Service. + +For the sake of the example, let's use two implementations of a greet service based on the `Environment`. The `GreetService` interface contains a single method of `Say(input string) (output string, err error)`. Create a `./service/greet_service.go` file and write the following code: + +```go +package service + +import ( + "fmt" + + "app/database" + "app/environment" +) + +// GreetService example service. +type GreetService interface { + Say(input string) (string, error) +} + +// NewGreetService returns a service backed with a "db" based on "env". +func NewGreetService(env environment.Env, db database.DB) GreetService { + service := &greeter{db: db, prefix: "Hello"} + + switch env { + case environment.PROD: + return service + case environment.DEV: + return &greeterWithLogging{service} + default: + panic("unknown environment") + } +} + +type greeter struct { + prefix string + db database.DB +} + +func (s *greeter) Say(input string) (string, error) { + if err := s.db.Exec("simulate a query..."); err != nil { + return "", err + } + + result := s.prefix + " " + input + return result, nil +} + +type greeterWithLogging struct { + *greeter +} + +func (s *greeterWithLogging) Say(input string) (string, error) { + result, err := s.greeter.Say(input) + fmt.Printf("result: %s\nerror: %v\n", result, err) + return result, err +} + +``` + +The `greeter` will be used on "production" and the `greeterWithLogging` on "development". The `GreetService` depends on the `Environment` and the `DB`. + +## Models + +Continue by creating our HTTP request and response models. + +Create a `model/request.go` file and copy-paste the following code: + +```go +package model + +type Request struct { + Name string `url:"name"` +} +``` + +Same for the `model/response.go` file. + +```go +package model + +type Response struct { + Message string `json:"msg"` +} +``` + +The server will accept a URL Query Parameter of `name` (e.g. `/greet?name=kataras`) and will reply back with a JSON message. + +## Controller + +MVC Controllers are responsible for controlling the flow of the application execution. When you make a request (means request a page) to MVC Application, a controller is responsible for returning the response to that request. + +We will only need the `GreetController` for our mini web-application. Create a file at `controller/greet_controller.go` which looks like that: + +```go +package controller + +import ( + "app/model" + "app/service" +) + +type GreetController struct { + Service service.GreetService + // Ctx iris.Context +} + +func (c *GreetController) Get(req model.Request) (model.Response, error) { + message, err := c.Service.Say(req.Name) + if err != nil { + return model.Response{}, err + } + + return model.Response{Message: message}, nil +} +``` + +The `GreetController` depends on the `GreetService`. It serves the `GET: /greet` index path through its `Get` method. The `Get` method accepts a `model.Request` which contains a single field name of `Name` which will be extracted from the `URL Query Parameter 'name'` (because it's a `GET` requst and its `url:"name"` struct field). + +## Wrap up + +```sh + +-------------------+ + | Env (DEV, PROD) | + +---------+---------+ + | | | + | | | + | | | + DEV | | | PROD +-------------------+---------------------+ | +----------------------+------------------- + | | | + | | | + +---+-----+ +----------------v------------------+ +----+----+ + | sqlite | | NewDB(Env) DB | | mysql | + +---+-----+ +----------------+---+--------------+ +----+----+ + | | | | + | | | | + | | | | + +--------------+-----+ +-------------------v---v-----------------+ +----+------+ + | greeterWithLogging | | NewGreetService(Env, DB) GreetService | | greeter | + +--------------+-----+ +---------------------------+-------------+ +----+------+ + | | | + | | | + | +-----------------------------------------+ | + | | GreetController | | | + | | | | | + | | - Service GreetService <-- | | + | | | | + | +-------------------+---------------------+ | + | | | + | | | + | | | + | +-----------+-----------+ | + | | HTTP Request | | + | +-----------------------+ | + | | /greet?name=kataras | | + | +-----------+-----------+ | + | | | ++------------------+--------+ +------------+------------+ +-------+------------------+ +| model.Response (JSON) | | Response (JSON, error) | | Bad Request | ++---------------------------+ +-------------------------+ +--------------------------+ +| { | | mysql: not implemented | +| "msg": "Hello kataras" | +--------------------------+ +| } | ++---------------------------+ +``` + +Now it's the time to wrap all the above into our `main.go` file. Copy-paste the following code: + +```go +package main + +import ( + "app/controller" + "app/database" + "app/environment" + "app/service" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.Get("/ping", pong).Describe("healthcheck") + + mvc.Configure(app.Party("/greet"), setup) + + // http://localhost:8080/greet?name=kataras + app.Listen(":8080", iris.WithLogLevel("debug")) +} + +func pong(ctx iris.Context) { + ctx.WriteString("pong") +} + +func setup(app *mvc.Application) { + // Register Dependencies. + app.Register( + environment.DEV, // DEV, PROD + database.NewDB, // sqlite, mysql + service.NewGreetService, // greeterWithLogging, greeter + ) + + // Register Controllers. + app.Handle(new(controller.GreetController)) +} +``` + +The `mvc.Application.Register` method registers one more dependencies, dependencies can depend on previously registered dependencies too. Thats the reason we pass, first, the `Environment(DEV)`, then the `NewDB` which depends on that `Environment`, following by the `NewGreetService` function which depends on both the `Environment(DEV)` and the `DB`. + +The `mvc.Application.Handle` registers a new controller, which depends on the `GreetService`, for the targeted sub-router of `Party("/greet")`. + +## Run + +Install [Go](https://golang.org/dl) and run the application with: + +```sh +go run main.go +``` + +<details><summary>Docker</summary> + +Download the [Dockerfile](https://raw.githubusercontent.com/kataras/iris/9b93c0dbb491dcedf49c91e89ca13bab884d116f/_examples/mvc/overview/Dockerfile) and [docker-compose.yml](https://raw.githubusercontent.com/kataras/iris/9b93c0dbb491dcedf49c91e89ca13bab884d116f/_examples/mvc/overview/docker-compose.yml) files to the `app` folder. + +Install [Docker](https://www.docker.com/) and execute the following command: + +```sh +$ docker-compose up +``` +</details> + +Visit http://localhost:8080?name=kataras. + +Optionally, replace the `main.go`'s `app.Register(environment.DEV` with `environment.PROD`, restart the application and refresh. You will see that a new database (`sqlite`) and another service of (`greeterWithLogging`) will be binded to the `GreetController`. With **a single change** you achieve to completety change the result. diff --git a/mvc/overview/controller/greet_controller.go b/mvc/overview/controller/greet_controller.go new file mode 100644 index 00000000..737bd537 --- /dev/null +++ b/mvc/overview/controller/greet_controller.go @@ -0,0 +1,23 @@ +package controller + +import ( + "app/model" + "app/service" +) + +// GreetController handles the index. +type GreetController struct { + Service service.GreetService + // Ctx iris.Context +} + +// Get serves [GET] /. +// Query: name +func (c *GreetController) Get(req model.Request) (model.Response, error) { + message, err := c.Service.Say(req.Name) + if err != nil { + return model.Response{}, err + } + + return model.Response{Message: message}, nil +} diff --git a/mvc/overview/database/database.go b/mvc/overview/database/database.go new file mode 100644 index 00000000..c99e96c6 --- /dev/null +++ b/mvc/overview/database/database.go @@ -0,0 +1,20 @@ +package database + +import "app/environment" + +// DB example database interface. +type DB interface { + Exec(q string) error +} + +// NewDB returns a database based on "env". +func NewDB(env environment.Env) DB { + switch env { + case environment.PROD: + return &mysql{} + case environment.DEV: + return &sqlite{} + default: + panic("unknown environment") + } +} diff --git a/mvc/overview/database/mysql.go b/mvc/overview/database/mysql.go new file mode 100644 index 00000000..5d14da05 --- /dev/null +++ b/mvc/overview/database/mysql.go @@ -0,0 +1,10 @@ +package database + +import "fmt" + +type mysql struct{} + +func (db *mysql) Exec(q string) error { + // simulate an error response. + return fmt.Errorf("mysql: not implemented <%s>", q) +} diff --git a/mvc/overview/database/sqlite.go b/mvc/overview/database/sqlite.go new file mode 100644 index 00000000..956a82fd --- /dev/null +++ b/mvc/overview/database/sqlite.go @@ -0,0 +1,5 @@ +package database + +type sqlite struct{} + +func (db *sqlite) Exec(q string) error { return nil } diff --git a/mvc/overview/docker-compose.yml b/mvc/overview/docker-compose.yml new file mode 100644 index 00000000..db906506 --- /dev/null +++ b/mvc/overview/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.1' + +services: + app: + build: . + ports: + - 8080:8080 + environment: + PORT: 8080 + ENVIRONMENT: development + restart: on-failure + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/ping"] + interval: 30s + timeout: 10s + retries: 5 diff --git a/mvc/overview/environment/environment.go b/mvc/overview/environment/environment.go new file mode 100644 index 00000000..519a7cc9 --- /dev/null +++ b/mvc/overview/environment/environment.go @@ -0,0 +1,50 @@ +package environment + +import ( + "os" + "strings" +) + +// Available environments example. +const ( + PROD Env = "production" + DEV Env = "development" +) + +// Env is the environment type. +type Env string + +// String just returns the string representation of the Env. +func (e Env) String() string { + return string(e) +} + +// ReadEnv returns the environment of the system environment variable of "key". +// Returns the "def" if not found. +// Reports a panic message if the environment variable found +// but the Env is unknown. +func ReadEnv(key string, def Env) Env { + v := Getenv(key, def.String()) + if v == "" { + return def + } + + env := Env(strings.ToLower(v)) + switch env { + case PROD, DEV: // allowed. + default: + panic("unexpected environment " + v) + } + + return env +} + +// Getenv returns the value of a system environment variable "key". +// Defaults to "def" if not found. +func Getenv(key string, def string) string { + if v := os.Getenv(key); v != "" { + return v + } + + return def +} diff --git a/mvc/overview/go.mod b/mvc/overview/go.mod new file mode 100644 index 00000000..f613d0e8 --- /dev/null +++ b/mvc/overview/go.mod @@ -0,0 +1,62 @@ +module app + +go 1.22 + +require github.com/kataras/iris/v12 v12.2.11 + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/mvc/overview/go.sum b/mvc/overview/go.sum new file mode 100644 index 00000000..f9398280 --- /dev/null +++ b/mvc/overview/go.sum @@ -0,0 +1,200 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/mvc/overview/main.go b/mvc/overview/main.go index d96f260e..26c2eb81 100644 --- a/mvc/overview/main.go +++ b/mvc/overview/main.go @@ -1,62 +1,90 @@ -// file: main.go - package main import ( - "github.com/iris-contrib/examples/mvc/overview/datasource" - "github.com/iris-contrib/examples/mvc/overview/repositories" - "github.com/iris-contrib/examples/mvc/overview/services" - "github.com/iris-contrib/examples/mvc/overview/web/controllers" - "github.com/iris-contrib/examples/mvc/overview/web/middleware" - - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "app/controller" + "app/database" + "app/environment" + "app/service" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) func main() { app := iris.New() app.Logger().SetLevel("debug") - // Load the template files. - app.RegisterView(iris.HTML("./web/views", ".html")) - - // Serve our controllers. - mvc.New(app.Party("/hello")).Handle(new(controllers.HelloController)) - // You can also split the code you write to configure an mvc.Application - // using the `mvc.Configure` method, as shown below. - mvc.Configure(app.Party("/movies"), movies) - - // http://localhost:8080/hello - // http://localhost:8080/hello/iris - // http://localhost:8080/movies - // http://localhost:8080/movies/1 - app.Run( - // Start the web server at localhost:8080 - iris.Addr("localhost:8080"), - // disables updates: - iris.WithoutVersionChecker, - // skip err server closed when CTRL/CMD+C pressed: - iris.WithoutServerError(iris.ErrServerClosed), - // enables faster json serialization and more: - iris.WithOptimizations, - ) + app.Get("/ping", pong).Describe("healthcheck") + + mvc.Configure(app.Party("/greet"), setup) + + // http://localhost:8080/greet?name=kataras + addr := ":" + environment.Getenv("PORT", "8080") + app.Listen(addr) +} + +func pong(ctx iris.Context) { + ctx.WriteString("pong") } -// note the mvc.Application, it's not iris.Application. -func movies(app *mvc.Application) { - // Add the basic authentication(admin:password) middleware - // for the /movies based requests. - app.Router.Use(middleware.BasicAuth) - - // Create our movie repository with some (memory) data from the datasource. - repo := repositories.NewMovieRepository(datasource.Movies) - // Create our movie service, we will bind it to the movie app's dependencies. - movieService := services.NewMovieService(repo) - app.Register(movieService) - - // serve our movies controller. - // Note that you can serve more than one controller - // you can also create child mvc apps using the `movies.Party(relativePath)` or `movies.Clone(app.Party(...))` - // if you want. - app.Handle(new(controllers.MovieController)) +/* + +-------------------+ + | Env (DEV, PROD) | + +---------+---------+ + | | | + | | | + | | | + DEV | | | PROD + +-------------------+---------------------+ | +----------------------+------------------- + + | | | + | | | + +---+-----+ +----------------v------------------+ +----+----+ + | sqlite | | NewDB(Env) DB | | mysql | + +---+-----+ +----------------+---+--------------+ +----+----+ + | | | | + | | | | + | | | | + +--------------+-----+ +-------------------v---v-----------------+ +----+------+ + | greeterWithLogging | | NewGreetService(Env, DB) GreetService | | greeter | + +--------------+-----+ +---------------------------+-------------+ +----+------+ + | | | + | | | + | +-----------------------------------------+ | + | | GreetController | | | + | | | | | + | | - Service GreetService <-- | | + | | | | + | +-------------------+---------------------+ | + | | | + | | | + | | | + | +-----------+-----------+ | + | | HTTP Request | | + | +-----------------------+ | + | | /greet?name=kataras | | + | +-----------+-----------+ | + | | | + ++------------------+--------+ +------------+------------+ +-------+------------------+ +| model.Response (JSON) | | Response (JSON, error) | | Bad Request | ++---------------------------+ +-------------------------+ +--------------------------+ +| { | | mysql: not implemented | +| "msg": "Hello kataras" | +--------------------------+ +| } | ++---------------------------+ +*/ +func setup(app *mvc.Application) { + // Register Dependencies. + // Tip: A dependency can depend on other dependencies too. + env := environment.ReadEnv("ENVIRONMENT", environment.DEV) + app.Register( + env, // DEV, PROD + database.NewDB, // sqlite, mysql + service.NewGreetService, // greeterWithLogging, greeter + ) + + // Register Controllers. + app.Handle(new(controller.GreetController)) } diff --git a/mvc/overview/model/request.go b/mvc/overview/model/request.go new file mode 100644 index 00000000..03a826ed --- /dev/null +++ b/mvc/overview/model/request.go @@ -0,0 +1,6 @@ +package model + +// Request example incoming request. +type Request struct { + Name string `json:"name" url:"name"` +} diff --git a/mvc/overview/model/response.go b/mvc/overview/model/response.go new file mode 100644 index 00000000..18e7855f --- /dev/null +++ b/mvc/overview/model/response.go @@ -0,0 +1,6 @@ +package model + +// Response example server's response. +type Response struct { + Message string `json:"msg"` +} diff --git a/mvc/overview/service/greet_service.go b/mvc/overview/service/greet_service.go new file mode 100644 index 00000000..c0d493d8 --- /dev/null +++ b/mvc/overview/service/greet_service.go @@ -0,0 +1,51 @@ +package service + +import ( + "fmt" + + "app/database" + "app/environment" +) + +// GreetService example service. +type GreetService interface { + Say(input string) (string, error) +} + +// NewGreetService returns a service backed with a "db" based on "env". +func NewGreetService(env environment.Env, db database.DB) GreetService { + service := &greeter{db: db, prefix: "Hello"} + + switch env { + case environment.PROD: + return service + case environment.DEV: + return &greeterWithLogging{service} + default: + panic("unknown environment") + } +} + +type greeter struct { + prefix string + db database.DB +} + +func (s *greeter) Say(input string) (string, error) { + if err := s.db.Exec("simulate a query..."); err != nil { + return "", err + } + + result := s.prefix + " " + input + return result, nil +} + +type greeterWithLogging struct { + *greeter +} + +func (s *greeterWithLogging) Say(input string) (string, error) { + result, err := s.greeter.Say(input) + fmt.Printf("result: %s\nerror: %v\n", result, err) + return result, err +} diff --git a/mvc/overview/web/middleware/basicauth.go b/mvc/overview/web/middleware/basicauth.go deleted file mode 100644 index c9b6eacf..00000000 --- a/mvc/overview/web/middleware/basicauth.go +++ /dev/null @@ -1,12 +0,0 @@ -// file: web/middleware/basicauth.go - -package middleware - -import "github.com/kataras/iris/middleware/basicauth" - -// BasicAuth middleware sample. -var BasicAuth = basicauth.New(basicauth.Config{ - Users: map[string]string{ - "admin": "password", - }, -}) diff --git a/mvc/regexp/main.go b/mvc/regexp/main.go new file mode 100644 index 00000000..ca342450 --- /dev/null +++ b/mvc/regexp/main.go @@ -0,0 +1,49 @@ +// Package main shows how to match "/xxx.json" in MVC handler. +package main + +/* +There is no MVC naming pattern for such these things,you can imagine the limitations of that. +Instead you can use the `BeforeActivation` on your controller to add more advanced routing features +(https://github.com/kataras/iris/tree/main/_examples/routing). + +You can also create your own macro, +i.e: /{file:json} or macro function of a specific parameter type i.e: (/{file:string json()}). +Read the routing examples and you will gain a deeper view, there are all covered. +*/ + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + + mvcApp := mvc.New(app.Party("/module")) + mvcApp.Handle(new(myController)) + + // http://localhost:8080/module/xxx.json (OK) + // http://localhost:8080/module/xxx.xml (Not Found) + app.Listen(":8080") +} + +type myController struct{} + +func (m *myController) BeforeActivation(b mvc.BeforeActivation) { + // b.Dependencies().Register + // b.Router().Use/UseGlobal/Done // and any standard API call you already know + + // 1-> Method + // 2-> Path + // 3-> The controller's function name to be parsed as handler + // 4-> Any handlers that should run before the HandleJSON + + // "^[a-zA-Z0-9_.-]+.json$)" to validate file-name pattern and json + // or just: ".json$" to validate suffix. + + b.Handle("GET", "/{file:string regexp(^[a-zA-Z0-9_.-]+.json$))}", "HandleJSON" /*optionalMiddleware*/) +} + +func (m *myController) HandleJSON(file string) string { + return "custom serving of json: " + file +} diff --git a/mvc/overview/datamodels/README.md b/mvc/repository/datamodels/README.md similarity index 100% rename from mvc/overview/datamodels/README.md rename to mvc/repository/datamodels/README.md diff --git a/mvc/overview/datamodels/movie.go b/mvc/repository/datamodels/movie.go similarity index 94% rename from mvc/overview/datamodels/movie.go rename to mvc/repository/datamodels/movie.go index 7649d487..4499ad47 100644 --- a/mvc/overview/datamodels/movie.go +++ b/mvc/repository/datamodels/movie.go @@ -8,7 +8,7 @@ package datamodels // which could wrap by embedding the datamodels.Movie or // declare new fields instead butwe will use this datamodel // as the only one Movie model in our application, -// for the shake of simplicty. +// for the sake of simplicty. type Movie struct { ID int64 `json:"id"` Name string `json:"name"` diff --git a/mvc/overview/datasource/README.md b/mvc/repository/datasource/README.md similarity index 100% rename from mvc/overview/datasource/README.md rename to mvc/repository/datasource/README.md diff --git a/hero/overview/datasource/movies.go b/mvc/repository/datasource/movies.go similarity index 92% rename from hero/overview/datasource/movies.go rename to mvc/repository/datasource/movies.go index 7c407ff0..518245df 100644 --- a/hero/overview/datasource/movies.go +++ b/mvc/repository/datasource/movies.go @@ -2,7 +2,7 @@ package datasource -import "github.com/iris-contrib/examples/hero/overview/datamodels" +import "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" // Movies is our imaginary data source. var Movies = map[int64]datamodels.Movie{ diff --git a/mvc/overview/folder_structure.png b/mvc/repository/folder_structure.png similarity index 100% rename from mvc/overview/folder_structure.png rename to mvc/repository/folder_structure.png diff --git a/mvc/repository/main.go b/mvc/repository/main.go new file mode 100644 index 00000000..1cd430b7 --- /dev/null +++ b/mvc/repository/main.go @@ -0,0 +1,53 @@ +// file: main.go + +package main + +import ( + "github.com/kataras/iris/v12/_examples/mvc/repository/datasource" + "github.com/kataras/iris/v12/_examples/mvc/repository/repositories" + "github.com/kataras/iris/v12/_examples/mvc/repository/services" + "github.com/kataras/iris/v12/_examples/mvc/repository/web/controllers" + "github.com/kataras/iris/v12/_examples/mvc/repository/web/middleware" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + // Load the template files. + app.RegisterView(iris.HTML("./web/views", ".html")) + + // Serve our controllers. + mvc.New(app.Party("/hello")).Handle(new(controllers.HelloController)) + // You can also split the code you write to configure an mvc.Application + // using the `mvc.Configure` method, as shown below. + mvc.Configure(app.Party("/movies"), movies) + + // http://localhost:8080/hello + // http://localhost:8080/hello/iris + // http://localhost:8080/movies + // http://localhost:8080/movies/1 + app.Listen(":8080", iris.WithOptimizations) +} + +// note the mvc.Application, it's not iris.Application. +func movies(app *mvc.Application) { + // Add the basic authentication(admin:password) middleware + // for the /movies based requests. + app.Router.Use(middleware.BasicAuth) + + // Create our movie repository with some (memory) data from the datasource. + repo := repositories.NewMovieRepository(datasource.Movies) + // Create our movie service, we will bind it to the movie app's dependencies. + movieService := services.NewMovieService(repo) + app.Register(movieService) + + // serve our movies controller. + // Note that you can serve more than one controller + // you can also create child mvc apps using the `movies.Party(relativePath)` or `movies.Clone(app.Party(...))` + // if you want. + app.Handle(new(controllers.MovieController)) +} diff --git a/mvc/overview/models/README.md b/mvc/repository/models/README.md similarity index 84% rename from mvc/overview/models/README.md rename to mvc/repository/models/README.md index 068d73d5..280664ee 100644 --- a/mvc/overview/models/README.md +++ b/mvc/repository/models/README.md @@ -5,7 +5,7 @@ There should be the domain/business-level models. Example: ```go -import "github.com/iris-contrib/examples/mvc/overview/datamodels" +import "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" type Movie struct { datamodels.Movie diff --git a/mvc/overview/repositories/README.md b/mvc/repository/repositories/README.md similarity index 100% rename from mvc/overview/repositories/README.md rename to mvc/repository/repositories/README.md diff --git a/mvc/overview/repositories/movie_repository.go b/mvc/repository/repositories/movie_repository.go similarity index 98% rename from mvc/overview/repositories/movie_repository.go rename to mvc/repository/repositories/movie_repository.go index 003cc50e..6a79aeee 100644 --- a/mvc/overview/repositories/movie_repository.go +++ b/mvc/repository/repositories/movie_repository.go @@ -6,7 +6,7 @@ import ( "errors" "sync" - "github.com/iris-contrib/examples/mvc/overview/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" ) // Query represents the visitor and action queries. diff --git a/mvc/overview/services/README.md b/mvc/repository/services/README.md similarity index 100% rename from mvc/overview/services/README.md rename to mvc/repository/services/README.md diff --git a/hero/overview/services/movie_service.go b/mvc/repository/services/movie_service.go similarity index 93% rename from hero/overview/services/movie_service.go rename to mvc/repository/services/movie_service.go index 93f523b0..5e1b0280 100644 --- a/hero/overview/services/movie_service.go +++ b/mvc/repository/services/movie_service.go @@ -3,8 +3,8 @@ package services import ( - "github.com/iris-contrib/examples/hero/overview/datamodels" - "github.com/iris-contrib/examples/hero/overview/repositories" + "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/repository/repositories" ) // MovieService handles some of the CRUID operations of the movie datamodel. diff --git a/mvc/overview/web/controllers/hello_controller.go b/mvc/repository/web/controllers/hello_controller.go similarity index 93% rename from mvc/overview/web/controllers/hello_controller.go rename to mvc/repository/web/controllers/hello_controller.go index d1ff76ae..21bbc99e 100644 --- a/mvc/overview/web/controllers/hello_controller.go +++ b/mvc/repository/web/controllers/hello_controller.go @@ -5,7 +5,7 @@ package controllers import ( "errors" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12/mvc" ) // HelloController is our sample controller @@ -23,7 +23,7 @@ var helloView = mvc.View{ // Get will return a predefined view with bind data. // // `mvc.Result` is just an interface with a `Dispatch` function. -// `mvc.Response` and `mvc.View` are the built'n result type dispatchers +// `mvc.Response` and `mvc.View` are the builtin result type dispatchers // you can even create custom response dispatchers by // implementing the `github.com/kataras/iris/hero#Result` interface. func (c *HelloController) Get() mvc.Result { diff --git a/mvc/overview/web/controllers/movie_controller.go b/mvc/repository/web/controllers/movie_controller.go similarity index 83% rename from mvc/overview/web/controllers/movie_controller.go rename to mvc/repository/web/controllers/movie_controller.go index cec0e9f4..9f1aec89 100644 --- a/mvc/overview/web/controllers/movie_controller.go +++ b/mvc/repository/web/controllers/movie_controller.go @@ -5,10 +5,10 @@ package controllers import ( "errors" - "github.com/iris-contrib/examples/mvc/overview/datamodels" - "github.com/iris-contrib/examples/mvc/overview/services" + "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/repository/services" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // MovieController is our /movies controller. @@ -23,14 +23,16 @@ type MovieController struct { // curl -i http://localhost:8080/movies // // The correct way if you have sensitive data: -// func (c *MovieController) Get() (results []viewmodels.Movie) { -// data := c.Service.GetAll() // -// for _, movie := range data { -// results = append(results, viewmodels.Movie{movie}) -// } -// return -// } +// func (c *MovieController) Get() (results []viewmodels.Movie) { +// data := c.Service.GetAll() +// +// for _, movie := range data { +// results = append(results, viewmodels.Movie{movie}) +// } +// return +// } +// // otherwise just return the datamodels. func (c *MovieController) Get() (results []datamodels.Movie) { return c.Service.GetAll() diff --git a/mvc/repository/web/middleware/basicauth.go b/mvc/repository/web/middleware/basicauth.go new file mode 100644 index 00000000..8cda6629 --- /dev/null +++ b/mvc/repository/web/middleware/basicauth.go @@ -0,0 +1,10 @@ +// file: web/middleware/basicauth.go + +package middleware + +import "github.com/kataras/iris/v12/middleware/basicauth" + +// BasicAuth middleware sample. +var BasicAuth = basicauth.Default(map[string]string{ + "admin": "password", +}) diff --git a/mvc/overview/web/viewmodels/README.md b/mvc/repository/web/viewmodels/README.md similarity index 89% rename from mvc/overview/web/viewmodels/README.md rename to mvc/repository/web/viewmodels/README.md index 8a959d50..10520287 100644 --- a/mvc/overview/web/viewmodels/README.md +++ b/mvc/repository/web/viewmodels/README.md @@ -6,9 +6,10 @@ Example: ```go import ( - "github.com/iris-contrib/examples/mvc/overview/datamodels" + "github.com/kataras/iris/v12/_examples/mvc/repository/datamodels" - "github.com/kataras/iris/context" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" ) type Movie struct { @@ -41,7 +42,7 @@ so theoretically, something like the following is permitted if it's really neces // This is called where the return value from a controller's method functions // is type of `Movie`. // For example the `controllers/movie_controller.go#GetBy`. -func (m Movie) Dispatch(ctx context.Context) { +func (m Movie) Dispatch(ctx iris.Context) { if !m.IsValid() { ctx.NotFound() return diff --git a/mvc/overview/web/views/hello/index.html b/mvc/repository/web/views/hello/index.html similarity index 100% rename from mvc/overview/web/views/hello/index.html rename to mvc/repository/web/views/hello/index.html diff --git a/mvc/overview/web/views/hello/name.html b/mvc/repository/web/views/hello/name.html similarity index 100% rename from mvc/overview/web/views/hello/name.html rename to mvc/repository/web/views/hello/name.html diff --git a/mvc/request-default-values/main.go b/mvc/request-default-values/main.go new file mode 100644 index 00000000..90de0cc7 --- /dev/null +++ b/mvc/request-default-values/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +// https://github.com/kataras/iris/issues/1706 +// When you need that type of logic behind a request input, +// e.g. set default values, the right way to do that is +// to register a request-scoped dependency for that type. +// We have the `Context.ReadQuery(pointer)` +// which you can use to bind a struct value, that value can have default values. +// Here is how you could do that: +func main() { + app := iris.New() + + mvcApp := mvc.New(app) + { + mvcApp.Register(paramsDependency) + + mvcApp.Handle(new(controller)) + } + + // http://localhost:8080/records?phone=random&order_by=DESC + // http://localhost:8080/records?phone=random + app.Listen(":8080") +} + +type params struct { + CallID string `url:"phone"` + ComDir int `url:"dir"` + CaseUserID string `url:"on"` + StartYear int `url:"sy"` + EndYear int `url:"ey"` + OrderBy string `url:"order_by"` + Offset int `url:"offset"` +} + +// As we've read in the previous examples, the paramsDependency +// describes a request-scoped dependency. +// It should accept the iris context (or any previously registered or builtin dependency) +// and it should return the value which will be binded to the +// controller's methods (or fields) - see `GetRecords`. +var paramsDependency = func(ctx iris.Context) params { + p := params{ + OrderBy: "ASC", // default value. + } + // Bind the URL values to the "p": + ctx.ReadQuery(&p) + // Or bind a specific URL value by giving a default value: + // p.OrderBy = ctx.URLParamDefault("order_by", "ASC") + // + // OR make checks for default values after ReadXXX, + // e.g. if p.OrderBy == "" {...} + + /* More options to read a request: + // Bind the JSON request body to the "p": + ctx.ReadJSON(&p) + // Bind the Form to the "p": + ctx.ReadForm(&p) + // Bind any, based on the client's content-type header: + ctx.ReadBody(&p) + // Bind the http requests to a struct value: + ctx.ReadHeader(&h) + */ + + return p +} + +type controller struct{} + +func (c *controller) GetRecords(stru params) string { + return fmt.Sprintf("%#+v\n", stru) +} diff --git a/mvc/session-controller/main.go b/mvc/session-controller/main.go index 5c1bb2ae..953f6e69 100644 --- a/mvc/session-controller/main.go +++ b/mvc/session-controller/main.go @@ -1,28 +1,24 @@ -// +build go1.9 - package main import ( "fmt" "time" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" ) // VisitController handles the root route. type VisitController struct { - // the current request session, - // its initialization happens by the dependency function that we've added to the `visitApp`. + // the current request session, automatically binded. Session *sessions.Session - // A time.time which is binded from the MVC, - // order of binded fields doesn't matter. + // A time.time which is binded from the MVC application manually. StartTime time.Time } -// Get handles +// Get handles index // Method: GET // Path: http://localhost:8080 func (c *VisitController) Get() string { @@ -31,30 +27,20 @@ func (c *VisitController) Get() string { visits := c.Session.Increment("visits", 1) // write the current, updated visits. since := time.Now().Sub(c.StartTime).Seconds() - return fmt.Sprintf("%d visit from my current session in %0.1f seconds of server's up-time", + return fmt.Sprintf("%d visit(s) from my current session in %0.1f seconds of server's up-time", visits, since) } func newApp() *iris.Application { app := iris.New() + // Configure sessions manager as we used to. sess := sessions.New(sessions.Config{Cookie: "mysession_cookie_name"}) + app.Use(sess.Handler()) + + visitApp := mvc.New(app) + visitApp.Register(time.Now()) + // The `VisitController.Session` is automatically binded to the current `sessions.Session`. - visitApp := mvc.New(app.Party("/")) - // bind the current *session.Session, which is required, to the `VisitController.Session` - // and the time.Now() to the `VisitController.StartTime`. - visitApp.Register( - // if dependency is a function which accepts - // a Context and returns a single value - // then the result type of this function is resolved by the controller - // and on each request it will call the function with its Context - // and set the result(the *sessions.Session here) to the controller's field. - // - // If dependencies are registered without field or function's input arguments as - // consumers then those dependencies are being ignored before the server ran, - // so you can bind many dependecies and use them in different controllers. - sess.Start, - time.Now(), - ) visitApp.Handle(new(VisitController)) return app @@ -63,10 +49,10 @@ func newApp() *iris.Application { func main() { app := newApp() - // 1. open the browser (no in private mode) + // 1. Prepare a client, e.g. your browser // 2. navigate to http://localhost:8080 // 3. refresh the page some times // 4. close the browser - // 5. re-open the browser and re-play 2. - app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker) + // 5. re-open the browser (if it wasn't in private mode) and re-play 2. + app.Listen(":8080") } diff --git a/mvc/session-controller/main_test.go b/mvc/session-controller/main_test.go index f8900501..e7ec5929 100644 --- a/mvc/session-controller/main_test.go +++ b/mvc/session-controller/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestMVCSession(t *testing.T) { diff --git a/mvc/singleton/main.go b/mvc/singleton/main.go index 2d087b58..971d2581 100644 --- a/mvc/singleton/main.go +++ b/mvc/singleton/main.go @@ -4,8 +4,8 @@ import ( "fmt" "sync/atomic" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" ) func main() { @@ -13,7 +13,7 @@ func main() { mvc.New(app.Party("/")).Handle(&globalVisitorsController{visits: 0}) // http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } type globalVisitorsController struct { diff --git a/mvc/versioned-controller/main.go b/mvc/versioned-controller/main.go new file mode 100644 index 00000000..56cedb47 --- /dev/null +++ b/mvc/versioned-controller/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +// Optional deprecated X-API-XXX headers for version 1. +var opts = mvc.DeprecationOptions{ + WarnMessage: "deprecated, see <this link>", + DeprecationDate: time.Now().UTC(), + DeprecationInfo: "a bigger version is available, see <this link> for more information", +} + +func main() { + app := newApp() + + // See main_test.go for request examples. + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + dataRouter := app.Party("/data") + { + m := mvc.New(dataRouter) + + m.Handle(new(v1Controller), mvc.Version("1.0.0"), mvc.Deprecated(opts)) + m.Handle(new(v2Controller), mvc.Version("2.3.0")) + m.Handle(new(v3Controller), mvc.Version(">=3.0.0 <4.0.0")) + m.Handle(new(noVersionController)) // or if missing it will respond with 501 version not found. + } + + return app +} + +type v1Controller struct{} + +func (c *v1Controller) Get() string { + return "data (v1.x)" +} + +type v2Controller struct{} + +func (c *v2Controller) Get() string { + return "data (v2.x)" +} + +type v3Controller struct{} + +func (c *v3Controller) Get() string { + return "data (v3.x)" +} + +type noVersionController struct{} + +func (c *noVersionController) Get() string { + return "data" +} diff --git a/mvc/versioned-controller/main_test.go b/mvc/versioned-controller/main_test.go new file mode 100644 index 00000000..a7906104 --- /dev/null +++ b/mvc/versioned-controller/main_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" + "github.com/kataras/iris/v12/versioning" +) + +func TestVersionedController(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + e.GET("/data").WithHeader(versioning.AcceptVersionHeaderKey, "1.0.0").Expect(). + Status(iris.StatusOK).Body().IsEqual("data (v1.x)") + e.GET("/data").WithHeader(versioning.AcceptVersionHeaderKey, "2.3.0").Expect(). + Status(iris.StatusOK).Body().IsEqual("data (v2.x)") + e.GET("/data").WithHeader(versioning.AcceptVersionHeaderKey, "3.1.0").Expect(). + Status(iris.StatusOK).Body().IsEqual("data (v3.x)") + + // Test invalid version or no version at all. + e.GET("/data").WithHeader(versioning.AcceptVersionHeaderKey, "4.0.0").Expect(). + Status(iris.StatusOK).Body().IsEqual("data") + e.GET("/data").Expect(). + Status(iris.StatusOK).Body().IsEqual("data") + + // Test Deprecated (v1) + ex := e.GET("/data").WithHeader(versioning.AcceptVersionHeaderKey, "1.0.0").Expect() + ex.Status(iris.StatusOK).Body().IsEqual("data (v1.x)") + ex.Header("X-API-Warn").Equal(opts.WarnMessage) + expectedDateStr := opts.DeprecationDate.Format(app.ConfigurationReadOnly().GetTimeFormat()) + ex.Header("X-API-Deprecation-Date").Equal(expectedDateStr) +} diff --git a/tutorial/vuejs-todo-mvc/README.md b/mvc/vuejs-todo-mvc/README.md similarity index 75% rename from tutorial/vuejs-todo-mvc/README.md rename to mvc/vuejs-todo-mvc/README.md index 00c912fa..6308a925 100644 --- a/tutorial/vuejs-todo-mvc/README.md +++ b/mvc/vuejs-todo-mvc/README.md @@ -1,5 +1,7 @@ # A Todo MVC Application using Iris and Vue.js +## Hackernoon Article: https://medium.com/hackernoon/a-todo-mvc-application-using-iris-and-vue-js-5019ff870064 + Vue.js is a front-end framework for building web applications using javascript. It has a blazing fast Virtual DOM renderer. Iris is a back-end framework for building web applications using The Go Programming Language (disclaimer: author here). It's one of the fastest and featured web frameworks out there. We wanna use this to serve our "todo service". @@ -27,9 +29,9 @@ Many articles have been written, in the past, that lead developers not to use a You’ll need two dependencies: 1. Vue.js, for our client-side requirements. Download it from [here](https://vuejs.org/), latest v2. -2. The Iris Web Framework, for our server-side requirements. Can be found [here](https://github.com/kataras/iris), latest v10. +2. The Iris Web Framework, for our server-side requirements. Can be found [here](https://github.com/kataras/iris), latest v12. -> If you have Go already installed then just execute `go get -u github.com/kataras/iris` to install the Iris Web Framework. +> If you have Go already installed then just execute `go get github.com/kataras/iris/v12@latest` to install the Iris Web Framework. ## Start @@ -56,15 +58,24 @@ _Read the comments in the source code, they may be very helpful_ // Full spec-compliant TodoMVC with Iris // and hash-based routing in ~200 effective lines of JavaScript. -var socket = new Ws("ws://localhost:8080/todos/sync"); - -socket.On("saved", function () { - // console.log("receive: on saved"); - fetchTodos(function (items) { - app.todos = items - }); -}); +var ws; + +((async () => { + const events = { + todos: { + saved: function (ns, msg) { + app.todos = msg.unmarshal() + // or make a new http fetch + // fetchTodos(function (items) { + // app.todos = msg.unmarshal() + // }); + } + } + }; + const conn = await neffos.dial("ws://localhost:8080/todos/sync", events); + ws = await conn.connect("todos"); +})()).catch(console.error); function fetchTodos(onComplete) { axios.get("/todos").then(response => { @@ -93,7 +104,7 @@ var todoStorage = { return; } // console.log("send: save"); - socket.Emit("save") + ws.emit("save") }); } } @@ -257,7 +268,7 @@ window.addEventListener('hashchange', onHashChange) onHashChange() // mount -app.$mount('.todoapp') +app.$mount('.todoapp'); ``` Let's add our view, the static html. @@ -272,14 +283,13 @@ Let's add our view, the static html. <title>Iris + Vue.js • TodoMVC</title> <link rel="stylesheet" href="https://unpkg.com/todomvc-app-css@2.0.4/index.css"> <!-- this needs to be loaded before guide's inline scripts --> - <script src="https://vuejs.org/js/vue.js"></script> + <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <!-- $http --> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <!-- --> <script src="https://unpkg.com/director@1.2.8/build/director.js"></script> - <!-- websocket sync between multiple tabs --> - <script src="/todos/iris-ws.js"></script> - <!-- --> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> + <style> [v-cloak] { display: none; @@ -291,20 +301,22 @@ Let's add our view, the static html. <section class="todoapp"> <header class="header"> <h1>todos</h1> - <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" @keyup.enter="addTodo"> + <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" + @keyup.enter="addTodo"> </header> <section class="main" v-show="todos.length" v-cloak> <input class="toggle-all" type="checkbox" v-model="allDone"> <ul class="todo-list"> - <li v-for="todo in filteredTodos" class="todo" :key="todo.id" :class="{ completed: todo.completed, editing: todo == editedTodo }"> + <li v-for="todo in filteredTodos" class="todo" :key="todo.id" + :class="{ completed: todo.completed, editing: todo == editedTodo }"> <div class="view"> - <!-- v-model="todo.completed" --> + <!-- v-model="todo.completed" --> <input class="toggle" type="checkbox" @click="completeTodo(todo)"> <label @dblclick="editTodo(todo)">{{ todo.title }}</label> <button class="destroy" @click="removeTodo(todo)"></button> </div> - <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" - @keyup.esc="cancelEdit(todo)"> + <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" + @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> </li> </ul> </section> @@ -409,23 +421,25 @@ func (s *MemoryService) Save(sessionOwner string, newItems []Item) error { We are going to use some of the MVC functionalities of the iris web framework here but you can do the same with the standard API as well. ```go -// file: vuejs-todo-mvc/controllers/todo_controller.go +// file: vuejs-todo-mvc/web/controllers/todo_controller.go package controllers import ( - "vuejs-todo-mvc/todo" + "vuejs-todo-mvc/todo" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/websocket" ) // TodoController is our TODO app's web controller. type TodoController struct { - Service todo.Service + Service todo.Service + + Session *sessions.Session - Session *sessions.Session + NS *websocket.NSConn } // BeforeActivation called once before the server ran, and before @@ -433,44 +447,48 @@ type TodoController struct { // You can bind custom things to the controller, add new methods, add middleware, // add dependencies to the struct or the method(s) and more. func (c *TodoController) BeforeActivation(b mvc.BeforeActivation) { - // this could be binded to a controller's function input argument - // if any, or struct field if any: - b.Dependencies().Add(func(ctx iris.Context) (items []todo.Item) { - ctx.ReadJSON(&items) - return - }) + // this could be binded to a controller's function input argument + // if any, or struct field if any: + b.Dependencies().Add(func(ctx iris.Context) (items []todo.Item) { + ctx.ReadJSON(&items) + return + }) } // Get handles the GET: /todos route. func (c *TodoController) Get() []todo.Item { - return c.Service.Get(c.Session.ID()) + return c.Service.Get(c.Session.ID()) } // PostItemResponse the response data that will be returned as json // after a post save action of all todo items. type PostItemResponse struct { - Success bool `json:"success"` + Success bool `json:"success"` } var emptyResponse = PostItemResponse{Success: false} // Post handles the POST: /todos route. func (c *TodoController) Post(newItems []todo.Item) PostItemResponse { - if err := c.Service.Save(c.Session.ID(), newItems); err != nil { - return emptyResponse - } + if err := c.Service.Save(c.Session.ID(), newItems); err != nil { + return emptyResponse + } - return PostItemResponse{Success: true} + return PostItemResponse{Success: true} } -func (c *TodoController) GetSync(conn websocket.Connection) { - conn.Join(c.Session.ID()) - conn.On("save", func() { // "save" event from client. - conn.To(c.Session.ID()).Emit("saved", nil) // fire a "saved" event to the rest of the clients w. - }) +func (c *TodoController) Save(msg websocket.Message) error { + id := c.Session.ID() + c.NS.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Event: "saved", + To: id, + Body: websocket.Marshal(c.Service.Get(id)), + }) - conn.Wait() + return nil } + ``` And finally our main application's endpoint. @@ -480,57 +498,65 @@ And finally our main application's endpoint. package main import ( - "vuejs-todo-mvc/todo" - "vuejs-todo-mvc/web/controllers" + "strings" - "github.com/kataras/iris" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/todo" + "github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/web/controllers" - "github.com/kataras/iris/mvc" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/websocket" ) func main() { - app := iris.New() - - // serve our app in public, public folder - // contains the client-side vue.js application, - // no need for any server-side template here, - // actually if you're going to just use vue without any - // back-end services, you can just stop afer this line and start the server. - app.StaticWeb("/", "./public") - - // configure the http sessions. - sess := sessions.New(sessions.Config{ - Cookie: "iris_session", - }) - - // configure the websocket server. - ws := websocket.New(websocket.Config{}) - - // create a sub router and register the client-side library for the iris websockets, - // you could skip it but iris websockets supports socket.io-like API. - todosRouter := app.Party("/todos") - // http://localhost:8080/todos/iris-ws.js - // serve the javascript client library to communicate with - // the iris high level websocket event system. - todosRouter.Any("/iris-ws.js", websocket.ClientHandler()) - - // create our mvc application targeted to /todos relative sub path. - todosApp := mvc.New(todosRouter) - - // any dependencies bindings here... - todosApp.Register( - todo.NewMemoryService(), - sess.Start, - ws.Upgrade, - ) - - // controllers registration here... - todosApp.Handle(new(controllers.TodoController)) - - // start the web server at http://localhost:8080 - app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker) + app := iris.New() + + // serve our app in public, public folder + // contains the client-side vue.js application, + // no need for any server-side template here, + // actually if you're going to just use vue without any + // back-end services, you can just stop afer this line and start the server. + app.HandleDir("/", iris.Dir("./public")) + + // configure the http sessions. + sess := sessions.New(sessions.Config{ + Cookie: "iris_session", + }) + + // create a sub router and register the http controllers. + todosRouter := app.Party("/todos") + + // create our mvc application targeted to /todos relative sub path. + todosApp := mvc.New(todosRouter) + + // any dependencies bindings here... + todosApp.Register( + todo.NewMemoryService(), + ) + + todosController := new(controllers.TodoController) + // controllers registration here... + todosApp.Handle(todosController) + + // Create a sub mvc app for websocket controller. + // Inherit the parent's dependencies. + todosWebsocketApp := todosApp.Party("/sync") + todosWebsocketApp.HandleWebsocket(todosController). + SetNamespace("todos"). + SetEventMatcher(func(methodName string) (string, bool) { + return strings.ToLower(methodName), true + }) + + websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, todosWebsocketApp) + idGenerator := func(ctx iris.Context) string { + id := sess.Start(ctx).ID() + return id + } + todosWebsocketApp.Router.Get("/", websocket.Handler(websocketServer, idGenerator)) + + // start the web server at http://localhost:8080 + app.Listen(":8080") } ``` @@ -549,13 +575,13 @@ Open one or more browser tabs at: http://localhost:8080 and have fun! ### Download the Source Code -The whole project, all the files you saw in this article are located at: https://github.com/kataras/iris/tree/master/_examples/tutorial/vuejs-todo-mvc +The whole project, all the files you saw in this article are located at: https://github.com/kataras/iris/tree/main/_examples/mvc/vuejs-todo-mvc ## References https://vuejs.org/v2/examples/todomvc.html (using browser's local storage) -https://github.com/kataras/iris/tree/master/_examples/mvc (mvc examples and features overview repository) +https://github.com/kataras/iris/tree/main/_examples/mvc (mvc examples and features overview repository) ## Thank you, once again diff --git a/tutorial/vuejs-todo-mvc/screen.png b/mvc/vuejs-todo-mvc/screen.png similarity index 100% rename from tutorial/vuejs-todo-mvc/screen.png rename to mvc/vuejs-todo-mvc/screen.png diff --git a/mvc/vuejs-todo-mvc/src/go.mod b/mvc/vuejs-todo-mvc/src/go.mod new file mode 100644 index 00000000..b481f971 --- /dev/null +++ b/mvc/vuejs-todo-mvc/src/go.mod @@ -0,0 +1,62 @@ +module github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src + +go 1.22 + +require github.com/kataras/iris/v12 v12.2.11 + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/mvc/vuejs-todo-mvc/src/go.sum b/mvc/vuejs-todo-mvc/src/go.sum new file mode 100644 index 00000000..f9398280 --- /dev/null +++ b/mvc/vuejs-todo-mvc/src/go.sum @@ -0,0 +1,200 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/tutorial/vuejs-todo-mvc/src/todo/item.go b/mvc/vuejs-todo-mvc/src/todo/item.go similarity index 100% rename from tutorial/vuejs-todo-mvc/src/todo/item.go rename to mvc/vuejs-todo-mvc/src/todo/item.go diff --git a/tutorial/vuejs-todo-mvc/src/todo/service.go b/mvc/vuejs-todo-mvc/src/todo/service.go similarity index 95% rename from tutorial/vuejs-todo-mvc/src/todo/service.go rename to mvc/vuejs-todo-mvc/src/todo/service.go index d9af2854..6f40ce23 100644 --- a/tutorial/vuejs-todo-mvc/src/todo/service.go +++ b/mvc/vuejs-todo-mvc/src/todo/service.go @@ -18,7 +18,7 @@ type MemoryService struct { func NewMemoryService() *MemoryService { return &MemoryService{ - items: make(map[string][]Item, 0), + items: make(map[string][]Item), } } diff --git a/tutorial/vuejs-todo-mvc/src/web/controllers/todo_controller.go b/mvc/vuejs-todo-mvc/src/web/controllers/todo_controller.go similarity index 62% rename from tutorial/vuejs-todo-mvc/src/web/controllers/todo_controller.go rename to mvc/vuejs-todo-mvc/src/web/controllers/todo_controller.go index 74df9643..407b8eef 100644 --- a/tutorial/vuejs-todo-mvc/src/web/controllers/todo_controller.go +++ b/mvc/vuejs-todo-mvc/src/web/controllers/todo_controller.go @@ -1,12 +1,12 @@ package controllers import ( - "github.com/iris-contrib/examples/tutorial/vuejs-todo-mvc/src/todo" + "github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/todo" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/websocket" ) // TodoController is our TODO app's web controller. @@ -14,6 +14,8 @@ type TodoController struct { Service todo.Service Session *sessions.Session + + NS *websocket.NSConn } // BeforeActivation called once before the server ran, and before @@ -23,10 +25,10 @@ type TodoController struct { func (c *TodoController) BeforeActivation(b mvc.BeforeActivation) { // this could be binded to a controller's function input argument // if any, or struct field if any: - b.Dependencies().Add(func(ctx iris.Context) (items []todo.Item) { + b.Dependencies().Register(func(ctx iris.Context) (items []todo.Item) { ctx.ReadJSON(&items) return - }) + }) // Note: from Iris v12.2 these type of dependencies are automatically resolved. } // Get handles the GET: /todos route. @@ -51,15 +53,14 @@ func (c *TodoController) Post(newItems []todo.Item) PostItemResponse { return PostItemResponse{Success: true} } -func (c *TodoController) GetSync(conn websocket.Connection) { - // join to the session in order to send "saved" - // events only to a single user, that means - // that if user has opened more than one browser window/tab - // of the same session then the changes will be reflected to one another. - conn.Join(c.Session.ID()) - conn.On("save", func() { // "save" event from client. - conn.To(c.Session.ID()).Emit("saved", nil) // fire a "saved" event to the rest of the clients w. +func (c *TodoController) Save(msg websocket.Message) error { + id := c.Session.ID() + c.NS.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Event: "saved", + To: id, + Body: websocket.Marshal(c.Service.Get(id)), }) - conn.Wait() + return nil } diff --git a/mvc/vuejs-todo-mvc/src/web/main.go b/mvc/vuejs-todo-mvc/src/web/main.go new file mode 100644 index 00000000..ba653a80 --- /dev/null +++ b/mvc/vuejs-todo-mvc/src/web/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "strings" + + "github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/todo" + "github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/web/controllers" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/websocket" +) + +func main() { + app := iris.New() + + // serve our app in public, public folder + // contains the client-side vue.js application, + // no need for any server-side template here, + // actually if you're going to just use vue without any + // back-end services, you can just stop afer this line and start the server. + app.HandleDir("/", iris.Dir("./public")) + + // configure the http sessions. + sess := sessions.New(sessions.Config{ + Cookie: "iris_session", + }) + + // create a sub router and register the http controllers. + todosRouter := app.Party("/todos") + + // Register sessions handler. + // TodoController.Session will automatically + // filled with the current request's session. + todosRouter.Use(sess.Handler()) + + // create our mvc application targeted to /todos relative sub path. + todosApp := mvc.New(todosRouter) + + // any dependencies bindings here... + todosApp.Register( + todo.NewMemoryService(), + ) + + todosController := new(controllers.TodoController) + // controllers registration here... + todosApp.Handle(todosController) + + // Create a sub mvc app for websocket controller. + // Inherit the parent's dependencies. + todosWebsocketApp := todosApp.Party("/sync") + todosWebsocketApp.HandleWebsocket(todosController). + SetNamespace("todos"). + SetEventMatcher(func(methodName string) (string, bool) { + return strings.ToLower(methodName), true + }) + + websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, todosWebsocketApp) + idGenerator := func(ctx iris.Context) string { + id := sess.Start(ctx).ID() + return id + } + todosWebsocketApp.Router.Get("/", websocket.Handler(websocketServer, idGenerator)) + + // start the web server at http://localhost:8080 + app.Listen(":8080") +} diff --git a/tutorial/vuejs-todo-mvc/src/web/public/css/index b/mvc/vuejs-todo-mvc/src/web/public/css/index similarity index 100% rename from tutorial/vuejs-todo-mvc/src/web/public/css/index rename to mvc/vuejs-todo-mvc/src/web/public/css/index diff --git a/tutorial/vuejs-todo-mvc/src/web/public/index.html b/mvc/vuejs-todo-mvc/src/web/public/index.html similarity index 80% rename from tutorial/vuejs-todo-mvc/src/web/public/index.html rename to mvc/vuejs-todo-mvc/src/web/public/index.html index 38cca166..0f2a7157 100644 --- a/tutorial/vuejs-todo-mvc/src/web/public/index.html +++ b/mvc/vuejs-todo-mvc/src/web/public/index.html @@ -6,14 +6,13 @@ <title>Iris + Vue.js • TodoMVC</title> <link rel="stylesheet" href="https://unpkg.com/todomvc-app-css@2.0.4/index.css"> <!-- this needs to be loaded before guide's inline scripts --> - <script src="https://vuejs.org/js/vue.js"></script> + <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <!-- $http --> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <!-- --> <script src="https://unpkg.com/director@1.2.8/build/director.js"></script> - <!-- websocket sync between multiple tabs --> - <script src="/todos/iris-ws.js"></script> - <!-- --> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> + <style> [v-cloak] { display: none; @@ -25,20 +24,22 @@ <section class="todoapp"> <header class="header"> <h1>todos</h1> - <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" @keyup.enter="addTodo"> + <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" + @keyup.enter="addTodo"> </header> <section class="main" v-show="todos.length" v-cloak> <input class="toggle-all" type="checkbox" v-model="allDone"> <ul class="todo-list"> - <li v-for="todo in filteredTodos" class="todo" :key="todo.id" :class="{ completed: todo.completed, editing: todo == editedTodo }"> + <li v-for="todo in filteredTodos" class="todo" :key="todo.id" + :class="{ completed: todo.completed, editing: todo == editedTodo }"> <div class="view"> - <!-- v-model="todo.completed" --> + <!-- v-model="todo.completed" --> <input class="toggle" type="checkbox" @click="completeTodo(todo)"> <label @dblclick="editTodo(todo)">{{ todo.title }}</label> <button class="destroy" @click="removeTodo(todo)"></button> </div> - <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" - @keyup.esc="cancelEdit(todo)"> + <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" + @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)"> </li> </ul> </section> diff --git a/tutorial/vuejs-todo-mvc/src/web/public/js/app.js b/mvc/vuejs-todo-mvc/src/web/public/js/app.js similarity index 90% rename from tutorial/vuejs-todo-mvc/src/web/public/js/app.js rename to mvc/vuejs-todo-mvc/src/web/public/js/app.js index ab30eee8..fcc0863d 100644 --- a/tutorial/vuejs-todo-mvc/src/web/public/js/app.js +++ b/mvc/vuejs-todo-mvc/src/web/public/js/app.js @@ -1,15 +1,24 @@ // Full spec-compliant TodoMVC with Iris // and hash-based routing in ~200 effective lines of JavaScript. -var socket = new Ws("ws://localhost:8080/todos/sync"); - -socket.On("saved", function () { - // console.log("receive: on saved"); - fetchTodos(function (items) { - app.todos = items - }); -}); +var ws; + +((async () => { + const events = { + todos: { + saved: function (ns, msg) { + app.todos = msg.unmarshal() + // or make a new http fetch + // fetchTodos(function (items) { + // app.todos = msg.unmarshal() + // }); + } + } + }; + const conn = await neffos.dial("ws://localhost:8080/todos/sync", events); + ws = await conn.connect("todos"); +})()).catch(console.error); function fetchTodos(onComplete) { axios.get("/todos").then(response => { @@ -38,7 +47,7 @@ var todoStorage = { return; } // console.log("send: save"); - socket.Emit("save") + ws.emit("save") }); } } @@ -202,4 +211,4 @@ window.addEventListener('hashchange', onHashChange) onHashChange() // mount -app.$mount('.todoapp') \ No newline at end of file +app.$mount('.todoapp'); \ No newline at end of file diff --git a/mvc/vuejs-todo-mvc/src/web/public/js/lib/.gitkeep b/mvc/vuejs-todo-mvc/src/web/public/js/lib/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mvc/web_mvc_diagram.png b/mvc/web_mvc_diagram.png deleted file mode 100644 index 7d795683..00000000 Binary files a/mvc/web_mvc_diagram.png and /dev/null differ diff --git a/mvc/websocket-auth/auth.yml b/mvc/websocket-auth/auth.yml new file mode 100644 index 00000000..9cfed272 --- /dev/null +++ b/mvc/websocket-auth/auth.yml @@ -0,0 +1,36 @@ +Headers: # required. + - "Authorization" + - "X-Authorization" +Cookie: # optional. + Name: "iris_auth_cookie" + Secure: false + Hash: "D*G-KaPdSgUkXp2s5v8y/B?E(H+MbQeThWmYq3t6w9z$C&F)J@NcRfUjXn2r4u7x" # length of 64 characters (512-bit). + Block: "VkYp3s6v9y$B&E)H@McQfTjWmZq4t7w!" # length of 32 characters (256-bit). +Keys: + - ID: IRIS_AUTH_ACCESS # required. + Alg: EdDSA + MaxAge: 2h # 2 hours lifetime for access tokens. + Private: |+ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIFdZWoDdFny5SMnP9Fyfr8bafi/B527EVZh8JJjDTIFO + -----END PRIVATE KEY----- + Public: |+ + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAzpgjKSr9E032DX+foiOxq1QDsbzjLxagTN+yVpGWZB4= + -----END PUBLIC KEY----- + - ID: IRIS_AUTH_REFRESH # optional. Good practise to have it though. + Alg: EdDSA + # 1 month lifetime for refresh tokens, + # after that period the user has to signin again. + MaxAge: 720h + Private: |+ + -----BEGIN PRIVATE KEY----- + MC4CAQAwBQYDK2VwBCIEIHJ1aoIjA2sRp5eqGjGR3/UMucrHbBdBv9p8uwfzZ1KZ + -----END PRIVATE KEY----- + Public: |+ + -----BEGIN PUBLIC KEY----- + MCowBQYDK2VwAyEAsKKAr+kDtfAqwG7cZdoEAfh9jHt9W8qi9ur5AA1KQAQ= + -----END PUBLIC KEY----- + # Example of setting a binary form of the encryption key for refresh tokens, + # it could be a "string" as well. + EncryptionKey: !!binary stSNLTu91YyihPxzeEOXKwGVMG00CjcC/68G8nMgmqA= diff --git a/mvc/websocket-auth/browser/index.html b/mvc/websocket-auth/browser/index.html new file mode 100644 index 00000000..bd7c5032 --- /dev/null +++ b/mvc/websocket-auth/browser/index.html @@ -0,0 +1,106 @@ +<html> + +<head> + <title>Online visitors MVC example</title> + <style> + body { + margin: 0; + font-family: -apple-system, "San Francisco", "Helvetica Neue", "Noto", "Roboto", "Calibri Light", sans-serif; + color: #212121; + font-size: 1.0em; + line-height: 1.6; + } + + .container { + max-width: 750px; + margin: auto; + padding: 15px; + } + + #online_visitors { + font-weight: bold; + font-size: 18px; + } + </style> +</head> + +<body> + <div class="container"> + <span id="online_visitors">1 online visitor</span> + </div> + + <!-- the message's input --> + <input id="input" type="text" /> + + <!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' --> + <button id="sendBtn" disabled>Send</button> + + <!-- the messages will be shown here --> + <pre id="output"></pre> + <!-- import the iris client-side library for browser from a CDN or locally. + However, `neffos.(min.)js` is a NPM package too so alternatively, + you can use it as dependency on your package.json and all nodejs-npm tooling become available: + see the "browserify" example for more--> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> + <script type="text/javascript"> + const wsURL = "ws://localhost:8080/protected/ws" + var outputTxt = document.getElementById("output"); + function addMessage(msg) { + outputTxt.innerHTML += msg + "\n"; + } + + async function runExample() { + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: function (nsConn, msg) { + if (nsConn.conn.wasReconnected()) { + addMessage("re-connected after " + nsConn.conn.reconnectTries.toString() + " trie(s)"); + } + + let inputTxt = document.getElementById("input"); + let sendBtn = document.getElementById("sendBtn"); + + sendBtn.disabled = false; + sendBtn.onclick = function () { + const input = inputTxt.value; + inputTxt.value = ""; + nsConn.emit("OnChat", input); + addMessage("Me: " + input); + }; + + addMessage("connected to namespace: " + msg.Namespace); + }, + _OnNamespaceDisconnect: function (nsConn, msg) { + addMessage("disconnected from namespace: " + msg.Namespace); + }, + OnChat: function (nsConn, msg) { // "OnChat" event. + console.log(msg); + + addMessage(msg.Body); + }, + OnVisit: function (nsConn, msg) { + const newCount = Number(msg.Body); // or parseInt. + console.log("visit websocket event with newCount of: ", newCount); + + var text = "1 online visitor"; + if (newCount > 1) { + text = newCount + " online visitors"; + } + document.getElementById("online_visitors").innerHTML = text; + }, + } + }); + + conn.connect("default"); + } catch (err) { + console.log(err) + } + } + + runExample(); + </script> + +</body> + +</html> \ No newline at end of file diff --git a/mvc/websocket-auth/main.go b/mvc/websocket-auth/main.go new file mode 100644 index 00000000..8dcd0cf9 --- /dev/null +++ b/mvc/websocket-auth/main.go @@ -0,0 +1,76 @@ +//go:build go1.18 +// +build go1.18 + +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/auth" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/websocket" +) + +// $ go run . +func main() { + app := newApp() + + // http://localhost:8080/signin (creds: kataras2006@hotmail.com 123456) + // http://localhost:8080/protected + // http://localhost:8080/signout + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + // Auth part. + app.RegisterView(iris.Blocks("./views", ".html"). + LayoutDir("layouts"). + Layout("main")) + + s := auth.MustLoad[User]("./auth.yml") + s.AddProvider(NewProvider()) + + app.Get("/signin", renderSigninForm) + app.Post("/signin", s.SigninHandler) + app.Get("/signout", s.SignoutHandler) + // + + websocketAPI := app.Party("/protected") + websocketAPI.Use(s.VerifyHandler()) + websocketAPI.HandleDir("/", iris.Dir("./browser")) // render the ./browser/index.html. + + websocketMVC := mvc.New(websocketAPI) + websocketMVC.HandleWebsocket(new(websocketController)) + websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, websocketMVC) + websocketAPI.Get("/ws", s.VerifyHandler() /* optional */, websocket.Handler(websocketServer)) + + return app +} + +func renderSigninForm(ctx iris.Context) { + if err := ctx.View("signin", iris.Map{"Title": "Signin Page"}); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +type websocketController struct { + *websocket.NSConn `stateless:"true"` +} + +func (c *websocketController) Namespace() string { + return "default" +} + +func (c *websocketController) OnChat(msg websocket.Message) error { + ctx := websocket.GetContext(c.Conn) + user := auth.GetUser[User](ctx) + + msg.Body = []byte(fmt.Sprintf("%s: %s", user.Email, string(msg.Body))) + c.Conn.Server().Broadcast(c, msg) + + return nil +} diff --git a/mvc/websocket-auth/user.go b/mvc/websocket-auth/user.go new file mode 100644 index 00000000..f4f65ea4 --- /dev/null +++ b/mvc/websocket-auth/user.go @@ -0,0 +1,34 @@ +//go:build go1.18 +// +build go1.18 + +package main + +type AccessRole uint16 + +func (r AccessRole) Is(v AccessRole) bool { + return r&v != 0 +} + +func (r AccessRole) Allow(v AccessRole) bool { + return r&v >= v +} + +const ( + InvalidAccessRole AccessRole = 1 << iota + Read + Write + Delete + + Owner = Read | Write | Delete + Member = Read | Write +) + +type User struct { + ID string `json:"id"` + Email string `json:"email"` + Role AccessRole `json:"role"` +} + +func (u User) GetID() string { + return u.ID +} diff --git a/mvc/websocket-auth/user_provider.go b/mvc/websocket-auth/user_provider.go new file mode 100644 index 00000000..cf1d9ae1 --- /dev/null +++ b/mvc/websocket-auth/user_provider.go @@ -0,0 +1,101 @@ +//go:build go1.18 +// +build go1.18 + +package main + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/kataras/iris/v12/auth" +) + +type Provider struct { + dataset []User + + invalidated map[string]struct{} // key = token. Entry is blocked. + invalidatedAll map[string]int64 // key = user id, value = timestamp. Issued before is consider invalid. + mu sync.RWMutex +} + +func NewProvider() *Provider { + return &Provider{ + dataset: []User{ + { + ID: "id-1", + Email: "kataras2006@hotmail.com", + Role: Owner, + }, + { + ID: "id-2", + Email: "example@example.com", + Role: Member, + }, + }, + invalidated: make(map[string]struct{}), + invalidatedAll: make(map[string]int64), + } +} + +func (p *Provider) Signin(ctx context.Context, username, password string) (User, error) { // fired on SigninHandler. + // your database... + for _, user := range p.dataset { + if user.Email == username { + return user, nil + } + } + + return User{}, fmt.Errorf("user not found") +} + +func (p *Provider) ValidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on VerifyHandler. + // your database and checks of blocked tokens... + + // check for specific token ids. + p.mu.RLock() + _, tokenBlocked := p.invalidated[standardClaims.ID] + if !tokenBlocked { + // this will disallow refresh tokens with issuer as the blocked access token as well. + if standardClaims.Issuer != "" { + _, tokenBlocked = p.invalidated[standardClaims.Issuer] + } + } + p.mu.RUnlock() + + if tokenBlocked { + return fmt.Errorf("token was invalidated") + } + // + + // check all tokens issuet before the "InvalidateToken" method was fired for this user. + p.mu.RLock() + ts, oldUserBlocked := p.invalidatedAll[u.ID] + p.mu.RUnlock() + + if oldUserBlocked && standardClaims.IssuedAt <= ts { + return fmt.Errorf("token was invalidated") + } + // + + return nil // else valid. +} + +func (p *Provider) InvalidateToken(ctx context.Context, standardClaims auth.StandardClaims, u User) error { // fired on SignoutHandler. + // invalidate this specific token. + p.mu.Lock() + p.invalidated[standardClaims.ID] = struct{}{} + p.mu.Unlock() + + return nil +} + +func (p *Provider) InvalidateTokens(ctx context.Context, u User) error { // fired on SignoutAllHandler. + // invalidate all previous tokens came from "u". + p.mu.Lock() + p.invalidatedAll[u.ID] = time.Now().Unix() + p.mu.Unlock() + + return nil +} diff --git a/mvc/websocket-auth/views/layouts/main.html b/mvc/websocket-auth/views/layouts/main.html new file mode 100644 index 00000000..b44c3648 --- /dev/null +++ b/mvc/websocket-auth/views/layouts/main.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{ if .Title }}{{ .Title }}{{ else }}Default Main Title{{ end }}</title> +</head> +<style> + body { + margin: 0; + display: flex; + min-height: 100vh; + flex-direction: column; + } + main { + display: block; + flex: 1 0 auto; + } + .container { + max-width: 500px; + margin: auto; + } +</style> +<body> + <div class="container"> + <main>{{ template "content" . }}</main> + <footer style="position: fixed; bottom: 0; width: 100%;">{{ partial "partials/footer" . }}</footer> + </div> +</body> +</html> \ No newline at end of file diff --git a/mvc/websocket-auth/views/partials/footer.html b/mvc/websocket-auth/views/partials/footer.html new file mode 100644 index 00000000..ac94be3d --- /dev/null +++ b/mvc/websocket-auth/views/partials/footer.html @@ -0,0 +1 @@ +<i>Iris Web Framework © 2023</i> \ No newline at end of file diff --git a/mvc/websocket-auth/views/signin.html b/mvc/websocket-auth/views/signin.html new file mode 100644 index 00000000..57f7514c --- /dev/null +++ b/mvc/websocket-auth/views/signin.html @@ -0,0 +1,9 @@ +<div class="user_signin"> + <form action="" method="post"> + <label for="username">Email:</label> + <input name="username" type="email" /> + <label for="password">Password:</label> + <input name="password" type="password" /> + <input type="submit" value="Sign in" /> + </form> +</div> \ No newline at end of file diff --git a/mvc/websocket/browser/index.html b/mvc/websocket/browser/index.html new file mode 100644 index 00000000..d21c7e24 --- /dev/null +++ b/mvc/websocket/browser/index.html @@ -0,0 +1,106 @@ +<html> + +<head> + <title>Online visitors MVC example</title> + <style> + body { + margin: 0; + font-family: -apple-system, "San Francisco", "Helvetica Neue", "Noto", "Roboto", "Calibri Light", sans-serif; + color: #212121; + font-size: 1.0em; + line-height: 1.6; + } + + .container { + max-width: 750px; + margin: auto; + padding: 15px; + } + + #online_visitors { + font-weight: bold; + font-size: 18px; + } + </style> +</head> + +<body> + <div class="container"> + <span id="online_visitors">1 online visitor</span> + </div> + + <!-- the message's input --> + <input id="input" type="text" /> + + <!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' --> + <button id="sendBtn" disabled>Send</button> + + <!-- the messages will be shown here --> + <pre id="output"></pre> + <!-- import the iris client-side library for browser from a CDN or locally. + However, `neffos.(min.)js` is a NPM package too so alternatively, + you can use it as dependency on your package.json and all nodejs-npm tooling become available: + see the "browserify" example for more--> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> + <script type="text/javascript"> + const wsURL = "ws://localhost:8080/websocket" + var outputTxt = document.getElementById("output"); + function addMessage(msg) { + outputTxt.innerHTML += msg + "\n"; + } + + async function runExample() { + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: function (nsConn, msg) { + if (nsConn.conn.wasReconnected()) { + addMessage("re-connected after " + nsConn.conn.reconnectTries.toString() + " trie(s)"); + } + + let inputTxt = document.getElementById("input"); + let sendBtn = document.getElementById("sendBtn"); + + sendBtn.disabled = false; + sendBtn.onclick = function () { + const input = inputTxt.value; + inputTxt.value = ""; + nsConn.emit("OnChat", input); + addMessage("Me: " + input); + }; + + addMessage("connected to namespace: " + msg.Namespace); + }, + _OnNamespaceDisconnect: function (nsConn, msg) { + addMessage("disconnected from namespace: " + msg.Namespace); + }, + OnChat: function (nsConn, msg) { // "OnChat" event. + console.log(msg); + + addMessage(msg.Body); + }, + OnVisit: function (nsConn, msg) { + const newCount = Number(msg.Body); // or parseInt. + console.log("visit websocket event with newCount of: ", newCount); + + var text = "1 online visitor"; + if (newCount > 1) { + text = newCount + " online visitors"; + } + document.getElementById("online_visitors").innerHTML = text; + }, + } + }); + + conn.connect("default"); + } catch (err) { + console.log(err) + } + } + + runExample(); + </script> + +</body> + +</html> \ No newline at end of file diff --git a/mvc/websocket/main.go b/mvc/websocket/main.go index c94ec5f9..71076016 100644 --- a/mvc/websocket/main.go +++ b/mvc/websocket/main.go @@ -1,39 +1,37 @@ package main import ( + "fmt" "sync/atomic" - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" + "github.com/kataras/iris/v12/websocket" ) func main() { app := iris.New() + app.Logger().SetLevel("debug") + // load templates. - app.RegisterView(iris.HTML("./views", ".html")) + // app.RegisterView(iris.HTML("./views", ".html")) - // render the ./views/index.html. - app.Get("/", func(ctx iris.Context) { - ctx.View("index.html") - }) + // render the ./browser/index.html. + app.HandleDir("/", iris.Dir("./browser")) - mvc.Configure(app.Party("/websocket"), configureMVC) - // Or mvc.New(app.Party(...)).Configure(configureMVC) + websocketAPI := app.Party("/websocket") - // http://localhost:8080 - app.Run(iris.Addr(":8080")) -} + m := mvc.New(websocketAPI) + m.Register( + &prefixedLogger{prefix: "DEV"}, + ) + m.HandleWebsocket(&websocketController{Namespace: "default", Age: 42, Otherstring: "other string"}) -func configureMVC(m *mvc.Application) { - ws := websocket.New(websocket.Config{}) - // http://localhost:8080/websocket/iris-ws.js - m.Router.Any("/iris-ws.js", websocket.ClientHandler()) + websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, m) - // This will bind the result of ws.Upgrade which is a websocket.Connection - // to the controller(s) served by the `m.Handle`. - m.Register(ws.Upgrade) - m.Handle(new(websocketController)) + websocketAPI.Get("/", websocket.Handler(websocketServer)) + // http://localhost:8080 + app.Listen(":8080") } var visits uint64 @@ -47,36 +45,74 @@ func decrement() uint64 { } type websocketController struct { - // Note that you could use an anonymous field as well, it doesn't matter, binder will find it. - // - // This is the current websocket connection, each client has its own instance of the *websocketController. - Conn websocket.Connection + *websocket.NSConn `stateless:"true"` + Namespace string + Age int + Otherstring string + + Logger LoggerService } -func (c *websocketController) onLeave(roomName string) { +// or +// func (c *websocketController) Namespace() string { +// return "default" +// } + +func (c *websocketController) OnNamespaceDisconnect(msg websocket.Message) error { + c.Logger.Log("Disconnected") // visits-- newCount := decrement() - // This will call the "visit" event on all clients, except the current one, + // This will call the "OnVisit" event on all clients, except the current one, // (it can't because it's left but for any case use this type of design) - c.Conn.To(websocket.Broadcast).Emit("visit", newCount) + c.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Event: "OnVisit", + Body: []byte(fmt.Sprintf("%d", newCount)), + }) + + return nil } -func (c *websocketController) update() { +func (c *websocketController) OnNamespaceConnected(msg websocket.Message) error { + // println("Broadcast prefix is: " + c.BroadcastPrefix) + c.Logger.Log("Connected") + // visits++ newCount := increment() - // This will call the "visit" event on all clients, including the current + // This will call the "OnVisit" event on all clients, including the current one, // with the 'newCount' variable. // // There are many ways that u can do it and faster, for example u can just send a new visitor // and client can increment itself, but here we are just "showcasing" the websocket controller. - c.Conn.To(websocket.All).Emit("visit", newCount) + c.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Event: "OnVisit", + Body: []byte(fmt.Sprintf("%d", newCount)), + }) + + return nil +} + +func (c *websocketController) OnChat(msg websocket.Message) error { + ctx := websocket.GetContext(c.Conn) + + ctx.Application().Logger().Infof("[IP: %s] [ID: %s] broadcast to other clients the message [%s]", + ctx.RemoteAddr(), c, string(msg.Body)) + + c.Conn.Server().Broadcast(c, msg) + + return nil } -func (c *websocketController) Get( /* websocket.Connection could be lived here as well, it doesn't matter */ ) { - c.Conn.OnLeave(c.onLeave) - c.Conn.On("visit", c.update) +type LoggerService interface { + Log(string) +} + +type prefixedLogger struct { + prefix string +} - // call it after all event callbacks registration. - c.Conn.Wait() +func (s *prefixedLogger) Log(msg string) { + fmt.Printf("%s: %s\n", s.prefix, msg) } diff --git a/mvc/websocket/views/index.html b/mvc/websocket/views/index.html deleted file mode 100644 index ecedcff2..00000000 --- a/mvc/websocket/views/index.html +++ /dev/null @@ -1,63 +0,0 @@ -<html> - -<head> - <title>Online visitors MVC example</title> - <style> - body { - margin: 0; - font-family: -apple-system, "San Francisco", "Helvetica Neue", "Noto", "Roboto", "Calibri Light", sans-serif; - color: #212121; - font-size: 1.0em; - line-height: 1.6; - } - - .container { - max-width: 750px; - margin: auto; - padding: 15px; - } - - #online_visitors { - font-weight: bold; - font-size: 18px; - } - </style> -</head> - -<body> - <div class="container"> - <span id="online_visitors">1 online visitor</span> - </div> - - <script src="/websocket/iris-ws.js"></script> - - <script type="text/javascript"> - (function () { - var socket = new Ws("ws://localhost:8080/websocket"); - - socket.OnConnect(function(){ - // update the rest of connected clients, including "myself" when "my" connection is 100% ready. - socket.Emit("visit"); - }); - - - socket.On("visit", function (newCount) { - console.log("visit websocket event with newCount of: ", newCount); - - var text = "1 online visitor"; - if (newCount > 1) { - text = newCount + " online visitors"; - } - document.getElementById("online_visitors").innerHTML = text; - }); - - socket.OnDisconnect(function () { - document.getElementById("online_visitors").innerHTML = "you've been disconnected"; - }); - - })(); - </script> - -</body> - -</html> \ No newline at end of file diff --git a/orm/xorm/main.go b/orm/xorm/main.go deleted file mode 100644 index c8c3e08a..00000000 --- a/orm/xorm/main.go +++ /dev/null @@ -1,74 +0,0 @@ -// Package main shows how an orm can be used within your web app -// it just inserts a column and select the first. -package main - -import ( - "time" - - "github.com/kataras/iris" - - "github.com/go-xorm/xorm" - _ "github.com/mattn/go-sqlite3" -) - -/* - go get -u github.com/mattn/go-sqlite3 - go get -u github.com/go-xorm/xorm - - If you're on win64 and you can't install go-sqlite3: - 1. Download: https://sourceforge.net/projects/mingw-w64/files/latest/download - 2. Select "x86_x64" and "posix" - 3. Add C:\Program Files\mingw-w64\x86_64-7.1.0-posix-seh-rt_v5-rev1\mingw64\bin - to your PATH env variable. - - Docs: http://xorm.io/docs/ -*/ - -// User is our user table structure. -type User struct { - ID int64 // auto-increment by-default by xorm - Version string `xorm:"varchar(200)"` - Salt string - Username string - Password string `xorm:"varchar(200)"` - Languages string `xorm:"varchar(200)"` - CreatedAt time.Time `xorm:"created"` - UpdatedAt time.Time `xorm:"updated"` -} - -func main() { - app := iris.New() - - orm, err := xorm.NewEngine("sqlite3", "./test.db") - if err != nil { - app.Logger().Fatalf("orm failed to initialized: %v", err) - } - - iris.RegisterOnInterrupt(func() { - orm.Close() - }) - - err = orm.Sync2(new(User)) - - if err != nil { - app.Logger().Fatalf("orm failed to initialized User table: %v", err) - } - - app.Get("/insert", func(ctx iris.Context) { - user := &User{Username: "kataras", Salt: "hash---", Password: "hashed", CreatedAt: time.Now(), UpdatedAt: time.Now()} - orm.Insert(user) - - ctx.Writef("user inserted: %#v", user) - }) - - app.Get("/get", func(ctx iris.Context) { - user := User{ID: 1} - if ok, _ := orm.Get(&user); ok { - ctx.Writef("user found: %#v", user) - } - }) - - // http://localhost:8080/insert - // http://localhost:8080/get - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) -} diff --git a/miscellaneous/pprof/main.go b/pprof/main.go similarity index 53% rename from miscellaneous/pprof/main.go rename to pprof/main.go index 2b2a79e9..47705503 100644 --- a/miscellaneous/pprof/main.go +++ b/pprof/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/middleware/pprof" + "github.com/kataras/iris/v12/middleware/pprof" ) func main() { @@ -13,7 +13,9 @@ func main() { ctx.HTML("<h1> Please click <a href='/debug/pprof'>here</a>") }) - app.Any("/debug/pprof/{action:path}", pprof.New()) + p := pprof.New() + app.Any("/debug/pprof", p) + app.Any("/debug/pprof/{action:path}", p) // ___________ - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/project/README.md b/project/README.md new file mode 100644 index 00000000..634af157 --- /dev/null +++ b/project/README.md @@ -0,0 +1,5 @@ +# Project Structure + +```sh +$ go run main.go --config=server.yml +``` \ No newline at end of file diff --git a/project/api/configuration.go b/project/api/configuration.go new file mode 100644 index 00000000..3acff670 --- /dev/null +++ b/project/api/configuration.go @@ -0,0 +1,45 @@ +package api + +import ( + "os" + + "github.com/kataras/iris/v12" + + "gopkg.in/yaml.v3" +) + +// Configuration holds the necessary information +// for our server, including the Iris one. +type Configuration struct { + ServerName string `yaml:"ServerName"` + Env string `yaml:"Env"` + // The server's host, if empty, defaults to 0.0.0.0 + Host string `yaml:"Host"` + // The server's port, e.g. 80 + Port int `yaml:"Port"` + // If not empty runs under tls with this domain using letsencrypt. + Domain string `yaml:"Domain"` + // Enables write response and read request compression. + EnableCompression bool `yaml:"EnableCompression"` + // Defines the "Access-Control-Allow-Origin" header of the CORS middleware. + // Many can be separated by comma. + // Defaults to "*" (allow all). + AllowOrigin string `yaml:"AllowOrigin"` + // If not empty a request logger is registered, + // note that this will cost a lot in performance, use it only for debug. + RequestLog string `yaml:"RequestLog"` + // The database connection string. + ConnString string `yaml:"ConnString"` + // Iris specific configuration. + Iris iris.Configuration `yaml:"Iris"` +} + +// BindFile binds the yaml file's contents to this Configuration. +func (c *Configuration) BindFile(filename string) error { + contents, err := os.ReadFile(filename) + if err != nil { + return err + } + + return yaml.Unmarshal(contents, c) +} diff --git a/project/api/router.go b/project/api/router.go new file mode 100644 index 00000000..5b3d718a --- /dev/null +++ b/project/api/router.go @@ -0,0 +1,31 @@ +package api + +import ( + "time" + + "github.com/username/project/api/users" + "github.com/username/project/pkg/database" + "github.com/username/project/user" + + "github.com/kataras/iris/v12/middleware/modrevision" +) + +// buildRouter is the most important part of your server. +// All root endpoints are registered here. +func (srv *Server) buildRouter() { + // Add a simple health route. + srv.Any("/health", modrevision.New(modrevision.Options{ + ServerName: srv.config.ServerName, + Env: srv.config.Env, + Developer: "kataras", + TimeLocation: time.FixedZone("Greece/Athens", 7200), + })) + + api := srv.Party("/api") + api.RegisterDependency( + database.Open(srv.config.ConnString), + user.NewRepository, + ) + + api.PartyConfigure("/user", new(users.API)) +} diff --git a/project/api/server.go b/project/api/server.go new file mode 100644 index 00000000..42b45bb0 --- /dev/null +++ b/project/api/server.go @@ -0,0 +1,165 @@ +package api + +import ( + "context" + "fmt" + "time" + + "github.com/username/project/pkg/http/handlers" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/accesslog" + + "github.com/kataras/golog" +) + +// Server is a wrapper of the main iris application and our project's custom configuration fields. +type Server struct { + *iris.Application + config Configuration + + // Here you can keep an instance of the database too. + // db *mydatabase_pkg.DB + closers []func() // See `AddCloser` method. +} + +// NewServer initializes a new HTTP/2 server. +// Use its Run/Listen methods to start it based on network options. +func NewServer(c Configuration) *Server { + app := iris.New().SetName(c.ServerName) + app.Configure(iris.WithConfiguration(c.Iris), iris.WithLowercaseRouting) + + srv := &Server{ + Application: app, + config: c, + } + + if err := srv.prepare(); err != nil { + srv.Logger().Fatal(err) + return nil + } + + return srv +} + +func (srv *Server) prepare() error { + // Here you can register the database instance + // and prepare any project-relative fields. + + if srv.Logger().Level == golog.DebugLevel { + srv.registerDebugFeatures() + } + + srv.registerMiddlewares() + srv.buildRouter() + return nil +} + +// registers application-level middlewares. +func (srv *Server) registerMiddlewares() { + if srv.config.RequestLog != "" { + srv.registerAccessLogger() + } + + srv.UseRouter(handlers.CORS(srv.config.AllowOrigin)) + + if srv.config.EnableCompression { + srv.Use(iris.Compression) + } +} + +func (srv *Server) registerDebugFeatures() {} + +func (srv *Server) registerAccessLogger() { + // Initialize a new request access log middleware, + // note that we use unbuffered data so we can have the results as fast as possible, + // this has its cost use it only on debug. + // Also, in the future see the iris example to + // enable log rotation (date eand filesize-based files). + ac := accesslog.FileUnbuffered(srv.config.RequestLog) + + // The default configuration: + ac.Delim = '|' + ac.TimeFormat = "2006-01-02 15:04:05" + ac.Async = false + ac.IP = true + ac.BytesReceivedBody = true + ac.BytesSentBody = true + ac.BytesReceived = false + ac.BytesSent = false + ac.BodyMinify = false + ac.RequestBody = true + ac.ResponseBody = false + ac.KeepMultiLineError = true + ac.PanicLog = accesslog.LogHandler + + // Default line format if formatter is missing: + // Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response| + // + // Set Custom Formatter: + ac.SetFormatter(&accesslog.JSON{ + Indent: " ", + HumanTime: true, + }) + + // ac.SetFormatter(&accesslog.CSV{}) + // ac.SetFormatter(&accesslog.Template{Text: "{{.Code}}"}) + + srv.UseRouter(ac.Handler) +} + +// Start runs the server on the TCP network address "0.0.0.0:port" which +// handles HTTP/1.1 & 2 requests on incoming connections. +func (srv *Server) Start() error { + if srv.config.Domain != "" { + srv.config.Port = 80 // not required but let's force-modify it. + return srv.Application.Run(iris.AutoTLS( + ":443", + srv.config.Domain, + "kataras2006@hotmail.com", + )) + } + + srv.ConfigureHost(func(su *iris.Supervisor) { + // Set timeouts. More than enough, normally we use 20-30 seconds. + su.Server.ReadTimeout = 5 * time.Minute + su.Server.WriteTimeout = 5 * time.Minute + su.Server.IdleTimeout = 10 * time.Minute + su.Server.ReadHeaderTimeout = 2 * time.Minute + }) + + addr := fmt.Sprintf("%s:%d", srv.config.Host, srv.config.Port) + return srv.Listen(addr) +} + +// AddCloser adds one or more function that should be called on +// manual server shutdown or OS interrupt signals. +func (srv *Server) AddCloser(closers ...func()) { + for _, closer := range closers { + if closer == nil { + continue + } + + // Terminate any opened connections on OS interrupt signals. + iris.RegisterOnInterrupt(closer) + } + + srv.closers = append(srv.closers, closers...) +} + +// Close gracefully terminates the HTTP server and calls the closers afterwards. +func (srv *Server) Close() error { + ctx, cancelCtx := context.WithTimeout(context.Background(), 5*time.Second) + err := srv.Shutdown(ctx) + cancelCtx() + + for _, closer := range srv.closers { + if closer == nil { + continue + } + + closer() + } + + return err +} diff --git a/project/api/users/api.go b/project/api/users/api.go new file mode 100644 index 00000000..6156f5d1 --- /dev/null +++ b/project/api/users/api.go @@ -0,0 +1,27 @@ +package users + +import ( + "github.com/username/project/user" + + "github.com/kataras/iris/v12" +) + +type API struct { + Users user.Repository // exported field so api/router.go#api.RegisterDependency can bind it. +} + +func (api *API) Configure(r iris.Party) { + r.Post("/signup", api.signUp) + r.Post("/signin", api.signIn) + // Add middlewares such as user verification by bearer token here. + + // Authenticated routes... + r.Get("/", api.getInfo) +} + +func (api *API) getInfo(ctx iris.Context) { + ctx.WriteString("...") +} + +func (api *API) signUp(ctx iris.Context) {} +func (api *API) signIn(ctx iris.Context) {} diff --git a/project/cmd/cmd.go b/project/cmd/cmd.go new file mode 100644 index 00000000..ba4e29f6 --- /dev/null +++ b/project/cmd/cmd.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "github.com/username/project/api" + + "github.com/kataras/iris/v12" + "github.com/spf13/cobra" +) + +const defaultConfigFilename = "server.yml" + +var serverConfig api.Configuration + +// New returns a new CLI app. +// Build with: +// $ go build -ldflags="-s -w" +func New() *cobra.Command { + configFile := defaultConfigFilename + + rootCmd := &cobra.Command{ + Use: "project", + Short: "Command line interface for project.", + Long: "The root command will start the HTTP server.", + Version: "v0.0.1", + SilenceErrors: true, + SilenceUsage: true, + TraverseChildren: true, + SuggestionsMinimumDistance: 1, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Read configuration from file before any of the commands run functions. + return serverConfig.BindFile(configFile) + }, + RunE: func(cmd *cobra.Command, args []string) error { + return startServer() + }, + } + + helpTemplate := HelpTemplate{ + BuildRevision: iris.BuildRevision, + BuildTime: iris.BuildTime, + ShowGoRuntimeVersion: true, + } + rootCmd.SetHelpTemplate(helpTemplate.String()) + + // Shared flags. + flags := rootCmd.PersistentFlags() + flags.StringVar(&configFile, "config", configFile, "--config=server.yml a filepath which contains the YAML config format") + + // Subcommands here. + // rootCmd.AddCommand(...) + + return rootCmd +} + +func startServer() error { + srv := api.NewServer(serverConfig) + return srv.Start() +} diff --git a/project/cmd/help.go b/project/cmd/help.go new file mode 100644 index 00000000..a5173dae --- /dev/null +++ b/project/cmd/help.go @@ -0,0 +1,43 @@ +package cmd + +import ( + "fmt" + "runtime" + "strconv" + "strings" + "time" +) + +// HelpTemplate is the structure which holds the necessary information for the help command. +type HelpTemplate struct { + BuildTime string + BuildRevision string + ShowGoRuntimeVersion bool + + Template fmt.Stringer +} + +func (h HelpTemplate) String() string { + tmpl := `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} + {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` + + if h.BuildRevision != "" { + buildTitle := ">>>> build" // if we ever want an emoji, there is one: \U0001f4bb + tab := strings.Repeat(" ", len(buildTitle)) + + n, _ := strconv.ParseInt(h.BuildTime, 10, 64) + buildTimeStr := time.Unix(n, 0).Format(time.UnixDate) + + buildTmpl := fmt.Sprintf("\n%s\n", buildTitle) + + fmt.Sprintf("%s revision %s\n", tab, h.BuildRevision) + + fmt.Sprintf("%s datetime %s\n", tab, buildTimeStr) + + if h.ShowGoRuntimeVersion { + buildTmpl += fmt.Sprintf("%s runtime %s\n", tab, runtime.Version()) + } + + tmpl += buildTmpl + } + + return tmpl +} diff --git a/project/go.mod b/project/go.mod new file mode 100644 index 00000000..c7152b72 --- /dev/null +++ b/project/go.mod @@ -0,0 +1,59 @@ +module github.com/username/project + +go 1.22 + +require ( + github.com/kataras/golog v0.1.11 + github.com/kataras/iris/v12 v12.2.11 + github.com/spf13/cobra v1.8.0 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect +) diff --git a/project/go.sum b/project/go.sum new file mode 100644 index 00000000..d62a9874 --- /dev/null +++ b/project/go.sum @@ -0,0 +1,193 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/project/main.go b/project/main.go new file mode 100644 index 00000000..0e8ce255 --- /dev/null +++ b/project/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "os" + + "github.com/username/project/cmd" +) + +func main() { + app := cmd.New() + if err := app.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/project/pkg/database/database.go b/project/pkg/database/database.go new file mode 100644 index 00000000..80e5687c --- /dev/null +++ b/project/pkg/database/database.go @@ -0,0 +1,9 @@ +package database + +type DB struct { + /* ... */ +} + +func Open(connString string) *DB { + return &DB{} +} diff --git a/project/pkg/http/handlers/cors.go b/project/pkg/http/handlers/cors.go new file mode 100644 index 00000000..1c245994 --- /dev/null +++ b/project/pkg/http/handlers/cors.go @@ -0,0 +1,28 @@ +package handlers + +import "github.com/kataras/iris/v12" + +// CORS set ups a cors allow-all. +// We may need to edit it before deployment. +func CORS(allowedOrigin string) iris.Handler { // or "github.com/iris-contrib/middleware/cors" + if allowedOrigin == "" { + allowedOrigin = "*" + } + + return func(ctx iris.Context) { + ctx.Header("Access-Control-Allow-Origin", allowedOrigin) + ctx.Header("Access-Control-Allow-Credentials", "true") + // July 2021 Mozzila updated the following document: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy + ctx.Header("Referrer-Policy", "no-referrer-when-downgrade") + ctx.Header("Access-Control-Expose-Headers", "*, Authorization, X-Authorization") + if ctx.Method() == iris.MethodOptions { + ctx.Header("Access-Control-Allow-Methods", "*") + ctx.Header("Access-Control-Allow-Headers", "*") + ctx.Header("Access-Control-Max-Age", "86400") + ctx.StatusCode(iris.StatusNoContent) + return + } + + ctx.Next() + } +} diff --git a/project/server.yml b/project/server.yml new file mode 100644 index 00000000..0784028a --- /dev/null +++ b/project/server.yml @@ -0,0 +1,18 @@ +ServerName: My Project +Env: development +Host: 0.0.0.0 +Port: 80 +EnableCompression: true +AllowOrigin: "*" +Iris: + # Defaults to info. + LogLevel: info + # Defaults to false. + EnableOptimizations: true + # Defaults to empty. + RemoteAddrHeaders: + - "X-Real-Ip" + - "X-Forwarded-For" + - "CF-Connecting-IP" + - "True-Client-Ip" + - "X-Appengine-Remote-Addr" diff --git a/project/user/repository.go b/project/user/repository.go new file mode 100644 index 00000000..99c67a12 --- /dev/null +++ b/project/user/repository.go @@ -0,0 +1,14 @@ +package user + +import "github.com/username/project/pkg/database" + +type Repository interface { // Repo methods here... +} + +type repo struct { // Hold database instance here: e.g. + db *database.DB +} + +func NewRepository(db *database.DB) Repository { + return &repo{db: db} +} diff --git a/project/user/user.go b/project/user/user.go new file mode 100644 index 00000000..2802fd14 --- /dev/null +++ b/project/user/user.go @@ -0,0 +1,4 @@ +package user + +type User struct { /* ... */ +} diff --git a/miscellaneous/recover/main.go b/recover/main.go similarity index 76% rename from miscellaneous/recover/main.go rename to recover/main.go index 9b5b7dc5..7825180d 100644 --- a/miscellaneous/recover/main.go +++ b/recover/main.go @@ -1,14 +1,13 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/middleware/recover" + "github.com/kataras/iris/v12/middleware/recover" ) func main() { app := iris.New() - // use this recover(y) middleware app.Use(recover.New()) i := 0 @@ -22,7 +21,7 @@ func main() { }) // http://localhost:8080, refresh it 5-6 times. - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } // Note: diff --git a/recover/panic-and-custom-error-handler-with-compression/main.go b/recover/panic-and-custom-error-handler-with-compression/main.go new file mode 100644 index 00000000..545e9b5a --- /dev/null +++ b/recover/panic-and-custom-error-handler-with-compression/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "errors" + "fmt" + + "github.com/kataras/iris/v12" + // "github.com/kataras/iris/v12/context" +) + +func main() { + app := iris.New() + app.UseRouter(iris.Compression) + app.UseRouter(myErrorHandler) + + app.Get("/", handler) + + app.Listen(":8080") +} + +func myErrorHandler(ctx iris.Context) { + recorder := ctx.Recorder() + + defer func() { + var err error + + if v := recover(); v != nil { // panic + if panicErr, ok := v.(error); ok { + err = panicErr + } else { + err = errors.New(fmt.Sprint(v)) + } + } else { // custom error. + err = ctx.GetErr() + } + + if err != nil { + // To keep compression after reset: + // clear body and any headers created between recorder and handler. + recorder.ResetBody() + recorder.ResetHeaders() + // + + // To disable compression after reset: + // recorder.Reset() + // recorder.ResponseWriter.(*context.CompressResponseWriter).Disabled = true + // + + ctx.StopWithJSON(iris.StatusInternalServerError, iris.Map{ + "message": err.Error(), + }) + } + }() + + ctx.Next() +} + +func handler(ctx iris.Context) { + ctx.WriteString("Content may fall") + ctx.Header("X-Test", "value") + + // ctx.SetErr(fmt.Errorf("custom error message")) + panic("errr!") +} diff --git a/request-body/form-query-headers-params-decoder/main.go b/request-body/form-query-headers-params-decoder/main.go new file mode 100644 index 00000000..0e764472 --- /dev/null +++ b/request-body/form-query-headers-params-decoder/main.go @@ -0,0 +1,60 @@ +// package main contains an example on how to register a custom decoder +// for a custom type when using the `ReadQuery/ReadParams/ReadHeaders/ReadForm` methods. +// +// Let's take for example the mongo-driver/primite.ObjectID: +// +// ObjectID is type ObjectID [12]byte. +// You have to register a converter for that custom type. +// ReadJSON works because the ObjectID has a MarshalJSON method +// which the encoding/json pakcage uses as a converter. +// See here: https://godoc.org/go.mongodb.org/mongo-driver/bson/primitive#ObjectID.MarshalJSON. +// +// To register a converter import the github.com/iris-contrib/schema and call +// schema.Query.RegisterConverter(value interface{}, converterFunc Converter). +// +// The Converter is just a type of func(string) reflect.Value. +// +// There is another way, but requires introducing a custom type which will wrap the mongo's ObjectID +// and implements the encoding.TextUnmarshaler e.g. +// func(id *ID) UnmarshalText(text []byte) error){ ...}. +package main + +import ( + "reflect" + + "go.mongodb.org/mongo-driver/bson/primitive" + + "github.com/iris-contrib/schema" + "github.com/kataras/iris/v12" +) + +type MyType struct { + ID primitive.ObjectID `url:"id"` +} + +func main() { + // Register on initialization. + schema.Query.RegisterConverter(primitive.ObjectID{}, func(value string) reflect.Value { + id, err := primitive.ObjectIDFromHex(value) + if err != nil { + return reflect.Value{} + } + return reflect.ValueOf(id) + }) + + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + var t MyType + err := ctx.ReadQuery(&t) + if err != nil && !iris.IsErrPath(err) { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("MyType.ID: %q", t.ID.Hex()) + }) + + // http://localhost:8080?id=507f1f77bcf86cd799439011 + app.Listen(":8080") +} diff --git a/request-body/read-body/main.go b/request-body/read-body/main.go new file mode 100644 index 00000000..ebf2ced1 --- /dev/null +++ b/request-body/read-body/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + // See main_test.go for usage. + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + // To automatically decompress using gzip: + // app.Use(iris.GzipReader) + + app.Use(setAllowedResponses) + + app.Post("/", readBody) + + return app +} + +type payload struct { + Message string `json:"message" xml:"message" msgpack:"message" yaml:"Message" url:"message" form:"message"` +} + +func readBody(ctx iris.Context) { + var p payload + + // Bind request body to "p" depending on the content-type that client sends the data, + // e.g. JSON, XML, YAML, MessagePack, Protobuf, Form and URL Query. + err := ctx.ReadBody(&p) + if err != nil { + ctx.StopWithProblem(iris.StatusBadRequest, + iris.NewProblem().Title("Parser issue").Detail(err.Error())) + return + } + + // For the sake of the example, log the received payload. + ctx.Application().Logger().Infof("Received: %#+v", p) + + // Send back the payload depending on the accept content type and accept-encoding of the client, + // e.g. JSON, XML and so on. + ctx.Negotiate(p) +} + +func setAllowedResponses(ctx iris.Context) { + // Indicate that the Server can send JSON, XML, YAML and MessagePack for this request. + ctx.Negotiation().JSON().XML().YAML().MsgPack() + // Add more, allowed by the server format of responses, mime types here... + + // If client is missing an "Accept: " header then default it to JSON. + ctx.Negotiation().Accept.JSON() + + ctx.Next() +} diff --git a/request-body/read-body/main_test.go b/request-body/read-body/main_test.go new file mode 100644 index 00000000..6ab79065 --- /dev/null +++ b/request-body/read-body/main_test.go @@ -0,0 +1,50 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadBodyAndNegotiate(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + + var ( + expectedPayload = payload{Message: "a message"} + expectedMsgPackPayload = "\x81\xa7message\xa9a message" + expectedXMLPayload = `<payload><message>a message</message></payload>` + expectedYAMLPayload = "Message: a message\n" + ) + + // Test send JSON and receive JSON. + e.POST("/").WithJSON(expectedPayload).Expect().Status(httptest.StatusOK). + JSON().IsEqual(expectedPayload) + + // Test send Form and receive XML. + e.POST("/").WithForm(expectedPayload). + WithHeader("Accept", "application/xml"). + Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedXMLPayload) + + // Test send URL Query and receive MessagePack. + e.POST("/").WithQuery("message", expectedPayload.Message). + WithHeader("Accept", "application/msgpack"). + Expect().Status(httptest.StatusOK).ContentType("application/msgpack"). + Body().IsEqual(expectedMsgPackPayload) + + // Test send MessagePack and receive MessagePack. + e.POST("/").WithBytes([]byte(expectedMsgPackPayload)). + WithHeader("Content-Type", "application/msgpack"). + WithHeader("Accept", "application/msgpack"). + Expect().Status(httptest.StatusOK). + ContentType("application/msgpack").Body().IsEqual(expectedMsgPackPayload) + + // Test send YAML and receive YAML. + e.POST("/").WithBytes([]byte(expectedYAMLPayload)). + WithHeader("Content-Type", "application/x-yaml"). + WithHeader("Accept", "application/x-yaml"). + Expect().Status(httptest.StatusOK). + ContentType("application/x-yaml").Body().IsEqual(expectedYAMLPayload) +} diff --git a/http_request/read-custom-per-type/main.go b/request-body/read-custom-per-type/main.go similarity index 84% rename from http_request/read-custom-per-type/main.go rename to request-body/read-custom-per-type/main.go index 2c339988..e60b3429 100644 --- a/http_request/read-custom-per-type/main.go +++ b/request-body/read-custom-per-type/main.go @@ -1,9 +1,9 @@ package main import ( - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -19,7 +19,7 @@ func main() { // // The response should be: // Received: main.config{Addr:"localhost:8080", ServerName:"Iris"} - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations) + app.Listen(":8080", iris.WithOptimizations) } func newApp() *iris.Application { @@ -48,7 +48,7 @@ func handler(ctx iris.Context) { // Note: // second parameter is nil because our &c implements the `context#BodyDecoder` // which has a priority over the context#Unmarshaler (which can be a more global option for reading request's body) - // see the `http_request/read-custom-via-unmarshaler/main.go` example to learn how to use the context#Unmarshaler too. + // see the `request-body/read-custom-via-unmarshaler/main.go` example to learn how to use the context#Unmarshaler too. // // Note 2: // If you need to read the body again for any reason @@ -56,8 +56,7 @@ func handler(ctx iris.Context) { // if err := ctx.UnmarshalBody(&c, nil); err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusBadRequest, err) return } diff --git a/http_request/read-custom-per-type/main_test.go b/request-body/read-custom-per-type/main_test.go similarity index 74% rename from http_request/read-custom-per-type/main_test.go rename to request-body/read-custom-per-type/main_test.go index 323b08b3..448367cd 100644 --- a/http_request/read-custom-per-type/main_test.go +++ b/request-body/read-custom-per-type/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestReadCustomPerType(t *testing.T) { @@ -13,5 +13,5 @@ func TestReadCustomPerType(t *testing.T) { expectedResponse := `Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}` e.POST("/").WithText("addr: localhost:8080\nserverName: Iris").Expect(). - Status(httptest.StatusOK).Body().Equal(expectedResponse) + Status(httptest.StatusOK).Body().IsEqual(expectedResponse) } diff --git a/http_request/read-custom-via-unmarshaler/main.go b/request-body/read-custom-via-unmarshaler/main.go similarity index 88% rename from http_request/read-custom-via-unmarshaler/main.go rename to request-body/read-custom-via-unmarshaler/main.go index 4c4bcf55..ad0d1332 100644 --- a/http_request/read-custom-via-unmarshaler/main.go +++ b/request-body/read-custom-via-unmarshaler/main.go @@ -1,9 +1,9 @@ package main import ( - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -19,7 +19,7 @@ func main() { // // The response should be: // Received: main.config{Addr:"localhost:8080", ServerName:"Iris"} - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations) + app.Listen(":8080", iris.WithOptimizations) } func newApp() *iris.Application { @@ -64,8 +64,7 @@ func handler(ctx iris.Context) { // if err := ctx.UnmarshalBody(&c, iris.UnmarshalerFunc(yaml.Unmarshal)); err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusBadRequest, err) return } diff --git a/http_request/read-custom-via-unmarshaler/main_test.go b/request-body/read-custom-via-unmarshaler/main_test.go similarity index 74% rename from http_request/read-custom-via-unmarshaler/main_test.go rename to request-body/read-custom-via-unmarshaler/main_test.go index a068a65d..9359f042 100644 --- a/http_request/read-custom-via-unmarshaler/main_test.go +++ b/request-body/read-custom-via-unmarshaler/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestReadCustomViaUnmarshaler(t *testing.T) { @@ -13,5 +13,5 @@ func TestReadCustomViaUnmarshaler(t *testing.T) { expectedResponse := `Received: main.config{Addr:"localhost:8080", ServerName:"Iris"}` e.POST("/").WithText("addr: localhost:8080\nserverName: Iris").Expect(). - Status(httptest.StatusOK).Body().Equal(expectedResponse) + Status(httptest.StatusOK).Body().IsEqual(expectedResponse) } diff --git a/request-body/read-form/checkboxes/main.go b/request-body/read-form/checkboxes/main.go new file mode 100644 index 00000000..4007fbf0 --- /dev/null +++ b/request-body/read-form/checkboxes/main.go @@ -0,0 +1,35 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./templates", ".html")) + + app.Get("/", showForm) + app.Post("/", handleForm) + + app.Listen(":8080") +} + +func showForm(ctx iris.Context) { + if err := ctx.View("form.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +type formExample struct { + Colors []string `form:"colors[]"` // or just colors, it'll work as expected. +} + +func handleForm(ctx iris.Context) { + var form formExample + err := ctx.ReadForm(&form) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.JSON(iris.Map{"Colors": form.Colors}) +} diff --git a/request-body/read-form/checkboxes/templates/form.html b/request-body/read-form/checkboxes/templates/form.html new file mode 100644 index 00000000..aaaf6821 --- /dev/null +++ b/request-body/read-form/checkboxes/templates/form.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Select a color</title> +</head> +<body> + <form action="/" method="POST"> + <p>Select one or more colors</p> + + <label for="red">Red</label> + <!-- name can be "colors" too --> + <input type="checkbox" name="colors[]" value="red" id="red"> + <label for="green">Green</label> + <input type="checkbox" name="colors[]" value="green" id="green"> + <label for="blue">Blue</label> + <input type="checkbox" name="colors[]" value="blue" id="blue"> + <input type="submit"> + </form> +</body> +</html> \ No newline at end of file diff --git a/http_request/read-form/main.go b/request-body/read-form/main.go similarity index 67% rename from http_request/read-form/main.go rename to request-body/read-form/main.go index 7b619a7b..942a2378 100644 --- a/http_request/read-form/main.go +++ b/request-body/read-form/main.go @@ -2,7 +2,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) type Visitor struct { @@ -19,8 +19,8 @@ func main() { app.Get("/", func(ctx iris.Context) { if err := ctx.View("form.html"); err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.WriteString(err.Error()) + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -28,8 +28,11 @@ func main() { visitor := Visitor{} err := ctx.ReadForm(&visitor) if err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.WriteString(err.Error()) + if !iris.IsErrPath(err) /* see: https://github.com/kataras/iris/issues/1157 */ || + err == iris.ErrEmptyForm { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } } ctx.Writef("Visitor: %#v", visitor) @@ -40,5 +43,5 @@ func main() { ctx.Writef("Username: %s", username) }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080", iris.WithEmptyFormError /* returns ErrEmptyForm if the request form body was empty */) } diff --git a/http_request/read-form/templates/form.html b/request-body/read-form/templates/form.html similarity index 100% rename from http_request/read-form/templates/form.html rename to request-body/read-form/templates/form.html diff --git a/request-body/read-headers/main.go b/request-body/read-headers/main.go new file mode 100644 index 00000000..ee878d39 --- /dev/null +++ b/request-body/read-headers/main.go @@ -0,0 +1,41 @@ +// package main contains an example on how to use the ReadHeaders, +// same way you can do the ReadQuery, ReadJSON, ReadProtobuf and e.t.c. +package main + +import ( + "github.com/kataras/iris/v12" +) + +type myHeaders struct { + RequestID string `header:"X-Request-Id,required"` + Authentication string `header:"Authentication,required"` +} + +func main() { + app := newApp() + + // http://localhost:8080 + /* + myHeaders: main.myHeaders{ + RequestID: "373713f0-6b4b-42ea-ab9f-e2e04bc38e73", + Authentication: "Bearer my-token", + } + */ + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + var hs myHeaders + if err := ctx.ReadHeaders(&hs); err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("myHeaders: %#v", hs) + }) + + return app +} diff --git a/request-body/read-headers/main_test.go b/request-body/read-headers/main_test.go new file mode 100644 index 00000000..38371e85 --- /dev/null +++ b/request-body/read-headers/main_test.go @@ -0,0 +1,51 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadHeaders(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + + expectedOKBody := `myHeaders: main.myHeaders{RequestID:"373713f0-6b4b-42ea-ab9f-e2e04bc38e73", Authentication:"Bearer my-token"}` + + tests := []struct { + headers map[string]string + code int + body string + regex bool + }{ + {headers: map[string]string{ + "X-Request-Id": "373713f0-6b4b-42ea-ab9f-e2e04bc38e73", + "Authentication": "Bearer my-token", + }, code: 200, body: expectedOKBody, regex: false}, + {headers: map[string]string{ + "x-request-id": "373713f0-6b4b-42ea-ab9f-e2e04bc38e73", + "authentication": "Bearer my-token", + }, code: 200, body: expectedOKBody, regex: false}, + {headers: map[string]string{ + "X-Request-Id": "373713f0-6b4b-42ea-ab9f-e2e04bc38e73", + "Authentication": "Bearer my-token", + }, code: 200, body: expectedOKBody, regex: false}, + {headers: map[string]string{ + "Authentication": "Bearer my-token", + }, code: 500, body: "X-Request-Id is empty", regex: false}, + {headers: map[string]string{ + "X-Request-Id": "373713f0-6b4b-42ea-ab9f-e2e04bc38e73", + }, code: 500, body: "Authentication is empty", regex: false}, + {headers: map[string]string{}, code: 500, body: ".*\\(and 1 other error\\)$", regex: true}, + } + + for _, tt := range tests { + te := e.GET("/").WithHeaders(tt.headers).Expect().Status(tt.code).Body() + if tt.regex { + te.Match(tt.body) + } else { + te.Equal(tt.body) + } + } +} diff --git a/request-body/read-json-stream/main.go b/request-body/read-json-stream/main.go new file mode 100644 index 00000000..dd9ac3a6 --- /dev/null +++ b/request-body/read-json-stream/main.go @@ -0,0 +1,86 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.Post("/", postIndex) + + app.Post("/stream", postIndexStream) + + /* + curl -L -X POST "http://localhost:8080/" \ + -H 'Content-Type: application/json' \ + --data-raw '{"username":"john"}' + + curl -L -X POST "http://localhost:8080/stream" \ + -H 'Content-Type: application/json' \ + --data-raw '{"username":"john"} + {"username":"makis"} + {"username":"george"} + {"username":"michael"} + ' + + If JSONReader.ArrayStream was true then you must provide an array of objects instead, e.g. + [{"username":"john"}, + {"username":"makis"}, + {"username":"george"}, + {"username":"michael"}] + + */ + + app.Listen(":8080") +} + +type User struct { + Username string `json:"username"` +} + +func postIndex(ctx iris.Context) { + var u User + err := ctx.ReadJSON(&u, iris.JSONReader{ + // To throw an error on unknown request payload json fields. + DisallowUnknownFields: true, + Optimize: true, + }) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.JSON(iris.Map{ + "code": iris.StatusOK, + "username": u.Username, + }) +} + +func postIndexStream(ctx iris.Context) { + var users []User + job := func(decode iris.DecodeFunc) error { + var u User + if err := decode(&u); err != nil { + return err + } + users = append(users, u) + // When the returned error is not nil the decode operation + // is terminated and the error is received by the ReadJSONStream method below, + // otherwise it continues to read the next available object. + return nil + } + + err := ctx.ReadJSONStream(job, iris.JSONReader{ + Optimize: true, + DisallowUnknownFields: true, + ArrayStream: false, + }) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.JSON(iris.Map{ + "code": iris.StatusOK, + "users_count": len(users), + "users": users, + }) +} diff --git a/request-body/read-json-struct-validation/main.go b/request-body/read-json-struct-validation/main.go new file mode 100644 index 00000000..29493183 --- /dev/null +++ b/request-body/read-json-struct-validation/main.go @@ -0,0 +1,146 @@ +// Package main shows the validator(latest, version 10) integration with Iris' Context methods of +// `ReadJSON`, `ReadXML`, `ReadMsgPack`, `ReadYAML`, `ReadForm`, `ReadQuery`, `ReadBody`. +// +// You can find more examples of this 3rd-party library at: +// https://github.com/go-playground/validator/blob/master/_examples +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" + + // $ go get github.com/go-playground/validator/v10@latest + "github.com/go-playground/validator/v10" +) + +func main() { + app := iris.New() + app.Validator = validator.New() + + userRouter := app.Party("/user") + { + userRouter.Get("/validation-errors", resolveErrorsDocumentation) + userRouter.Post("/", postUser) + } + + // Use Postman or any tool to perform a POST request + // to the http://localhost:8080/user with RAW BODY of: + /* + { + "fname": "", + "lname": "", + "age": 45, + "email": "mail@example.com", + "favColor": "#000", + "addresses": [{ + "street": "Eavesdown Docks", + "planet": "Persphone", + "phone": "none", + "city": "Unknown" + }] + } + */ + /* The response should be: + { + "title": "Validation error", + "detail": "One or more fields failed to be validated", + "type": "http://localhost:8080/user/validation-errors", + "status": 400, + "fields": [ + { + "tag": "required", + "namespace": "User.FirstName", + "kind": "string", + "type": "string", + "value": "", + "param": "" + }, + { + "tag": "required", + "namespace": "User.LastName", + "kind": "string", + "type": "string", + "value": "", + "param": "" + } + ] + } + */ + app.Listen(":8080") +} + +// User contains user information. +type User struct { + FirstName string `json:"fname" validate:"required"` + LastName string `json:"lname" validate:"required"` + Age uint8 `json:"age" validate:"gte=0,lte=130"` + Email string `json:"email" validate:"required,email"` + FavouriteColor string `json:"favColor" validate:"hexcolor|rgb|rgba"` + Addresses []*Address `json:"addresses" validate:"required,dive,required"` // a User can have a home and cottage... +} + +// Address houses a users address information. +type Address struct { + Street string `json:"street" validate:"required"` + City string `json:"city" validate:"required"` + Planet string `json:"planet" validate:"required"` + Phone string `json:"phone" validate:"required"` +} + +type validationError struct { + ActualTag string `json:"tag"` + Namespace string `json:"namespace"` + Kind string `json:"kind"` + Type string `json:"type"` + Value string `json:"value"` + Param string `json:"param"` +} + +func wrapValidationErrors(errs validator.ValidationErrors) []validationError { + validationErrors := make([]validationError, 0, len(errs)) + for _, validationErr := range errs { + validationErrors = append(validationErrors, validationError{ + ActualTag: validationErr.ActualTag(), + Namespace: validationErr.Namespace(), + Kind: validationErr.Kind().String(), + Type: validationErr.Type().String(), + Value: fmt.Sprintf("%v", validationErr.Value()), + Param: validationErr.Param(), + }) + } + + return validationErrors +} + +func postUser(ctx iris.Context) { + var user User + err := ctx.ReadJSON(&user) + if err != nil { + // Handle the error, below you will find the right way to do that... + + if errs, ok := err.(validator.ValidationErrors); ok { + // Wrap the errors with JSON format, the underline library returns the errors as interface. + validationErrors := wrapValidationErrors(errs) + + // Fire an application/json+problem response and stop the handlers chain. + ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem(). + Title("Validation error"). + Detail("One or more fields failed to be validated"). + Type("/user/validation-errors"). + Key("errors", validationErrors)) + + return + } + + // It's probably an internal JSON error, let's dont give more info here. + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + ctx.JSON(iris.Map{"message": "OK"}) +} + +func resolveErrorsDocumentation(ctx iris.Context) { + ctx.WriteString("A page that should document to web developers or users of the API on how to resolve the validation errors") +} diff --git a/http_request/read-json/main.go b/request-body/read-json/main.go similarity index 80% rename from http_request/read-json/main.go rename to request-body/read-json/main.go index 88f84407..fee580f5 100644 --- a/http_request/read-json/main.go +++ b/request-body/read-json/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) type Company struct { @@ -14,8 +14,7 @@ func MyHandler(ctx iris.Context) { var c Company if err := ctx.ReadJSON(&c); err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusBadRequest, err) return } @@ -32,10 +31,8 @@ type Person struct { func MyHandler2(ctx iris.Context) { var persons []Person err := ctx.ReadJSON(&persons) - if err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusBadRequest, err) return } @@ -61,5 +58,5 @@ func main() { // // The response should be: // Received: main.Company{Name:"iris-Go", City:"New York", Other:"Something here"} - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations) + app.Listen(":8080", iris.WithOptimizations) } diff --git a/request-body/read-many/main.go b/request-body/read-many/main.go new file mode 100644 index 00000000..af970968 --- /dev/null +++ b/request-body/read-many/main.go @@ -0,0 +1,60 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Post("/", logAllBody, logJSON, logFormValues, func(ctx iris.Context) { + // body, err := io.ReadAll(ctx.Request().Body) once or + body, err := ctx.GetBody() // as many times as you need. + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + if len(body) == 0 { + ctx.WriteString(`The body was empty +or iris.WithoutBodyConsumptionOnUnmarshal option is missing from app.Run. +Check the terminal window for any queries logs.`) + } else { + ctx.WriteString("OK body is still:\n") + ctx.Write(body) + } + }) + + // With ctx.UnmarshalBody, ctx.ReadJSON, ctx.ReadXML, ctx.ReadForm, ctx.FormValues + // and ctx.GetBody methods the default golang and net/http behavior + // is to consume the readen data - they are not available on any next handlers in the chain - + // to change that behavior just pass the `WithoutBodyConsumptionOnUnmarshal` option. + app.Listen(":8080", iris.WithoutBodyConsumptionOnUnmarshal) +} + +func logAllBody(ctx iris.Context) { + body, err := ctx.GetBody() + if err == nil && len(body) > 0 { + ctx.Application().Logger().Infof("logAllBody: %s", string(body)) + } + + ctx.Next() +} + +func logJSON(ctx iris.Context) { + var p interface{} + if err := ctx.ReadJSON(&p); err == nil { + ctx.Application().Logger().Infof("logJSON: %#+v", p) + } + + ctx.Next() +} + +func logFormValues(ctx iris.Context) { + values := ctx.FormValues() + if values != nil { + ctx.Application().Logger().Infof("logFormValues: %v", values) + } + + ctx.Next() +} diff --git a/request-body/read-msgpack/main.go b/request-body/read-msgpack/main.go new file mode 100644 index 00000000..4a4e92b5 --- /dev/null +++ b/request-body/read-msgpack/main.go @@ -0,0 +1,37 @@ +package main + +import "github.com/kataras/iris/v12" + +// User example struct to bind to. +type User struct { + Firstname string `msgpack:"firstname"` + Lastname string `msgpack:"lastname"` + City string `msgpack:"city"` + Age int `msgpack:"age"` +} + +// readMsgPack reads a `User` from MsgPack post body. +func readMsgPack(ctx iris.Context) { + var u User + err := ctx.ReadMsgPack(&u) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.Writef("Received: %#+v\n", u) +} + +func main() { + app := iris.New() + app.Post("/", readMsgPack) + + // POST: http://localhost:8080 + // + // To run the example, use a tool like Postman: + // 1. Body: Binary + // 2. Select File, select the one from "_examples/response-writer/write-rest" example. + // The output should be: + // Received: main.User{Firstname:"John", Lastname:"Doe", City:"Neither FBI knows!!!", Age:25} + app.Listen(":8080") +} diff --git a/request-body/read-params/main.go b/request-body/read-params/main.go new file mode 100644 index 00000000..993f59b5 --- /dev/null +++ b/request-body/read-params/main.go @@ -0,0 +1,37 @@ +// package main contains an example on how to use the ReadParams, +// same way you can do the ReadQuery, ReadJSON, ReadProtobuf and e.t.c. +package main + +import ( + "github.com/kataras/iris/v12" +) + +type myParams struct { + Name string `param:"name"` + Age int `param:"age"` + Tail []string `param:"tail"` +} + +func main() { + app := newApp() + + // http://localhost:8080/kataras/27/iris/web/framework + // myParams: main.myParams{Name:"kataras", Age:27, Tail:[]string{"iris", "web", "framework"}} + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + app.Get("/{name}/{age:int}/{tail:path}", func(ctx iris.Context) { + var p myParams + if err := ctx.ReadParams(&p); err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("myParams: %#v", p) + }) + + return app +} diff --git a/request-body/read-params/main_test.go b/request-body/read-params/main_test.go new file mode 100644 index 00000000..debfee58 --- /dev/null +++ b/request-body/read-params/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadParams(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + + expectedBody := `myParams: main.myParams{Name:"kataras", Age:27, Tail:[]string{"iris", "web", "framework"}}` + e.GET("/kataras/27/iris/web/framework").Expect().Status(httptest.StatusOK).Body().IsEqual(expectedBody) +} diff --git a/request-body/read-query/main.go b/request-body/read-query/main.go new file mode 100644 index 00000000..e8c0de54 --- /dev/null +++ b/request-body/read-query/main.go @@ -0,0 +1,51 @@ +// package main contains an example on how to use the ReadQuery, +// same way you can do the ReadJSON & ReadProtobuf and e.t.c. +package main + +import ( + "github.com/kataras/iris/v12" +) + +type MyType struct { + Name string `url:"name,required"` + Age int `url:"age"` +} + +func main() { + app := iris.New() + app.UseRouter(iris.AllowQuerySemicolons) // Optionally: to restore pre go1.17 behavior of url parsing. + + app.Get("/", func(ctx iris.Context) { + var t MyType + err := ctx.ReadQuery(&t) + + // To ignore errors of "required" or when unexpected values are passed to the query, + // use the iris.IsErrPath. + // It can be ignored, e.g: + // if err!=nil && !iris.IsErrPath(err) { ... return } + // + // To receive an error on EMPTY query when ReadQuery is called + // you should enable the `FireEmptyFormError/WithEmptyFormError` ( see below). + // To check for the empty error you simple compare the error with the ErrEmptyForm, e.g.: + // err == iris.ErrEmptyForm, so, to ignore both path and empty errors, you do: + // if err!=nil && err != iris.ErrEmptyForm && !iris.IsErrPath(err) { ctx.StopWithError(...); return } + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("MyType: %#v", t) + }) + + app.Get("/simple", func(ctx iris.Context) { + names := ctx.URLParamSlice("name") + ctx.Writef("names: %v", names) + }) + + // http://localhost:8080?name=iris&age=3 + // http://localhost:8080/simple?name=john&name=doe&name=kataras + // + // Note: this `WithEmptyFormError` will give an error if the query was empty. + app.Listen(":8080", iris.WithEmptyFormError, + iris.WithoutServerError(iris.ErrServerClosed, iris.ErrURLQuerySemicolon)) +} diff --git a/request-body/read-url/main.go b/request-body/read-url/main.go new file mode 100644 index 00000000..36521614 --- /dev/null +++ b/request-body/read-url/main.go @@ -0,0 +1,38 @@ +// package main contains an example on how to use the ReadURL, +// same way you can do the ReadQuery, ReadParams, ReadJSON, ReadProtobuf and e.t.c. +package main + +import ( + "github.com/kataras/iris/v12" +) + +type myURL struct { + Name string `url:"name"` // or `param:"name"` + Age int `url:"age"` // >> >> + Tail []string `url:"tail"` // >> >> +} + +func main() { + app := newApp() + + // http://localhost:8080/iris/web/framework?name=kataras&age=27 + // myURL: main.myURL{Name:"kataras", Age:27, Tail:[]string{"iris", "web", "framework"}} + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + app.Get("/{tail:path}", func(ctx iris.Context) { + var u myURL + // ReadURL is a shortcut of ReadParams + ReadQuery. + if err := ctx.ReadURL(&u); err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.Writef("myURL: %#v", u) + }) + + return app +} diff --git a/request-body/read-url/main_test.go b/request-body/read-url/main_test.go new file mode 100644 index 00000000..ffb6232f --- /dev/null +++ b/request-body/read-url/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadURL(t *testing.T) { + app := newApp() + + e := httptest.New(t, app) + + expectedBody := `myURL: main.myURL{Name:"kataras", Age:27, Tail:[]string{"iris", "web", "framework"}}` + e.GET("/iris/web/framework").WithQuery("name", "kataras").WithQuery("age", 27).Expect().Status(httptest.StatusOK).Body().IsEqual(expectedBody) +} diff --git a/http_request/read-xml/main.go b/request-body/read-xml/main.go similarity index 85% rename from http_request/read-xml/main.go rename to request-body/read-xml/main.go index 5261bcfa..9b42e9ae 100644 --- a/http_request/read-xml/main.go +++ b/request-body/read-xml/main.go @@ -3,7 +3,7 @@ package main import ( "encoding/xml" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -20,7 +20,7 @@ func main() { // // The response should be: // Received: main.person{XMLName:xml.Name{Space:"", Local:"person"}, Name:"Winston Churchill", Age:90, Description:"Description of this person, the body of this inner element."} - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithOptimizations) + app.Listen(":8080", iris.WithOptimizations) } func newApp() *iris.Application { @@ -41,8 +41,7 @@ type person struct { func handler(ctx iris.Context) { var p person if err := ctx.ReadXML(&p); err != nil { - ctx.StatusCode(iris.StatusBadRequest) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusBadRequest, err) return } diff --git a/http_request/read-xml/main_test.go b/request-body/read-xml/main_test.go similarity index 83% rename from http_request/read-xml/main_test.go rename to request-body/read-xml/main_test.go index da4fbd7a..1cce03e2 100644 --- a/http_request/read-xml/main_test.go +++ b/request-body/read-xml/main_test.go @@ -3,7 +3,7 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestReadXML(t *testing.T) { @@ -14,5 +14,5 @@ func TestReadXML(t *testing.T) { send := `<person name="Winston Churchill" age="90"><description>Description of this person, the body of this inner element.</description></person>` e.POST("/").WithText(send).Expect(). - Status(httptest.StatusOK).Body().Equal(expectedResponse) + Status(httptest.StatusOK).Body().IsEqual(expectedResponse) } diff --git a/request-body/read-yaml/main.go b/request-body/read-yaml/main.go new file mode 100644 index 00000000..b353e94c --- /dev/null +++ b/request-body/read-yaml/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func newApp() *iris.Application { + app := iris.New() + app.Post("/", handler) + + return app +} + +// simple yaml stuff, read more at https://yaml.org/start.html +type product struct { + Invoice int `yaml:"invoice"` + Tax float32 `yaml:"tax"` + Total float32 `yaml:"total"` + Comments string `yaml:"comments"` +} + +func handler(ctx iris.Context) { + var p product + if err := ctx.ReadYAML(&p); err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.Writef("Received: %#+v", p) +} + +func main() { + app := newApp() + app.Listen(":8080") +} diff --git a/request-body/read-yaml/main_test.go b/request-body/read-yaml/main_test.go new file mode 100644 index 00000000..971e4e5d --- /dev/null +++ b/request-body/read-yaml/main_test.go @@ -0,0 +1,24 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestReadYAML(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + expectedResponse := `Received: main.product{Invoice:34843, Tax:251.42, Total:4443.52, Comments:"Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338."}` + send := `invoice: 34843 +tax : 251.42 +total: 4443.52 +comments: > + Late afternoon is best. + Backup contact is Nancy + Billsmer @ 338-4338.` + + e.POST("/").WithHeader("Content-Type", "application/x-yaml").WithBytes([]byte(send)).Expect(). + Status(httptest.StatusOK).Body().IsEqual(expectedResponse) +} diff --git a/request-ratelimit/rate-middleware/main.go b/request-ratelimit/rate-middleware/main.go new file mode 100644 index 00000000..84629524 --- /dev/null +++ b/request-ratelimit/rate-middleware/main.go @@ -0,0 +1,90 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/rate" +) + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + + // * http://localhost:8080/v1 + // * http://localhost:8080/v1/other + // * http://localhost:8080/v2/list (with X-API-Key request header) + // Read more at: https://en.wikipedia.org/wiki/Token_bucket + // + // Alternatives: + // * https://github.com/iris-contrib/middleware/blob/master/throttler/_example/main.go + // Read more at: https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm + // * https://github.com/iris-contrib/middleware/tree/master/tollboothic/_examples/limit-handler + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + v1 := app.Party("/v1") + { + // Register the rate limiter middleware at the "/v1" subrouter. + // + // Fist and second input parameters: + // Allow 1 request per second, with a maximum burst size of 5. + // + // Third optional variadic input parameter: + // Can be a cleanup function. + // Iris provides a cleanup function that will check for old entries and remove them. + // You can customize it, e.g. check every 1 minute + // if a client's last visit was 5 minutes ago ("old" entry) + // and remove it from the memory. + limitV1 := rate.Limit(1, 5, rate.PurgeEvery(time.Minute, 5*time.Minute)) + // rate.Every helper: + // rate.Limit(rate.Every(time.Minute), 5) + v1.Use(limitV1) + + v1.Get("/", index) + v1.Get("/other", other) + } + + v2 := app.Party("/v2") + { + v2.Use(useAPIKey) + // Initialize a new rate limit middleware to limit requests + // per API Key(see `useAPIKey` below) instead of client's Remote IP Address. + limitV2 := rate.Limit(rate.Every(time.Minute), 300, rate.PurgeEvery(5*time.Minute, 15*time.Minute)) + v2.Use(limitV2) + + v2.Get("/list", list) + } + + return app +} + +func useAPIKey(ctx iris.Context) { + apiKey := ctx.GetHeader("X-API-Key") + if apiKey == "" { // [validate your API Key here...] + ctx.StopWithStatus(iris.StatusForbidden) + return + } + + // Change the method that rate limit matches the requests with a specific user + // and set our own api key as theirs identifier. + rate.SetIdentifier(ctx, apiKey) + ctx.Next() +} + +func list(ctx iris.Context) { + ctx.JSON(iris.Map{"key": "value"}) +} + +func index(ctx iris.Context) { + ctx.HTML("<h1>Index Page</h1>") +} + +func other(ctx iris.Context) { + ctx.HTML("<h1>Other Page</h1>") +} + +// Note: Use `ctx.SendFileWithRate` to use a download rate limiter instead. diff --git a/request-ratelimit/ulule-limiter/main.go b/request-ratelimit/ulule-limiter/main.go new file mode 100644 index 00000000..661c84b8 --- /dev/null +++ b/request-ratelimit/ulule-limiter/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + "net/http" + "strconv" + "time" + + "github.com/kataras/iris/v12" + + "github.com/ulule/limiter/v3" + "github.com/ulule/limiter/v3/drivers/store/memory" +) + +func main() { + app := iris.New() + app.Get("/hello", IPRateLimit(), helloWorldHandler) // 3. Use middleware + app.Run(iris.Addr(":8080")) +} + +func helloWorldHandler(ctx iris.Context) { + err := ctx.StopWithJSON(iris.StatusOK, iris.Map{ + "message": "Hello World!", + }) + if err != nil { + return + } +} + +func IPRateLimit() iris.Handler { + // 1. Configure + rate := limiter.Rate{ + Period: 2 * time.Second, + Limit: 1, + } + store := memory.NewStore() + ipRateLimiter := limiter.New(store, rate) + + // 2. Return middleware handler + return func(ctx iris.Context) { + ip := ctx.RemoteAddr() + limiterCtx, err := ipRateLimiter.Get(ctx.Request().Context(), ip) + if err != nil { + log.Printf("IPRateLimit - ipRateLimiter.Get - err: %v, %s on %s", err, ip, ctx.Request().URL) + ctx.StatusCode(http.StatusInternalServerError) + ctx.JSON(iris.Map{ + "success": false, + "message": err, + }) + return + } + + ctx.Header("X-RateLimit-Limit", strconv.FormatInt(limiterCtx.Limit, 10)) + ctx.Header("X-RateLimit-Remaining", strconv.FormatInt(limiterCtx.Remaining, 10)) + ctx.Header("X-RateLimit-Reset", strconv.FormatInt(limiterCtx.Reset, 10)) + + if limiterCtx.Reached { + log.Printf("Too Many Requests from %s on %s", ip, ctx.Request().URL) + ctx.StatusCode(http.StatusTooManyRequests) + ctx.JSON(iris.Map{ + "success": false, + "message": "Too Many Requests on " + ctx.Request().URL.String(), + }) + return + } + ctx.Next() + } +} diff --git a/request-referrer/main.go b/request-referrer/main.go new file mode 100644 index 00000000..adfbe3b7 --- /dev/null +++ b/request-referrer/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + // GetReferrer extracts and returns the information from the "Referer" (or "Referrer") header + // and url query parameter as specified in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy. + r := ctx.GetReferrer() + switch r.Type { + case iris.ReferrerSearch: + ctx.Writef("Search %s: %s\n", r.Label, r.Query) + ctx.Writef("Google: %s\n", r.GoogleType) + case iris.ReferrerSocial: + ctx.Writef("Social %s\n", r.Label) + case iris.ReferrerIndirect: + ctx.Writef("Indirect: %s\n", r.URL) + } + }) + + // http://localhost:8080?referrer=https://twitter.com/Xinterio/status/1023566830974251008 + // http://localhost:8080?referrer=https://www.google.com/search?q=Top+6+golang+web+frameworks&oq=Top+6+golang+web+frameworks + app.Listen(":8080") +} diff --git a/cache/client-side/main.go b/response-writer/cache/client-side/main.go similarity index 94% rename from cache/client-side/main.go rename to response-writer/cache/client-side/main.go index 8b21438e..f460b463 100644 --- a/cache/client-side/main.go +++ b/response-writer/cache/client-side/main.go @@ -8,7 +8,7 @@ package main import ( "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) const refreshEvery = 10 * time.Second @@ -30,7 +30,7 @@ func main() { // }) app.Get("/", greet) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func greet(ctx iris.Context) { diff --git a/response-writer/cache/simple/main.go b/response-writer/cache/simple/main.go new file mode 100644 index 00000000..9617712c --- /dev/null +++ b/response-writer/cache/simple/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/cache" + "github.com/kataras/iris/v12/middleware/basicauth" +) + +var markdownContents = []byte(`## Hello Markdown + +This is a sample of Markdown contents + +Features +-------- + +All features of Sundown are supported, including: + +* **Compatibility**. The Markdown v1.0.3 test suite passes with + the --tidy option. Without --tidy, the differences are + mostly in whitespace and entity escaping, where blackfriday is + more consistent and cleaner. +`) + +// Cache should not be used on handlers that contain dynamic data. +// Cache is a good and a must-feature on static content, i.e "about page" or for a whole blog site. +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + app.Get("/", cache.Handler(10*time.Second), writeMarkdown) + // To customize the cache handler: + // cache.Cache(nil).MaxAge(func(ctx iris.Context) time.Duration { + // return time.Duration(ctx.MaxAge()) * time.Second + // }).AddRule(...).Store(...) + // saves its content on the first request and serves it instead of re-calculating the content. + // After 10 seconds it will be cleared and reset. + + pages := app.Party("/pages") + pages.Use(cache.Handler(10 * time.Second)) // Per Party. + pages.Get("/", pagesIndex) + pages.Post("/", pagesIndexPost) + + // Note: on authenticated requests + // the cache middleare does not run at all (see iris/cache/ruleset). + auth := basicauth.Default(map[string]string{ + "admin": "admin", + }) + app.Get("/protected", auth, cache.Handler(5*time.Second), protected) + + // Set custom cache key/identifier, + // for the sake of the example + // we will SHARE the keys on both GET and POST routes + // so the first one is executed that's the body + // for both of the routes. Please don't do that + // on production, this is just an example. + custom := app.Party("/custom") + custom.Use(cache.WithKey("shared")) + custom.Use(cache.Handler(10 * time.Second)) + custom.Get("/", customIndex) + custom.Post("/", customIndexPost) + + app.Listen(":8080") +} + +func writeMarkdown(ctx iris.Context) { + // tap multiple times the browser's refresh button and you will + // see this println only once every 10 seconds. + println("Handler executed. Content refreshed.") + + ctx.Markdown(markdownContents) +} + +func pagesIndex(ctx iris.Context) { + println("Handler executed. Content refreshed.") + ctx.WriteString("GET: hello") +} + +func pagesIndexPost(ctx iris.Context) { + println("Handler executed. Content refreshed.") + ctx.WriteString("POST: hello") +} + +func protected(ctx iris.Context) { + username, _, _ := ctx.Request().BasicAuth() + ctx.Writef("Hello, %s!", username) +} + +func customIndex(ctx iris.Context) { + ctx.WriteString("Contents from GET custom index") +} + +func customIndexPost(ctx iris.Context) { + ctx.WriteString("Contents from POST custom index") +} + +/* Note that `HandleDir` does use the browser's disk caching by-default +therefore, register the cache handler AFTER any HandleDir calls, +for a faster solution that server doesn't need to keep track of the response +navigate to https://github.com/kataras/iris/blob/main/_examples/cache/client-side/main.go. + +The `HandleDir` has its own cache mechanism, read the 'file-server' examples. */ diff --git a/response-writer/content-negotiation/main.go b/response-writer/content-negotiation/main.go new file mode 100644 index 00000000..d5619e1d --- /dev/null +++ b/response-writer/content-negotiation/main.go @@ -0,0 +1,114 @@ +// Package main contains three different ways to render content based on the client's accepted. +package main + +import "github.com/kataras/iris/v12" + +type testdata struct { + Name string `json:"name" xml:"Name"` + Age int `json:"age" xml:"Age"` +} + +func newApp() *iris.Application { + app := iris.New() + app.Logger().SetLevel("debug") + + // app.Use(func(ctx iris.Context) { + // requestedMime := ctx.URLParamDefault("type", "application/json") + // + // ctx.Negotiation().Accept.Override().MIME(requestedMime, nil) + // ctx.Next() + // }) + + app.Get("/resource", func(ctx iris.Context) { + data := testdata{ + Name: "test name", + Age: 26, + } + + // Server allows response only JSON and XML. These values + // are compared with the clients mime needs. Iris comes with default mime types responses + // but you can add a custom one by the `Negotiation().Mime(mime, content)` method, + // same for the "accept". + // You can also pass a custom ContentSelector(mime string) or ContentNegotiator to the + // `Context.Negotiate` method if you want to perform more advanced things. + // + // + // By-default the client accept mime is retrieved by the "Accept" header + // Indeed you can override or update it by `Negotiation().Accept.XXX` i.e + // ctx.Negotiation().Accept.Override().XML() + // + // All these values can change inside middlewares, the `Negotiation().Override()` and `.Accept.Override()` + // can override any previously set values. + // Order matters, if the client accepts anything (*/*) + // then the first prioritized mime's response data will be rendered. + ctx.Negotiation().JSON().XML() + // Accept-Charset vs: + ctx.Negotiation().Charset("utf-8", "iso-8859-7") + // Alternatively you can define the content/data per mime type + // anywhere in the handlers chain using the optional "v" variadic + // input argument of the Context.Negotiation().JSON,XML,YAML,Binary,Text,HTML(...) and e.t.c + // example (order matters): + // ctx.Negotiation().JSON(data).XML(data).Any("content for */*") + // ctx.Negotiate(nil) + + // if not nil passed in the `Context.Negotiate` method + // then it overrides any contents made by the negotitation builder above. + _, err := ctx.Negotiate(data) + if err != nil { + ctx.Writef("%v", err) + } + }) + + app.Get("/resource2", func(ctx iris.Context) { + jsonAndXML := testdata{ + Name: "test name", + Age: 26, + } + + // I prefer that one, as it gives me the freedom to modify + // response data per accepted mime content type on middlewares as well. + ctx.Negotiation(). + JSON(jsonAndXML). + XML(jsonAndXML). + HTML("<h1>Test Name</h1><h2>Age 26</h2>") + + ctx.Negotiate(nil) + }) + + app.Get("/resource3", func(ctx iris.Context) { + // If that line is missing and the requested + // mime type of content is */* or application/xml or application/json + // then 406 Not Acceptable http error code will be rendered instead. + // + // We also add the "gzip" algorithm as an option to encode + // resources on send. + ctx.Negotiation().JSON().XML().HTML().EncodingGzip() + + jsonAndXML := testdata{ + Name: "test name", + Age: 26, + } + + // Prefer that way instead of the '/resource2' above + // if "iris.N" is a static one and can be declared + // outside of a handler. + ctx.Negotiate(iris.N{ + // Text: for text/plain, + // Markdown: for text/mardown, + // Binary: for application/octet-stream, + // YAML: for application/x-yaml, + // JSONP: for text/javascript + // Other: for anything else, + JSON: jsonAndXML, // for application/json + XML: jsonAndXML, // for application/xml or text/xml + HTML: "<h1>Test Name</h1><h2>Age 26</h2>", // for text/html + }) + }) + + return app +} + +func main() { + app := newApp() + app.Listen(":8080") +} diff --git a/response-writer/content-negotiation/main_test.go b/response-writer/content-negotiation/main_test.go new file mode 100644 index 00000000..c4794e5e --- /dev/null +++ b/response-writer/content-negotiation/main_test.go @@ -0,0 +1,80 @@ +package main + +import ( + "bytes" + "compress/gzip" + "encoding/xml" + "io" + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +func TestContentNegotiation(t *testing.T) { + var ( + expectedJSONResponse = testdata{ + Name: "test name", + Age: 26, + } + expectedXMLResponse, _ = xml.Marshal(expectedJSONResponse) + expectedHTMLResponse = "<h1>Test Name</h1><h2>Age 26</h2>" + ) + + app := newApp() + app.Configure(iris.WithOptimizations) + e := httptest.New(t, app) + + e.GET("/resource").WithHeader("Accept", "application/json"). + Expect().Status(httptest.StatusOK). + ContentType("application/json", "utf-8"). + JSON().IsEqual(expectedJSONResponse) + e.GET("/resource").WithHeader("Accept", "application/xml").WithHeader("Accept-Charset", "iso-8859-7"). + Expect().Status(httptest.StatusOK). + ContentType("application/xml", "iso-8859-7"). + Body().IsEqual(string(expectedXMLResponse)) + + e.GET("/resource2").WithHeader("Accept", "application/json"). + Expect().Status(httptest.StatusOK). + ContentType("application/json", "utf-8"). + JSON().IsEqual(expectedJSONResponse) + e.GET("/resource2").WithHeader("Accept", "application/xml"). + Expect().Status(httptest.StatusOK). + ContentType("application/xml", "utf-8"). + Body().IsEqual(string(expectedXMLResponse)) + e.GET("/resource2").WithHeader("Accept", "text/html"). + Expect().Status(httptest.StatusOK). + ContentType("text/html", "utf-8"). + Body().IsEqual(expectedHTMLResponse) + + e.GET("/resource3").WithHeader("Accept", "application/json"). + Expect().Status(httptest.StatusOK). + ContentType("application/json", "utf-8"). + JSON().IsEqual(expectedJSONResponse) + e.GET("/resource3").WithHeader("Accept", "application/xml"). + Expect().Status(httptest.StatusOK). + ContentType("application/xml", "utf-8"). + Body().IsEqual(string(expectedXMLResponse)) + + // test html with "gzip" encoding algorithm. + rawGzipResponse := e.GET("/resource3").WithHeader("Accept", "text/html"). + WithHeader("Accept-Encoding", "gzip"). + Expect().Status(httptest.StatusOK). + ContentType("text/html", "utf-8"). + ContentEncoding("gzip"). + Body().Raw() + + zr, err := gzip.NewReader(bytes.NewReader([]byte(rawGzipResponse))) + if err != nil { + t.Fatal(err) + } + + rawResponse, err := io.ReadAll(zr) + if err != nil { + t.Fatal(err) + } + + if expected, got := expectedHTMLResponse, string(rawResponse); expected != got { + t.Fatalf("expected response to be:\n%s but got:\n%s", expected, got) + } +} diff --git a/response-writer/http2push/main.go b/response-writer/http2push/main.go new file mode 100644 index 00000000..f6b9f4d9 --- /dev/null +++ b/response-writer/http2push/main.go @@ -0,0 +1,47 @@ +// Server push lets the server preemptively "push" website assets +// to the client without the user having explicitly asked for them. +// When used with care, we can send what we know the user is going +// to need for the page they're requesting. +package main + +import ( + "net/http" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.Get("/", pushHandler) + app.Get("/main.js", simpleAssetHandler) + + app.Run(iris.TLS("127.0.0.1:443", "mycert.crt", "mykey.key")) + // $ openssl req -new -newkey rsa:4096 -x509 -sha256 \ + // -days 365 -nodes -out mycert.crt -keyout mykey.key +} + +func pushHandler(ctx iris.Context) { + // The target must either be an absolute path (like "/path") or an absolute + // URL that contains a valid host and the same scheme as the parent request. + // If the target is a path, it will inherit the scheme and host of the + // parent request. + target := "/main.js" + + if pusher, ok := ctx.ResponseWriter().Naive().(http.Pusher); ok { + err := pusher.Push(target, nil) + if err != nil { + if err == iris.ErrPushNotSupported { + ctx.StopWithText(iris.StatusHTTPVersionNotSupported, "HTTP/2 push not supported.") + } else { + ctx.StopWithError(iris.StatusInternalServerError, err) + } + return + } + } + + ctx.HTML(`<html><body><script src="%s"></script></body></html>`, target) +} + +func simpleAssetHandler(ctx iris.Context) { + ctx.ServeFile("./public/main.js") +} diff --git a/response-writer/http2push/mycert.crt b/response-writer/http2push/mycert.crt new file mode 100644 index 00000000..9db93b09 --- /dev/null +++ b/response-writer/http2push/mycert.crt @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIUfwMd9auWixp19UnXOmyxJ9Jkv7IwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA2MjUwOTUxNDdaFw0yMTA2 +MjUwOTUxNDdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDlVGyGAQ9uyfNbwZyrtYOSjLpxf5NpNToh2OzU7gy2 +OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwje+IjGZBw8x6E+8WoGdSzbrEZ6pUV +wKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO888dwK/mbIHrHTq4nO3o0gAdAJwu +amn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA0AT8eg544GyCdyteAH11oCDsHS8/ +DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8eJohddRTK6zHe9ixZTt/soayOF7OS +QQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po6bqDnUzdnkqAAwwymQapHMuHXZKN +rhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt+0AidLRH+dCY7MS9Ngga/sAK3vID +gSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat4y0VwSyysUy887vHr6lMK5CrAT/l +Ch8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bVGYsEYrrW+bCNN9wCGYTZEyX++os9 +v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w3wPf9K4Y40MNxeR90nyX4zjXGF1/ +91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L2UBwMacsfjBbN4djOc5IuYMar/VN +GQIDAQABo1MwUTAdBgNVHQ4EFgQUtkf+yAvqgZC8f22iJny9hFEDolMwHwYDVR0j +BBgwFoAUtkf+yAvqgZC8f22iJny9hFEDolMwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQsFAAOCAgEAE2QasBVru618rxupyJgEHw6r4iv7sz1Afz3Q5qJ4oSA9 +xVsrVCjr3iHRFSw8Rf670E8Ffk/JjzS65mHw6zeZj/ANBKQWLjRlqzYXeetq5HzG +SIgaG7p1RFvvzz3+leFGzjinZ6sKbfB4OB72o2YN+fO8DsDxgGKll0W4KAazizSe +HY9Pgu437tWnwF16rFO3IL47n5HzYlRoGIPOpzFoNX5+fyn9GlnKEtONF2QBKTjY +rdjvqFRByDiC74d8z/Yx8IiDRn1mTcG90JLR9+c6M7fruha9Y/rJfw+4AhVh5ZDz +Bl9rGPjwEs5zwutYvVAJzs7AVcighYP1lHKoJ7DxBDQeyBsYlUNk2l6bmZgLgGUZ ++2OyWlqc/jD2GdDsIaZ4i7QqhTI/6aYZIf5zUkblKV1aMSaDulKxRv//OwW28Jax +9EEoV7VaFb3sOkB/tZGhusXeQVtdrhahT3KkZLNwmNXoXWKJ5LjeUlFWJyV6JbDe +y/PIWWCwWqyuFCSZS+Cg3RDgAzfSxkI8uVZ+IKKJS3UluDX45lxXtbRrvTQ+oDrA +6ga5c1Vz9C4kn1K5yW4d7QIvg6vPiy7gvl+//sz9oxUM3yswInDBY0HKLgT0Uq9b +YzLDh2RSaHsgHMPy2BKqR+q2N+lpg7inAWuJM1Huq6eHFqhiyQkzsfscBd1Dpm8= +-----END CERTIFICATE----- diff --git a/response-writer/http2push/mykey.key b/response-writer/http2push/mykey.key new file mode 100644 index 00000000..39f7b3af --- /dev/null +++ b/response-writer/http2push/mykey.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDlVGyGAQ9uyfNb +wZyrtYOSjLpxf5NpNToh2OzU7gy2OexBji5lmWBQ3oYDG+FjAkbHORPzOMNpeMwj +e+IjGZBw8x6E+8WoGdSzbrEZ6pUVwKJGKEuDlx6g6HEmtv3ZwgGe20gvPjjW+oCO +888dwK/mbIHrHTq4nO3o0gAdAJwuamn9BlHU5O4RW7BQ4tLF+j/fBCACWRG1NHXA +0AT8eg544GyCdyteAH11oCDsHS8/DAPsM6t+tZrMCIt9+9dzPdVoOmQNaMMrcz8e +JohddRTK6zHe9ixZTt/soayOF7OSQQeekbr3HPYhD450zRVplLMHx7wnph/+O+Po +6bqDnUzdnkqAAwwymQapHMuHXZKNrhdfKau3rVo1GeXLIRgeWLUoxFSm4TYshrgt ++0AidLRH+dCY7MS9Ngga/sAK3vIDgSF75mFgOhY+q7nvY9Ecao6TnoNNRY29hUat +4y0VwSyysUy887vHr6lMK5CrAT/lCh8fuu20HUCoiLwMJvA6+wpivZkuiIvWY7bV +GYsEYrrW+bCNN9wCGYTZEyX++os9v/38wdOqGUT00ewXkjIUFCWbrnxxSr98kF3w +3wPf9K4Y40MNxeR90nyX4zjXGF1/91msUh+iivsz9mcN9DK83fgTyOsoVLX5cm/L +2UBwMacsfjBbN4djOc5IuYMar/VNGQIDAQABAoICAQCtWx1SSxjkcerxsLEDKApW +zOTfiUXgoOjZz0ZwS6b2VWDfyWAPU1r4ps39KaU+F+lzDhWjpYQqhbMjG7G9QMTs +bQvkEQLAaQ5duU5NPgQG1oCUsj8rMSBpGGz4jBnm834QHMk7VTjYYbKu3WTyo8cU +U2/+UDEkfxRlC+IkCmMFv1FxgMZ5PbktC/eDnYMhP2Pq7Q5ZWAVHymk9IMK0LHwm +Kdg842K4A3zTXwGkGwetDCMm+YQpG5TxqX/w82BRcCuTR5h8fnYSsWLEIvKwWyIl +ppcjaUnrFPG2yhxLqWUIKPpehuEjjhQMt9rDNoh6MHsJZZY5Dp5eq91EIvLoLQ99 +hXBmD4P8LDop4r0jniPZJi/ACsaD0jBooA4525+Kouq7RP28Jp/pek7lVOOcBgRv +D3zyESbKfqoaOfyfQ2ff4sILnTAr4V2nq3ekphGEYJrWN0ZoADcLdnr1cZ8L+VBI +o/4mi5/3HID/UEDliHSa97hxxGBEqTto0ZuXuNwfwx5ho33uVT6zNwRgiJ62Bgu3 +Fhk/wVGuZxWvb1KHUNInG9cvsslhO4Vu9wJvYj91BnRq36rsyKKid5DrU+PNgmog +lw3IXQpTojyRCYPuG9TKqEZ6b+so7GTKhBOjiwaupMOletVRGSAdbE81VN6HtxNW +aj39+FnxzMAlsieib+PBAQKCAQEA+t1fOYSaZBo7pZUmo2S0zulUEJjrYRGKJlWJ +4psWSwFu/7/3UL4q0RBQaSRew9u/YSpaNlBYfcpnFVOjiLwHq5Hx46Eq0BuKsNlJ +1/qxw9qjHqcrOre6K4/7NaWLPuM9fEmV+3MhFVXgv+WC5BHOowRTlOG30vIcC1J2 +L5xsBUsxDDY13cD1bLKRmFcyMFM8y7wMZmo7H/WfVmyoPKQaC43pTcmIXH0Jr2Ws +Wsfh18mhjtamaOPEFx5K0x4d0PI8tW5ouiUUkVIDaue27XfS969qEChv768/44eX +WeqcekaG9jv2noMClt79rYd3Lne9HkgY6IT9FT+JqXfu+KYwuQKCAQEA6gYzUsGB +9GQO8DE8AYn7JwNOtg1X4zKakXiGxH+nuZb7wJjAeGdYqTHySxPBXg0A2nDwoyz5 +4sAdLAr3FZoIvTzo7M5KIKFDzfyDmQDavhroH1mBAEiqKGNniP+RND3nWBBqDK1R +qcqbhI3Kj5Ycany6a4nP+hZRBIyT9sfJ0S0YruSY8IGXgDwhlJrZ7bsWMZylrgD/ +1qnPL0KqVBY8YR8msRj88h72IlD5o0kwvisOIvyhA0YgwGBb6lg7A+DifiF03ZlS +2yELbIkKDVr+p3jC7MBh4B+OJY68AMl6wVjAaDM1AZnpjKE5YmZg5+Ks5823zILo +PrSB9hn0+DIPYQKCAQEAh9x+JuNmzhHa/dkiHNl8hpadHYQD7gUWwZ4P1/bQAv0a +xU2MvmDPRXxFYDv/SqlnI1NRmhq3YiDM5SLv7SyQJt4al4IAcsaHvTFgqaSuw3hU +YVR9uAYqwE7w6OPn3r4o3Xfoz05Ru4FP//1nfucZ9vVv4rC/4nGWuJcHRM+9PLy1 +KnztfVR0VlL7QPrwRnW99kS4nnqn3K4khiTAlF73cAyCLsuXmydoqGIzDtMzv68G +XRpo82NvHmoccevcj/2w3T2XYECWvAEjsrEdQ8xiKBwLIAcWYEOUIUCcumiyKBKs +IwzkioI/U8AeuO0lobfdZ1n6i2sCuZA4mNxIQseWmQKCAQEA5YkfXdQeuq5JWJ1x +1bCYfjNoSHfd9CH2KSimRqVOxWGpm8Y3QeFbvNgYZjsCNlVauOZ9oA7FKfp0onY+ +0xk56SKM83eCjW6fKrK6AKAt7LhHZDhNpxGek+6r5luE+FCfUGkJG1YD+x2WW/UW +8K6zQF8GGeQZ8Zlh7axUlIBxGpG43BGrUHpLNqPD7BXWGq6dnhufBYRFay8y34/r +sH3+yuPa92ki7/geQppZwCZRgLSKMRbIdoWaKhZZEQlpGOzCOiRmk9OGyRcoNVRU +X7UYgPqZdc1cMo/AxGWzULJNjMaYMZvIKcHkqOKZfkIcWlSictn7pMPhN1+k+NWM +yMORAQKCAQAyXl02h/c2ihx6cjKlnNeDr2ZfzkoiAvFuKaoAR+KVvb9F9X7ZgKSi +wudZyelTglIVCYXeRmG09uX3rNGCzFrweRwgn6x/8DnN5pMRJVZOXFdgR+V9uKep +K6F7DYbPyggvLOAsezB+09i9lwxM+XdA2whVpL5NFR1rGfFglnE1EQHcEvNONkcv +0h8x9cNSptJyRDLiTIKI9EhonuzwzkGpvjULQE8MLbT8PbjoLFINcE9ZWhwtyw0V +XO32KE8iLKt3KzHz9CfTRCI3M7DwD752AC6zRr8ZS/HXzs+5WTkdVVEtRC7Abd3y +W2TzuSMYNDu876twbTVQJED3mwOAQ3J7 +-----END PRIVATE KEY----- diff --git a/response-writer/http2push/public/main.js b/response-writer/http2push/public/main.js new file mode 100644 index 00000000..2aae6c4c --- /dev/null +++ b/response-writer/http2push/public/main.js @@ -0,0 +1 @@ +window.alert("javascript loaded"); \ No newline at end of file diff --git a/response-writer/json-third-party/go.mod b/response-writer/json-third-party/go.mod new file mode 100644 index 00000000..88221bf7 --- /dev/null +++ b/response-writer/json-third-party/go.mod @@ -0,0 +1,60 @@ +module github.com/kataras/iris/_examples/response-writer/json-third-party + +go 1.22 + +require ( + github.com/bytedance/sonic v1.11.6 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/response-writer/json-third-party/go.sum b/response-writer/json-third-party/go.sum new file mode 100644 index 00000000..bbc939e0 --- /dev/null +++ b/response-writer/json-third-party/go.sum @@ -0,0 +1,200 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/response-writer/json-third-party/main.go b/response-writer/json-third-party/main.go new file mode 100644 index 00000000..ac958833 --- /dev/null +++ b/response-writer/json-third-party/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + // This is a 3rd-party library, which you can use to override the default behavior of ctx.JSON method. + "github.com/bytedance/sonic" +) + +func init() { + applyIrisGlobalPatches() // <- IMPORTANT. +} + +func applyIrisGlobalPatches() { + var json = sonic.ConfigFastest + + // Apply global modifications to the context REST writers + // without modifications to your web server's handlers code. + iris.Patches().Context().Writers().JSON(func(ctx iris.Context, v interface{}, options *iris.JSON) error { + enc := json.NewEncoder(ctx.ResponseWriter()) + enc.SetEscapeHTML(!options.UnescapeHTML) + enc.SetIndent("", options.Indent) + return enc.Encode(v) + }) +} + +// User example struct for json. +type User struct { + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + City string `json:"city"` + Age int `json:"age"` +} + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + user := User{ + Firstname: "Gerasimos", + Lastname: "Maropoulos", + City: "Athens", + Age: 29, + } + + // Use ctx.JSON as you used to. + ctx.JSON(user) + }) + + app.Listen(":8080") +} diff --git a/response-writer/protobuf/README.md b/response-writer/protobuf/README.md new file mode 100644 index 00000000..4c69034c --- /dev/null +++ b/response-writer/protobuf/README.md @@ -0,0 +1,18 @@ +# Protocol Buffers + +The `Context.Protobuf(proto.Message)` is the method which sends protos to the client. It accepts a [proto.Message](https://godoc.org/google.golang.org/protobuf/proto#Message) value. + +> Note: Iris is using the newest version of the Go protocol buffers implementation. Read more about it at [The Go Blog: A new Go API for Protocol Buffers](https://blog.golang.org/protobuf-apiv2). + + +1. Install the protoc-gen-go tool. + +```sh +$ go get -u google.golang.org/protobuf/cmd/protoc-gen-go@latest +``` + +2. Generate proto + +```sh +$ protoc -I protos/ protos/hello.proto --go_out=. +``` diff --git a/response-writer/protobuf/go.mod b/response-writer/protobuf/go.mod new file mode 100644 index 00000000..54e15041 --- /dev/null +++ b/response-writer/protobuf/go.mod @@ -0,0 +1,54 @@ +module app + +go 1.22 + +require ( + github.com/golang/protobuf v1.5.3 + github.com/kataras/iris/v12 v12.2.11 + google.golang.org/protobuf v1.33.0 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/response-writer/protobuf/go.sum b/response-writer/protobuf/go.sum new file mode 100644 index 00000000..85d378a0 --- /dev/null +++ b/response-writer/protobuf/go.sum @@ -0,0 +1,185 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/response-writer/protobuf/main.go b/response-writer/protobuf/main.go new file mode 100644 index 00000000..8996c813 --- /dev/null +++ b/response-writer/protobuf/main.go @@ -0,0 +1,60 @@ +package main + +import ( + "app/protos" + + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.Get("/", send) + app.Get("/json", sendAsJSON) + app.Post("/read", read) + app.Post("/read_json", readFromJSON) + + app.Listen(":8080") +} + +func send(ctx iris.Context) { + response := &protos.HelloReply{Message: "Hello, World!"} + ctx.Protobuf(response) +} + +func sendAsJSON(ctx iris.Context) { + response := &protos.HelloReply{Message: "Hello, World!"} + options := iris.JSON{ + Proto: iris.ProtoMarshalOptions{ + AllowPartial: true, + Multiline: true, + Indent: " ", + }, + } + + ctx.JSON(response, options) +} + +func read(ctx iris.Context) { + var request protos.HelloRequest + + err := ctx.ReadProtobuf(&request) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.Writef("HelloRequest.Name = %s", request.Name) +} + +func readFromJSON(ctx iris.Context) { + var request protos.HelloRequest + + err := ctx.ReadJSONProtobuf(&request) + if err != nil { + ctx.StopWithError(iris.StatusBadRequest, err) + return + } + + ctx.Writef("HelloRequest.Name = %s", request.Name) +} diff --git a/response-writer/protobuf/protos/hello.pb.go b/response-writer/protobuf/protos/hello.pb.go new file mode 100644 index 00000000..ee512210 --- /dev/null +++ b/response-writer/protobuf/protos/hello.pb.go @@ -0,0 +1,209 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.11.1 +// source: hello.proto + +package protos + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_hello_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_hello_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_hello_proto protoreflect.FileDescriptor + +var file_hello_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, + 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_hello_proto_rawDescOnce sync.Once + file_hello_proto_rawDescData = file_hello_proto_rawDesc +) + +func file_hello_proto_rawDescGZIP() []byte { + file_hello_proto_rawDescOnce.Do(func() { + file_hello_proto_rawDescData = protoimpl.X.CompressGZIP(file_hello_proto_rawDescData) + }) + return file_hello_proto_rawDescData +} + +var file_hello_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_hello_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protos.HelloRequest + (*HelloReply)(nil), // 1: protos.HelloReply +} +var file_hello_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_hello_proto_init() } +func file_hello_proto_init() { + if File_hello_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_hello_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_hello_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_hello_proto_goTypes, + DependencyIndexes: file_hello_proto_depIdxs, + MessageInfos: file_hello_proto_msgTypes, + }.Build() + File_hello_proto = out.File + file_hello_proto_rawDesc = nil + file_hello_proto_goTypes = nil + file_hello_proto_depIdxs = nil +} diff --git a/response-writer/protobuf/protos/hello.proto b/response-writer/protobuf/protos/hello.proto new file mode 100644 index 00000000..31281615 --- /dev/null +++ b/response-writer/protobuf/protos/hello.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package protos; + +option go_package = "./protos"; + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/response-writer/sse-third-party-2/index.html b/response-writer/sse-third-party-2/index.html new file mode 100644 index 00000000..202d8a65 --- /dev/null +++ b/response-writer/sse-third-party-2/index.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> + <title>SSE Examples</title> +</head> +<body> + <strong>Messages</strong> + <br> + <div id="messages"></div> + + <script type="text/javascript"> + e1 = new EventSource('/events/channel-1'); + e1.onmessage = function(event) { + document.getElementById('messages').innerHTML += 'Message on channel-1: ' + event.data + '<br>'; + }; + + e2 = new EventSource('/events/channel-2'); + e2.onmessage = function(event) { + document.getElementById('messages').innerHTML += 'Message on channel-2: ' + event.data + '<br>'; + }; + </script> +</body> +</html> diff --git a/response-writer/sse-third-party-2/main.go b/response-writer/sse-third-party-2/main.go new file mode 100644 index 00000000..3cba7c28 --- /dev/null +++ b/response-writer/sse-third-party-2/main.go @@ -0,0 +1,61 @@ +package main + +import ( + "log" + "net/http" + "os" + "strconv" + "time" + + "github.com/alexandrevicenzi/go-sse" + "github.com/kataras/iris/v12" +) + +// Install the sse third-party package. +// $ go get -u github.com/alexandrevicenzi/go-sse +// +// Documentation: https://pkg.go.dev/github.com/alexandrevicenzi/go-sse +func main() { + s := sse.NewServer(&sse.Options{ + // Increase default retry interval to 10s. + RetryInterval: 10 * 1000, + // CORS headers + Headers: map[string]string{ + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, OPTIONS", + "Access-Control-Allow-Headers": "Keep-Alive,X-Requested-With,Cache-Control,Content-Type,Last-Event-ID", + }, + // Custom channel name generator + ChannelNameFunc: func(request *http.Request) string { + return request.URL.Path + }, + // Print debug info + Logger: log.New(os.Stdout, "go-sse: ", log.Ldate|log.Ltime|log.Lshortfile), + }) + + defer s.Shutdown() + + app := iris.New() + app.Get("/", func(ctx iris.Context) { + ctx.ServeFile("./index.html") + }) + app.Get("/events/{channel}", iris.FromStd(s)) + + go func() { + for { + s.SendMessage("/events/channel-1", sse.SimpleMessage(time.Now().Format("2006/02/01/ 15:04:05"))) + time.Sleep(5 * time.Second) + } + }() + + go func() { + i := 0 + for { + i++ + s.SendMessage("/events/channel-2", sse.SimpleMessage(strconv.Itoa(i))) + time.Sleep(5 * time.Second) + } + }() + + app.Listen(":3000") +} diff --git a/http_responsewriter/sse-third-party/main.go b/response-writer/sse-third-party/main.go similarity index 81% rename from http_responsewriter/sse-third-party/main.go rename to response-writer/sse-third-party/main.go index 4c5be9b1..af378232 100644 --- a/http_responsewriter/sse-third-party/main.go +++ b/response-writer/sse-third-party/main.go @@ -3,12 +3,12 @@ package main import ( "time" - "github.com/kataras/iris" - "github.com/r3labs/sse" + "github.com/kataras/iris/v12" + "github.com/r3labs/sse/v2" ) -// First of all install the sse third-party package (you can use other if you don't like this approach) -// $ go get -u github.com/r3labs/sse +// First of all install the sse third-party package (you can use other if you don't like this approach or go ahead to the "sse" example) +// $ go get github.com/r3labs/sse/v2@v2.7.4 func main() { app := iris.New() s := sse.New() @@ -22,7 +22,7 @@ func main() { */ s.CreateStream("messages") - app.Any("/events", iris.FromStd(s.HTTPHandler)) + app.Any("/events", iris.FromStd(s)) go func() { // You design when to send messages to the client, @@ -42,10 +42,9 @@ func main() { s.Publish("messages", &sse.Event{ Data: []byte("third message"), }) - }() // ... - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app.Listen(":8080") } /* For a golang SSE client you can look at: https://github.com/r3labs/sse#example-client */ diff --git a/response-writer/sse/main.go b/response-writer/sse/main.go new file mode 100644 index 00000000..7ac0a21d --- /dev/null +++ b/response-writer/sse/main.go @@ -0,0 +1,191 @@ +// Package main shows how to send continuous event messages to the clients through SSE via a broker. +// Read details at: https://www.w3schools.com/htmL/html5_serversentevents.asp and +// https://robots.thoughtbot.com/writing-a-server-sent-events-server-in-go +package main + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/kataras/golog" + "github.com/kataras/iris/v12" +) + +// A Broker holds open client connections, +// listens for incoming events on its Notifier channel +// and broadcast event data to all registered connections. +type Broker struct { + + // Events are pushed to this channel by the main events-gathering routine. + Notifier chan []byte + + // New client connections. + newClients chan chan []byte + + // Closed client connections. + closingClients chan chan []byte + + // Client connections registry. + clients map[chan []byte]bool +} + +// NewBroker returns a new broker factory. +func NewBroker() *Broker { + b := &Broker{ + Notifier: make(chan []byte, 1), + newClients: make(chan chan []byte), + closingClients: make(chan chan []byte), + clients: make(map[chan []byte]bool), + } + + // Set it running - listening and broadcasting events. + go b.listen() + + return b +} + +// Listen on different channels and act accordingly. +func (b *Broker) listen() { + for { + select { + case s := <-b.newClients: + // A new client has connected. + // Register their message channel. + b.clients[s] = true + golog.Infof("Client added. %d registered clients", len(b.clients)) + + case s := <-b.closingClients: + // A client has dettached and we want to + // stop sending them messages. + delete(b.clients, s) + golog.Infof("Removed client. %d registered clients", len(b.clients)) + + case event := <-b.Notifier: + // We got a new event from the outside! + // Send event to all connected clients. + for clientMessageChan := range b.clients { + clientMessageChan <- event + } + } + } +} + +func (b *Broker) ServeHTTP(ctx iris.Context) { + // Make sure that the writer supports flushing. + + flusher, ok := ctx.ResponseWriter().Flusher() + if !ok { + ctx.StopWithText(iris.StatusHTTPVersionNotSupported, "Streaming unsupported!") + return + } + + // Set the headers related to event streaming, you can omit the "application/json" if you send plain text. + // If you develop a go client, you must have: "Accept" : "application/json, text/event-stream" header as well. + ctx.ContentType("application/json, text/event-stream") + ctx.Header("Cache-Control", "no-cache") + ctx.Header("Connection", "keep-alive") + // We also add a Cross-origin Resource Sharing header so browsers on different domains can still connect. + ctx.Header("Access-Control-Allow-Origin", "*") + + // Each connection registers its own message channel with the Broker's connections registry. + messageChan := make(chan []byte) + + // Signal the broker that we have a new connection. + b.newClients <- messageChan + + // Listen to connection close and when the entire request handler chain exits(this handler here) and un-register messageChan. + ctx.OnClose(func(iris.Context) { + // Remove this client from the map of connected clients + // when this handler exits. + b.closingClients <- messageChan + }) + + // Block waiting for messages broadcast on this connection's messageChan. + for { + // Write to the ResponseWriter. + // Server Sent Events compatible. + ctx.Writef("data: %s\n\n", <-messageChan) + // or json: data:{obj}. + + // Flush the data immediately instead of buffering it for later. + flusher.Flush() + } +} + +type event struct { + Timestamp int64 `json:"timestamp"` + Message string `json:"message"` +} + +const script = `<script type="text/javascript"> +if(typeof(EventSource) !== "undefined") { + console.log("server-sent events supported"); + var client = new EventSource("http://localhost:8080/events"); + var index = 1; + client.onmessage = function (evt) { + console.log(evt); + // it's not required that you send and receive JSON, you can just output the "evt.data" as well. + dataJSON = JSON.parse(evt.data) + var table = document.getElementById("messagesTable"); + var row = table.insertRow(index); + var cellTimestamp = row.insertCell(0); + var cellMessage = row.insertCell(1); + cellTimestamp.innerHTML = dataJSON.timestamp; + cellMessage.innerHTML = dataJSON.message; + index++; + + window.scrollTo(0,document.body.scrollHeight); + }; +} else { + document.getElementById("header").innerHTML = "<h2>SSE not supported by this client-protocol</h2>"; +} +</script>` + +func main() { + broker := NewBroker() + + go func() { + for { + time.Sleep(2 * time.Second) + + now := time.Now() + evt := event{ + Timestamp: now.Unix(), + Message: fmt.Sprintf("Hello at %s", now.Format(time.RFC1123)), + } + + evtBytes, err := json.Marshal(evt) + if err != nil { + golog.Error(err) + continue + } + + broker.Notifier <- evtBytes + } + }() + + app := iris.New() + app.Logger().SetLevel("debug") + + app.Get("/", func(ctx iris.Context) { + ctx.HTML( + `<html><head><title>SSE</title>` + script + `</head> + <body> + <h1 id="header">Waiting for messages...</h1> + <table id="messagesTable" border="1"> + <tr> + <th>Timestamp (server)</th> + <th>Message</th> + </tr> + </table> + </body> + </html>`) + }) + + app.Get("/events", broker.ServeHTTP) + + // http://localhost:8080 + // http://localhost:8080/events + app.Listen(":8080") +} diff --git a/response-writer/sse/optional.sse.mini.js.html b/response-writer/sse/optional.sse.mini.js.html new file mode 100644 index 00000000..01e1304a --- /dev/null +++ b/response-writer/sse/optional.sse.mini.js.html @@ -0,0 +1,17 @@ +<!-- you can just put that to your favourite browser --> +<html> + +<head> + <title>SSE (javascript side)</title> + + <script type="text/javascript"> + var client = new EventSource("http://localhost:8080/events") + client.onmessage = function (evt) { + console.log(evt) + } + </script> +</head> +<body> + <h1>Open the browser's console(F12) and watch for incoming event messages</h1> +</body> +</html> \ No newline at end of file diff --git a/response-writer/stream-writer/main.go b/response-writer/stream-writer/main.go new file mode 100644 index 00000000..58b2f11e --- /dev/null +++ b/response-writer/stream-writer/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "errors" + "io" + "time" // showcase the delay + + "github.com/kataras/iris/v12" +) + +var errDone = errors.New("done") + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.ContentType("text/html") + ctx.Header("Transfer-Encoding", "chunked") + i := 0 + ints := []int{1, 2, 3, 5, 7, 9, 11, 13, 15, 17, 23, 29} + // Send the response in chunks and wait for half a second between each chunk, + // until connection close. + err := ctx.StreamWriter(func(w io.Writer) error { + ctx.Writef("Message number %d<br>", ints[i]) + time.Sleep(500 * time.Millisecond) // simulate delay. + if i == len(ints)-1 { + return errDone // ends the loop. + } + i++ + return nil // continue write + }) + + if err != errDone { + // Test it by canceling the request before the stream ends: + // [ERRO] $DATETIME stream: context canceled. + ctx.Application().Logger().Errorf("stream: %v", err) + } + }) + + type messageNumber struct { + Number int `json:"number"` + } + + app.Get("/json", func(ctx iris.Context) { + ctx.Header("Transfer-Encoding", "chunked") + i := 0 + ints := []int{1, 2, 3, 5, 7, 9, 11, 13, 15, 17, 23, 29} + // Send the response in chunks and wait for half a second between each chunk, + // until connection close. + notifyClose := ctx.Request().Context().Done() + for { + select { + case <-notifyClose: + // err := ctx.Request().Context().Err() + ctx.Application().Logger().Infof("Connection closed, loop end.") + return + default: + ctx.JSON(messageNumber{Number: ints[i]}) + ctx.WriteString("\n") + time.Sleep(500 * time.Millisecond) // simulate delay. + if i == len(ints)-1 { + ctx.Application().Logger().Infof("Loop end.") + return + } + i++ + ctx.ResponseWriter().Flush() + } + } + }) + + app.Listen(":8080") +} + +/* +Look the following methods too: +- Context.OnClose(callback) +- Context.OnConnectionClose(callback) and +- Context.Request().Context().Done()/.Err() too +*/ diff --git a/response-writer/write-rest/main.go b/response-writer/write-rest/main.go new file mode 100644 index 00000000..eacfefa9 --- /dev/null +++ b/response-writer/write-rest/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "encoding/xml" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/errors" +) + +// User example struct for json and msgpack. +type User struct { + Firstname string `json:"firstname" msgpack:"firstname"` + Lastname string `json:"lastname" msgpack:"lastname"` + City string `json:"city" msgpack:"city"` + Age int `json:"age" msgpack:"age"` +} + +// ExampleXML just a test struct to view represents xml content-type +type ExampleXML struct { + XMLName xml.Name `xml:"example"` + One string `xml:"one,attr"` + Two string `xml:"two,attr"` +} + +// ExampleYAML just a test struct to write yaml to the client. +type ExampleYAML struct { + Name string `yaml:"name"` + ServerAddr string `yaml:"ServerAddr"` +} + +func main() { + app := iris.New() + // Optionally, set a custom handler for JSON, JSONP, Protobuf, MsgPack, YAML, Markdown... + // write errors. + app.SetContextErrorHandler(new(errorHandler)) + // Read + app.Post("/decode", func(ctx iris.Context) { + // Read https://github.com/kataras/iris/blob/main/_examples/request-body/read-json/main.go as well. + var user User + err := ctx.ReadJSON(&user) + if err != nil { + errors.InvalidArgument.Details(ctx, "unable to parse body", err.Error()) + return + } + + ctx.Writef("%s %s is %d years old and comes from %s!", user.Firstname, user.Lastname, user.Age, user.City) + }) + + // Write + app.Get("/encode", func(ctx iris.Context) { + u := User{ + Firstname: "John", + Lastname: "Doe", + City: "Neither FBI knows!!!", + Age: 25, + } + + // Manually setting a content type: ctx.ContentType("text/javascript") + ctx.JSON(u) + }) + + // Use Secure field to prevent json hijacking. + // It prepends `"while(1),"` to the body when the data is array. + app.Get("/json_secure", func(ctx iris.Context) { + response := []string{"val1", "val2", "val3"} + options := iris.JSON{Indent: "", Secure: true} + ctx.JSON(response, options) + + // Will output: while(1);["val1","val2","val3"] + }) + + // Use ASCII field to generate ASCII-only JSON + // with escaped non-ASCII characters. + app.Get("/json_ascii", func(ctx iris.Context) { + response := iris.Map{"lang": "GO-虹膜", "tag": "<br>"} + options := iris.JSON{Indent: " ", ASCII: true} + ctx.JSON(response, options) + + /* Will output: + { + "lang": "GO-\u8679\u819c", + "tag": "\u003cbr\u003e" + } + */ + }) + + // Do not replace special HTML characters with their unicode entities + // using the UnescapeHTML field. + app.Get("/json_raw", func(ctx iris.Context) { + options := iris.JSON{UnescapeHTML: true} + ctx.JSON(iris.Map{ + "html": "<b>Hello, world!</b>", + }, options) + + // Will output: {"html":"<b>Hello, world!</b>"} + }) + + // Other content types, + + app.Get("/binary", func(ctx iris.Context) { + // useful when you want force-download of contents of raw bytes form. + ctx.Binary([]byte("Some binary data here.")) + }) + + app.Get("/text", func(ctx iris.Context) { + ctx.Text("Plain text here") + }) + + app.Get("/json", func(ctx iris.Context) { + ctx.JSON(map[string]string{"hello": "json"}) // or myjsonStruct{hello:"json} + }) + + app.Get("/jsonp", func(ctx iris.Context) { + ctx.JSONP(map[string]string{"hello": "jsonp"}, iris.JSONP{Callback: "callbackName"}) + }) + + app.Get("/xml", func(ctx iris.Context) { + ctx.XML(ExampleXML{One: "hello", Two: "xml"}) + // OR: + // ctx.XML(iris.XMLMap("keys", iris.Map{"key": "value"})) + }) + + app.Get("/markdown", func(ctx iris.Context) { + ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris")) + }) + + app.Get("/yaml", func(ctx iris.Context) { + ctx.YAML(ExampleYAML{Name: "Iris", ServerAddr: "localhost:8080"}) + // OR: + // ctx.YAML(iris.Map{"name": "Iris", "serverAddr": "localhost:8080"}) + }) + + // app.Get("/protobuf", func(ctx iris.Context) { + // ctx.Protobuf(proto.Message) + // }) + + app.Get("/msgpack", func(ctx iris.Context) { + u := User{ + Firstname: "John", + Lastname: "Doe", + City: "Neither FBI knows!!!", + Age: 25, + } + + ctx.MsgPack(u) + }) + + // http://localhost:8080/decode + // http://localhost:8080/encode + // http://localhost:8080/json_secure + // http://localhost:8080/json_ascii + // + // http://localhost:8080/binary + // http://localhost:8080/text + // http://localhost:8080/json + // http://localhost:8080/jsonp + // http://localhost:8080/xml + // http://localhost:8080/markdown + // http://localhost:8080/msgpack + // + // `iris.WithOptimizations` is an optional configurator, + // if passed to the `Run` then it will ensure that the application + // response to the client as fast as possible. + // + // + // `iris.WithoutServerError` is an optional configurator, + // if passed to the `Run` then it will not print its passed error as an actual server error. + app.Listen(":8080", iris.WithOptimizations) +} + +type errorHandler struct{} + +func (h *errorHandler) HandleContextError(ctx iris.Context, err error) { + errors.Internal.Err(ctx, err) +} diff --git a/routing/README.md b/routing/README.md deleted file mode 100644 index 62cde33e..00000000 --- a/routing/README.md +++ /dev/null @@ -1,1417 +0,0 @@ -# Routing - -## Handlers - -A Handler, as the name implies, handle requests. - -```go -// A Handler responds to an HTTP request. -// It writes reply headers and data to the -// Context.ResponseWriter() and then return. -// Returning signals that the request is finished; -// it is not valid to use the Context after or -// concurrently with the completion of the Handler call. -// -// Depending on the HTTP client software, HTTP protocol version, -// and any intermediaries between the client and the iris server, -// it may not be possible to read from the -// Context.Request().Body after writing to the context.ResponseWriter(). -// Cautious handlers should read the Context.Request().Body first, and then reply. -// -// Except for reading the body, handlers should not modify the provided Context. -// -// If Handler panics, the server (the caller of Handler) assumes that -// the effect of the panic was isolated to the active request. -// It recovers the panic, logs a stack trace to the server error log -// and hangs up the connection. -type Handler func(Context) -``` - -Once the handler is registered, we can use the returned [`Route`](https://godoc.org/github.com/kataras/iris/core/router#Route) instance to give a name to the handler registration for easier lookup in code or in templates. - -For more information, checkout the [Routing and reverse lookups](routing_reverse.md) section. - -## API - -All HTTP methods are supported, developers can also register handlers for same paths for different methods. - -The first parameter is the HTTP Method, -second parameter is the request path of the route, -third variadic parameter should contains one or more iris.Handler executed -by the registered order when a user requests for that specific resouce path from the server. - -Example code: - -```go -app := iris.New() - -app.Handle("GET", "/contact", func(ctx iris.Context) { - ctx.HTML("<h1> Hello from /contact </h1>") -}) -``` - -In order to make things easier for the end-developer, iris provides functions for all HTTP Methods. -The first parameter is the request path of the route, -second variadic parameter should contains one or more iris.Handler executed -by the registered order when a user requests for that specific resouce path from the server. - -Example code: - -```go -app := iris.New() - -// Method: "GET" -app.Get("/", handler) - -// Method: "POST" -app.Post("/", handler) - -// Method: "PUT" -app.Put("/", handler) - -// Method: "DELETE" -app.Delete("/", handler) - -// Method: "OPTIONS" -app.Options("/", handler) - -// Method: "TRACE" -app.Trace("/", handler) - -// Method: "CONNECT" -app.Connect("/", handler) - -// Method: "HEAD" -app.Head("/", handler) - -// Method: "PATCH" -app.Patch("/", handler) - -// register the route for all HTTP Methods -app.Any("/", handler) - -func handler(ctx iris.Context){ - ctx.Writef("Hello from method: %s and path: %s", ctx.Method(), ctx.Path()) -} -``` - -## Grouping Routes - -A set of routes that are being groupped by path prefix can (optionally) share the same middleware handlers and template layout. -A group can have a nested group too. - -`.Party` is being used to group routes, developers can declare an unlimited number of (nested) groups. - -Example code: - -```go -app := iris.New() - -users := app.Party("/users", myAuthMiddlewareHandler) - -// http://localhost:8080/users/42/profile -users.Get("/{id:int}/profile", userProfileHandler) -// http://localhost:8080/users/messages/1 -users.Get("/inbox/{id:int}", userMessageHandler) -``` - -The same could be also written using a function which accepts the child router(the Party). - -```go -app := iris.New() - -app.PartyFunc("/users", func(users iris.Party) { - users.Use(myAuthMiddlewareHandler) - - // http://localhost:8080/users/42/profile - users.Get("/{id:int}/profile", userProfileHandler) - // http://localhost:8080/users/messages/1 - users.Get("/inbox/{id:int}", userMessageHandler) -}) -``` - -> `id:int` is a (typed) dynamic path parameter, learn more by scrolling down. - -# Dynamic Path Parameters - -Iris has the easiest and the most powerful routing process you have ever meet. - -At the same time, -Iris has its own interpeter(yes like a programming language) -for route's path syntax and their dynamic path parameters parsing and evaluation. -We call them "macros" for shortcut. - -How? It calculates its needs and if not any special regexp needed then it just -registers the route with the low-level path syntax, -otherwise it pre-compiles the regexp and adds the necessary middleware(s). That means that you have zero performance cost compared to other routers or web frameworks. - -Standard macro types for route path parameters - -```sh -+------------------------+ -| {param:string} | -+------------------------+ -string type -anything - -+------------------------+ -| {param:int} | -+------------------------+ -int type -only numbers (0-9) - -+------------------------+ -| {param:long} | -+------------------------+ -int64 type -only numbers (0-9) - -+------------------------+ -| {param:boolean} | -+------------------------+ -bool type -only "1" or "t" or "T" or "TRUE" or "true" or "True" -or "0" or "f" or "F" or "FALSE" or "false" or "False" - -+------------------------+ -| {param:alphabetical} | -+------------------------+ -alphabetical/letter type -letters only (upper or lowercase) - -+------------------------+ -| {param:file} | -+------------------------+ -file type -letters (upper or lowercase) -numbers (0-9) -underscore (_) -dash (-) -point (.) -no spaces ! or other character - -+------------------------+ -| {param:path} | -+------------------------+ -path type -anything, should be the last part, more than one path segment, -i.e: /path1/path2/path3 , ctx.Params().Get("param") == "/path1/path2/path3" -``` - -If type is missing then parameter's type is defaulted to string, so -`{param} == {param:string}`. - -If a function not found on that type then the `string` macro type's functions are being used. - -Besides the fact that iris provides the basic types and some default "macro funcs" -you are able to register your own too!. - -Register a named path parameter function - -```go -app.Macros().Int.RegisterFunc("min", func(argument int) func(paramValue string) bool { - // [...] - return true - // -> true means valid, false means invalid fire 404 or if "else 500" is appended to the macro syntax then internal server error. -}) -``` - -At the `func(argument ...)` you can have any standard type, it will be validated before the server starts so don't care about any performance cost there, the only thing it runs at serve time is the returning `func(paramValue string) bool`. - -```go -{param:string equal(iris)} , "iris" will be the argument here: -app.Macros().String.RegisterFunc("equal", func(argument string) func(paramValue string) bool { - return func(paramValue string){ return argument == paramValue } -}) -``` - -Example Code: - -```go -app := iris.New() -// you can use the "string" type which is valid for a single path parameter that can be anything. -app.Get("/username/{name}", func(ctx iris.Context) { - ctx.Writef("Hello %s", ctx.Params().Get("name")) -}) // type is missing = {name:string} - -// Let's register our first macro attached to int macro type. -// "min" = the function -// "minValue" = the argument of the function -// func(string) bool = the macro's path parameter evaluator, this executes in serve time when -// a user requests a path which contains the :int macro type with the min(...) macro parameter function. -app.Macros().Int.RegisterFunc("min", func(minValue int) func(string) bool { - // do anything before serve here [...] - // at this case we don't need to do anything - return func(paramValue string) bool { - n, err := strconv.Atoi(paramValue) - if err != nil { - return false - } - return n >= minValue - } -}) - -// http://localhost:8080/profile/id>=1 -// this will throw 404 even if it's found as route on : /profile/0, /profile/blabla, /profile/-1 -// macro parameter functions are optional of course. -app.Get("/profile/{id:int min(1)}", func(ctx iris.Context) { - // second parameter is the error but it will always nil because we use macros, - // the validaton already happened. - id, _ := ctx.Params().GetInt("id") - ctx.Writef("Hello id: %d", id) -}) - -// to change the error code per route's macro evaluator: -app.Get("/profile/{id:int min(1)}/friends/{friendid:int min(1) else 504}", func(ctx iris.Context) { - id, _ := ctx.Params().GetInt("id") - friendid, _ := ctx.Params().GetInt("friendid") - ctx.Writef("Hello id: %d looking for friend id: ", id, friendid) -}) // this will throw e 504 error code instead of 404 if all route's macros not passed. - -// http://localhost:8080/game/a-zA-Z/level/0-9 -// remember, alphabetical is lowercase or uppercase letters only. -app.Get("/game/{name:alphabetical}/level/{level:int}", func(ctx iris.Context) { - ctx.Writef("name: %s | level: %s", ctx.Params().Get("name"), ctx.Params().Get("level")) -}) - -// let's use a trivial custom regexp that validates a single path parameter -// which its value is only lowercase letters. - -// http://localhost:8080/lowercase/anylowercase -app.Get("/lowercase/{name:string regexp(^[a-z]+)}", func(ctx iris.Context) { - ctx.Writef("name should be only lowercase, otherwise this handler will never executed: %s", ctx.Params().Get("name")) -}) - -// http://localhost:8080/single_file/app.js -app.Get("/single_file/{myfile:file}", func(ctx iris.Context) { - ctx.Writef("file type validates if the parameter value has a form of a file name, got: %s", ctx.Params().Get("myfile")) -}) - -// http://localhost:8080/myfiles/any/directory/here/ -// this is the only macro type that accepts any number of path segments. -app.Get("/myfiles/{directory:path}", func(ctx iris.Context) { - ctx.Writef("path type accepts any number of path segments, path after /myfiles/ is: %s", ctx.Params().Get("directory")) -}) - -app.Run(iris.Addr(":8080")) -} -``` - -A **path parameter name should contain only alphabetical letters. Symbols like '_' and numbers are NOT allowed**. - -Last, do not confuse `ctx.Params()` with `ctx.Values()`. -Path parameter's values goes to `ctx.Params()` and context's local storage -that can be used to communicate between handlers and middleware(s) goes to -`ctx.Values()`. - -# Routing and reverse lookups - -As mentioned in the [Handlers](handlers.md) chapter, Iris provides several handler registration methods, each of which returns a [`Route`](https://godoc.org/github.com/kataras/iris/core/router#Route) instance. - -## Route naming - -Route naming is easy, since we just call the returned `*Route` with a `Name` field to define a name: - -```go -package main - -import ( - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - // define a function - h := func(ctx iris.Context) { - ctx.HTML("<b>Hi</b1>") - } - - // handler registration and naming - home := app.Get("/", h) - home.Name = "home" - // or - app.Get("/about", h).Name = "about" - app.Get("/page/{id}", h).Name = "page" - - app.Run(iris.Addr(":8080")) -} -``` - -## Route reversing AKA generating URLs from the route name - -When we register the handlers for a specific path, we get the ability to create URLs based on the structured data we pass to Iris. In the example above, we've named three routers, one of which even takes parameters. If we're using the default `html/template` view engine, we can use a simple action to reverse the routes (and generae actual URLs): - -```sh -Home: {{ urlpath "home" }} -About: {{ urlpath "about" }} -Page 17: {{ urlpath "page" "17" }} -``` - -Above code would generate the following output: - -```sh -Home: http://localhost:8080/ -About: http://localhost:8080/about -Page 17: http://localhost:8080/page/17 -``` - -## Using route names in code - -We can use the following methods/functions to work with named routes (and their parameters): - -* [`GetRoutes`](https://godoc.org/github.com/kataras/iris/core/router#APIBuilder.GetRoutes) function to get all registered routes -* [`GetRoute(routeName string)`](https://godoc.org/github.com/kataras/iris/core/router#APIBuilder.GetRoute) method to retrieve a route by name -* [`URL(routeName string, paramValues ...interface{})`](https://godoc.org/github.com/kataras/iris/core/router#RoutePathReverser.URL) method to generate url string based on supplied parameters -* [`Path(routeName string, paramValues ...interface{}`](https://godoc.org/github.com/kataras/iris/core/router#RoutePathReverser.Path) method to generate just the path (without host and protocol) portion of the URL based on provided values - -## Examples - -Check out the [https://github.com/kataras/iris/tree/master/_examples/view/template_html_4](https://github.com/kataras/iris/tree/master/_examples/view/template_html_4) example for more details. - -# Middleware - -When we talk about Middleware in Iris we're talking about running code before and/or after our main handler code in a HTTP request lifecycle. For example, logging middleware might write the incoming request details to a log, then call the handler code, before writing details about the response to the log. One of the cool things about middleware is that these units are extremely flexible and reusable. - -A middleware is just a **Handler** form of `func(ctx iris.Context)`, the middleware is being executed when the previous middleware calls the `ctx.Next()`, this can be used for authentication, i.e: if logged in then `ctx.Next()` otherwise fire an error response. - -## Writing a middleware - -```go -package main - -import "github.com/kataras/iris" - -func main() { - app := iris.New() - // or app.Use(before) and app.Done(after). - app.Get("/", before, mainHandler, after) - app.Run(iris.Addr(":8080")) -} - -func before(ctx iris.Context) { - shareInformation := "this is a sharable information between handlers" - - requestPath := ctx.Path() - println("Before the mainHandler: " + requestPath) - - ctx.Values().Set("info", shareInformation) - ctx.Next() // execute the next handler, in this case the main one. -} - -func after(ctx iris.Context) { - println("After the mainHandler") -} - -func mainHandler(ctx iris.Context) { - println("Inside mainHandler") - - // take the info from the "before" handler. - info := ctx.Values().GetString("info") - - // write something to the client as a response. - ctx.HTML("<h1>Response</h1>") - ctx.HTML("<br/> Info: " + info) - - ctx.Next() // execute the "after". -} -``` - -```bash -$ go run main.go # and navigate to the http://localhost:8080 -Now listening on: http://localhost:8080 -Application started. Press CTRL+C to shut down. -Before the mainHandler: / -Inside mainHandler -After the mainHandler -``` - -### Globally - -```go -package main - -import "github.com/kataras/iris" - -func main() { - app := iris.New() - - // register our routes. - app.Get("/", indexHandler) - app.Get("/contact", contactHandler) - - // Order of those calls doesn't matter, `UseGlobal` and `DoneGlobal` - // are applied to existing routes and future routes. - // - // Remember: the `Use` and `Done` are applied to the current party's and its children, - // so if we used the `app.Use/Don`e before the routes registration - // it would work like UseGlobal/DoneGlobal in this case, because the `app` is the root party. - // - // See `app.Party/PartyFunc` for more. - app.UseGlobal(before) - app.DoneGlobal(after) - - app.Run(iris.Addr(":8080")) -} - -func before(ctx iris.Context) { - // [...] -} - -func after(ctx iris.Context) { - // [...] -} - -func indexHandler(ctx iris.Context) { - // write something to the client as a response. - ctx.HTML("<h1>Index</h1>") - - ctx.Next() // execute the "after" handler registered via `Done`. -} - -func contactHandler(ctx iris.Context) { - // write something to the client as a response. - ctx.HTML("<h1>Contact</h1>") - - ctx.Next() // execute the "after" handler registered via `Done`. -} -``` - -## [Explore](https://github.com/kataras/iris/tree/master/middleware) - -# Wrapping the Router - -**Very rare**, you may never need that but it's here in any case you need it. - -There are times you need to override or decide whether the Router will be executed on an incoming request. If you've any previous experience with the `net/http` and other web frameworks this function will be familiar with you (it has the form of a net/http middleware, but instead of accepting the next handler it accepts the Router as a function to be executed or not). - -```go -// WrapperFunc is used as an expected input parameter signature -// for the WrapRouter. It's a "low-level" signature which is compatible -// with the net/http. -// It's being used to run or no run the router based on a custom logic. -type WrapperFunc func(w http.ResponseWriter, r *http.Request, firstNextIsTheRouter http.HandlerFunc) - -// WrapRouter adds a wrapper on the top of the main router. -// Usually it's useful for third-party middleware -// when need to wrap the entire application with a middleware like CORS. -// -// Developers can add more than one wrappers, -// those wrappers' execution comes from last to first. -// That means that the second wrapper will wrap the first, and so on. -// -// Before build. -func WrapRouter(wrapperFunc WrapperFunc) -``` - -Iris' router searches for its routes based on the `HTTP Method` a Router Wrapper can override that behavior and execute custom code. - -Example Code: - -```go -package main - -import ( - "net/http" - "strings" - - "github.com/kataras/iris" -) - -// In this example you'll just see one use case of .WrapRouter. -// You can use the .WrapRouter to add custom logic when or when not the router should -// be executed in order to execute the registered routes' handlers. -// -// To see how you can serve files on root "/" without a custom wrapper -// just navigate to the "file-server/single-page-application" example. -// -// This is just for the proof of concept, you can skip this tutorial if it's too much for you. - - -func main() { - app := iris.New() - - app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) { - ctx.HTML("<b>Resource Not found</b>") - }) - - app.Get("/", func(ctx iris.Context) { - ctx.ServeFile("./public/index.html", false) - }) - - app.Get("/profile/{username}", func(ctx iris.Context) { - ctx.Writef("Hello %s", ctx.Params().Get("username")) - }) - - // serve files from the root "/", if we used .StaticWeb it could override - // all the routes because of the underline need of wildcard. - // Here we will see how you can by-pass this behavior - // by creating a new file server handler and - // setting up a wrapper for the router(like a "low-level" middleware) - // in order to manually check if we want to process with the router as normally - // or execute the file server handler instead. - - // use of the .StaticHandler - // which is the same as StaticWeb but it doesn't - // registers the route, it just returns the handler. - fileServer := app.StaticHandler("./public", false, false) - - // wrap the router with a native net/http handler. - // if url does not contain any "." (i.e: .css, .js...) - // (depends on the app , you may need to add more file-server exceptions), - // then the handler will execute the router that is responsible for the - // registered routes (look "/" and "/profile/{username}") - // if not then it will serve the files based on the root "/" path. - app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) { - path := r.URL.Path - // Note that if path has suffix of "index.html" it will auto-permant redirect to the "/", - // so our first handler will be executed instead. - - if !strings.Contains(path, ".") { - // if it's not a resource then continue to the router as normally. <-- IMPORTANT - router(w, r) - return - } - // acquire and release a context in order to use it to execute - // our file server - // remember: we use net/http.Handler because here we are in the "low-level", before the router itself. - ctx := app.ContextPool.Acquire(w, r) - fileServer(ctx) - app.ContextPool.Release(ctx) - }) - - // http://localhost:8080 - // http://localhost:8080/index.html - // http://localhost:8080/app.js - // http://localhost:8080/css/main.css - // http://localhost:8080/profile/anyusername - app.Run(iris.Addr(":8080")) - - // Note: In this example we just saw one use case, - // you may want to .WrapRouter or .Downgrade in order to bypass the iris' default router, i.e: - // you can use that method to setup custom proxies too. - // - // If you just want to serve static files on other path than root - // you can just use the StaticWeb, i.e: - // .StaticWeb("/static", "./public") - // ________________________________requestPath, systemPath -} -``` - -There is not much to say here, it's just a function wrapper which accepts the native response writer and request and the next handler which is the Iris' Router itself, it's being or not executed whether is called or not, **it's a middleware for the whole Router**. - -# Error handlers - -You can define your own handlers when a specific http error code occurs. - -> Error codes are the http status codes that are bigger or equal to 400, like 404 not found and 500 internal server. - -Example code: - -```go -package main - -import "github.com/kataras/iris" - -func main(){ - app := iris.New() - app.OnErrorCode(iris.StatusNotFound, notFound) - app.OnErrorCode(iris.StatusInternalServerError, internalServerError) - // to register a handler for all "error" status codes(context.StatusCodeNotSuccessful) - // defaults to < 200 || >= 400: - // app.OnAnyErrorCode(handler) - app.Get("/", index) - app.Run(iris.Addr(":8080")) -} - -func notFound(ctx iris.Context) { - // when 404 then render the template $views_dir/errors/404.html - ctx.View("errors/404.html") -} - -func internalServerError(ctx iris.Context) { - ctx.WriteString("Oups something went wrong, try again") -} - -func index(ctx context.Context) { - ctx.View("index.html") -} -``` - -# Context Outline - -The `iris.Context` source code can be found [here](https://github.com/kataras/iris/blob/master/context/context.go). Keep note using an IDE/Editors with `auto-complete` feature will help you a lot. - -```go -// Context is the midle-man server's "object" for the clients. -// -// A New context is being acquired from a sync.Pool on each connection. -// The Context is the most important thing on the iris's http flow. -// -// Developers send responses to the client's request through a Context. -// Developers get request information from the client's request a Context. -// -// This context is an implementation of the context.Context sub-package. -// context.Context is very extensible and developers can override -// its methods if that is actually needed. -type Context interface { - // ResponseWriter returns an http.ResponseWriter compatible response writer, as expected. - ResponseWriter() ResponseWriter - // ResetResponseWriter should change or upgrade the Context's ResponseWriter. - ResetResponseWriter(ResponseWriter) - - // Request returns the original *http.Request, as expected. - Request() *http.Request - - // SetCurrentRouteName sets the route's name internally, - // in order to be able to find the correct current "read-only" Route when - // end-developer calls the `GetCurrentRoute()` function. - // It's being initialized by the Router, if you change that name - // manually nothing really happens except that you'll get other - // route via `GetCurrentRoute()`. - // Instead, to execute a different path - // from this context you should use the `Exec` function - // or change the handlers via `SetHandlers/AddHandler` functions. - SetCurrentRouteName(currentRouteName string) - // GetCurrentRoute returns the current registered "read-only" route that - // was being registered to this request's path. - GetCurrentRoute() RouteReadOnly - - // Do calls the SetHandlers(handlers) - // and executes the first handler, - // handlers should not be empty. - // - // It's used by the router, developers may use that - // to replace and execute handlers immediately. - Do(Handlers) - - // AddHandler can add handler(s) - // to the current request in serve-time, - // these handlers are not persistenced to the router. - // - // Router is calling this function to add the route's handler. - // If AddHandler called then the handlers will be inserted - // to the end of the already-defined route's handler. - // - AddHandler(...Handler) - // SetHandlers replaces all handlers with the new. - SetHandlers(Handlers) - // Handlers keeps tracking of the current handlers. - Handlers() Handlers - - // HandlerIndex sets the current index of the - // current context's handlers chain. - // If -1 passed then it just returns the - // current handler index without change the current index.rns that index, useless return value. - // - // Look Handlers(), Next() and StopExecution() too. - HandlerIndex(n int) (currentIndex int) - // Proceed is an alternative way to check if a particular handler - // has been executed and called the `ctx.Next` function inside it. - // This is useful only when you run a handler inside - // another handler. It justs checks for before index and the after index. - // - // A usecase example is when you want to execute a middleware - // inside controller's `BeginRequest` that calls the `ctx.Next` inside it. - // The Controller looks the whole flow (BeginRequest, method handler, EndRequest) - // as one handler, so `ctx.Next` will not be reflected to the method handler - // if called from the `BeginRequest`. - // - // Although `BeginRequest` should NOT be used to call other handlers, - // the `BeginRequest` has been introduced to be able to set - // common data to all method handlers before their execution. - // Controllers can accept middleware(s) from the MVC's Application's Router as normally. - // - // That said let's see an example of `ctx.Proceed`: - // - // var authMiddleware = basicauth.New(basicauth.Config{ - // Users: map[string]string{ - // "admin": "password", - // }, - // }) - // - // func (c *UsersController) BeginRequest(ctx iris.Context) { - // if !ctx.Proceed(authMiddleware) { - // ctx.StopExecution() - // } - // } - // This Get() will be executed in the same handler as `BeginRequest`, - // internally controller checks for `ctx.StopExecution`. - // So it will not be fired if BeginRequest called the `StopExecution`. - // func(c *UsersController) Get() []models.User { - // return c.Service.GetAll() - //} - // Alternative way is `!ctx.IsStopped()` if middleware make use of the `ctx.StopExecution()` on failure. - Proceed(Handler) bool - // HandlerName returns the current handler's name, helpful for debugging. - HandlerName() string - // Next calls all the next handler from the handlers chain, - // it should be used inside a middleware. - // - // Note: Custom context should override this method in order to be able to pass its own context.Context implementation. - Next() - // NextOr checks if chain has a next handler, if so then it executes it - // otherwise it sets a new chain assigned to this Context based on the given handler(s) - // and executes its first handler. - // - // Returns true if next handler exists and executed, otherwise false. - // - // Note that if no next handler found and handlers are missing then - // it sends a Status Not Found (404) to the client and it stops the execution. - NextOr(handlers ...Handler) bool - // NextOrNotFound checks if chain has a next handler, if so then it executes it - // otherwise it sends a Status Not Found (404) to the client and stops the execution. - // - // Returns true if next handler exists and executed, otherwise false. - NextOrNotFound() bool - // NextHandler returns (it doesn't execute) the next handler from the handlers chain. - // - // Use .Skip() to skip this handler if needed to execute the next of this returning handler. - NextHandler() Handler - // Skip skips/ignores the next handler from the handlers chain, - // it should be used inside a middleware. - Skip() - // StopExecution if called then the following .Next calls are ignored, - // as a result the next handlers in the chain will not be fire. - StopExecution() - // IsStopped checks and returns true if the current position of the Context is 255, - // means that the StopExecution() was called. - IsStopped() bool - - // +------------------------------------------------------------+ - // | Current "user/request" storage | - // | and share information between the handlers - Values(). | - // | Save and get named path parameters - Params() | - // +------------------------------------------------------------+ - - // Params returns the current url's named parameters key-value storage. - // Named path parameters are being saved here. - // This storage, as the whole Context, is per-request lifetime. - Params() *RequestParams - - // Values returns the current "user" storage. - // Named path parameters and any optional data can be saved here. - // This storage, as the whole Context, is per-request lifetime. - // - // You can use this function to Set and Get local values - // that can be used to share information between handlers and middleware. - Values() *memstore.Store - // Translate is the i18n (localization) middleware's function, - // it calls the Get("translate") to return the translated value. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/miscellaneous/i18n - Translate(format string, args ...interface{}) string - - // +------------------------------------------------------------+ - // | Path, Host, Subdomain, IP, Headers etc... | - // +------------------------------------------------------------+ - - // Method returns the request.Method, the client's http method to the server. - Method() string - // Path returns the full request path, - // escaped if EnablePathEscape config field is true. - Path() string - // RequestPath returns the full request path, - // based on the 'escape'. - RequestPath(escape bool) string - - // Host returns the host part of the current url. - Host() string - // Subdomain returns the subdomain of this request, if any. - // Note that this is a fast method which does not cover all cases. - Subdomain() (subdomain string) - // IsWWW returns true if the current subdomain (if any) is www. - IsWWW() bool - // RemoteAddr tries to parse and return the real client's request IP. - // - // Based on allowed headers names that can be modified from Configuration.RemoteAddrHeaders. - // - // If parse based on these headers fail then it will return the Request's `RemoteAddr` field - // which is filled by the server before the HTTP handler. - // - // Look `Configuration.RemoteAddrHeaders`, - // `Configuration.WithRemoteAddrHeader(...)`, - // `Configuration.WithoutRemoteAddrHeader(...)` for more. - RemoteAddr() string - // GetHeader returns the request header's value based on its name. - GetHeader(name string) string - // IsAjax returns true if this request is an 'ajax request'( XMLHttpRequest) - // - // There is no a 100% way of knowing that a request was made via Ajax. - // You should never trust data coming from the client, they can be easily overcome by spoofing. - // - // Note that "X-Requested-With" Header can be modified by any client(because of "X-"), - // so don't rely on IsAjax for really serious stuff, - // try to find another way of detecting the type(i.e, content type), - // there are many blogs that describe these problems and provide different kind of solutions, - // it's always depending on the application you're building, - // this is the reason why this `IsAjax`` is simple enough for general purpose use. - // - // Read more at: https://developer.mozilla.org/en-US/docs/AJAX - // and https://xhr.spec.whatwg.org/ - IsAjax() bool - // IsMobile checks if client is using a mobile device(phone or tablet) to communicate with this server. - // If the return value is true that means that the http client using a mobile - // device to communicate with the server, otherwise false. - // - // Keep note that this checks the "User-Agent" request header. - IsMobile() bool - // +------------------------------------------------------------+ - // | Response Headers helpers | - // +------------------------------------------------------------+ - - // Header adds a header to the response writer. - Header(name string, value string) - - // ContentType sets the response writer's header key "Content-Type" to the 'cType'. - ContentType(cType string) - // GetContentType returns the response writer's header value of "Content-Type" - // which may, setted before with the 'ContentType'. - GetContentType() string - - // GetContentLength returns the request's header value of "Content-Length". - // Returns 0 if header was unable to be found or its value was not a valid number. - GetContentLength() int64 - - // StatusCode sets the status code header to the response. - // Look .GetStatusCode too. - StatusCode(statusCode int) - // GetStatusCode returns the current status code of the response. - // Look StatusCode too. - GetStatusCode() int - - // Redirect sends a redirect response to the client - // to a specific url or relative path. - // accepts 2 parameters string and an optional int - // first parameter is the url to redirect - // second parameter is the http status should send, - // default is 302 (StatusFound), - // you can set it to 301 (Permant redirect) - // or 303 (StatusSeeOther) if POST method, - // or StatusTemporaryRedirect(307) if that's nessecery. - Redirect(urlToRedirect string, statusHeader ...int) - - // +------------------------------------------------------------+ - // | Various Request and Post Data | - // +------------------------------------------------------------+ - - // URLParam returns true if the url parameter exists, otherwise false. - URLParamExists(name string) bool - // URLParamDefault returns the get parameter from a request, - // if not found then "def" is returned. - URLParamDefault(name string, def string) string - // URLParam returns the get parameter from a request, if any. - URLParam(name string) string - // URLParamTrim returns the url query parameter with trailing white spaces removed from a request. - URLParamTrim(name string) string - // URLParamTrim returns the escaped url query parameter from a request. - URLParamEscape(name string) string - // URLParamInt returns the url query parameter as int value from a request, - // returns -1 and an error if parse failed. - URLParamInt(name string) (int, error) - // URLParamIntDefault returns the url query parameter as int value from a request, - // if not found or parse failed then "def" is returned. - URLParamIntDefault(name string, def int) int - // URLParamInt64 returns the url query parameter as int64 value from a request, - // returns -1 and an error if parse failed. - URLParamInt64(name string) (int64, error) - // URLParamInt64Default returns the url query parameter as int64 value from a request, - // if not found or parse failed then "def" is returned. - URLParamInt64Default(name string, def int64) int64 - // URLParamFloat64 returns the url query parameter as float64 value from a request, - // returns -1 and an error if parse failed. - URLParamFloat64(name string) (float64, error) - // URLParamFloat64Default returns the url query parameter as float64 value from a request, - // if not found or parse failed then "def" is returned. - URLParamFloat64Default(name string, def float64) float64 - // URLParamBool returns the url query parameter as boolean value from a request, - // returns an error if parse failed or not found. - URLParamBool(name string) (bool, error) - // URLParams returns a map of GET query parameters separated by comma if more than one - // it returns an empty map if nothing found. - URLParams() map[string]string - - // FormValueDefault returns a single parsed form value by its "name", - // including both the URL field's query parameters and the POST or PUT form data. - // - // Returns the "def" if not found. - FormValueDefault(name string, def string) string - // FormValue returns a single parsed form value by its "name", - // including both the URL field's query parameters and the POST or PUT form data. - FormValue(name string) string - // FormValues returns the parsed form data, including both the URL - // field's query parameters and the POST or PUT form data. - // - // The default form's memory maximum size is 32MB, it can be changed by the - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // NOTE: A check for nil is necessary. - FormValues() map[string][]string - - // PostValueDefault returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name". - // - // If not found then "def" is returned instead. - PostValueDefault(name string, def string) string - // PostValue returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name" - PostValue(name string) string - // PostValueTrim returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", without trailing spaces. - PostValueTrim(name string) string - // PostValueInt returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int. - // - // If not found returns -1 and a non-nil error. - PostValueInt(name string) (int, error) - // PostValueIntDefault returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int. - // - // If not found returns or parse errors the "def". - PostValueIntDefault(name string, def int) int - // PostValueInt64 returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found returns -1 and a no-nil error. - PostValueInt64(name string) (int64, error) - // PostValueInt64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as int64. - // - // If not found or parse errors returns the "def". - PostValueInt64Default(name string, def int64) int64 - // PostValueInt64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found returns -1 and a non-nil error. - PostValueFloat64(name string) (float64, error) - // PostValueInt64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as float64. - // - // If not found or parse errors returns the "def". - PostValueFloat64Default(name string, def float64) float64 - // PostValueInt64Default returns the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name", as bool. - // - // If not found or value is false, then it returns false, otherwise true. - PostValueBool(name string) (bool, error) - // PostValues returns all the parsed form data from POST, PATCH, - // or PUT body parameters based on a "name" as a string slice. - // - // The default form's memory maximum size is 32MB, it can be changed by the - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - PostValues(name string) []string - // FormFile returns the first uploaded file that received from the client. - // - // The default form's memory maximum size is 32MB, it can be changed by the - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/http_request/upload-file - FormFile(key string) (multipart.File, *multipart.FileHeader, error) - // UploadFormFiles uploads any received file(s) from the client - // to the system physical location "destDirectory". - // - // The second optional argument "before" gives caller the chance to - // modify the *miltipart.FileHeader before saving to the disk, - // it can be used to change a file's name based on the current request, - // all FileHeader's options can be changed. You can ignore it if - // you don't need to use this capability before saving a file to the disk. - // - // Note that it doesn't check if request body streamed. - // - // Returns the copied length as int64 and - // a not nil error if at least one new file - // can't be created due to the operating system's permissions or - // http.ErrMissingFile if no file received. - // - // If you want to receive & accept files and manage them manually you can use the `context#FormFile` - // instead and create a copy function that suits your needs, the below is for generic usage. - // - // The default form's memory maximum size is 32MB, it can be changed by the - // `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument. - // - // See `FormFile` to a more controlled to receive a file. - // - // - // Example: https://github.com/kataras/iris/tree/master/_examples/http_request/upload-files - UploadFormFiles(destDirectory string, before ...func(Context, *multipart.FileHeader)) (n int64, err error) - - // +------------------------------------------------------------+ - // | Custom HTTP Errors | - // +------------------------------------------------------------+ - - // NotFound emits an error 404 to the client, using the specific custom error error handler. - // Note that you may need to call ctx.StopExecution() if you don't want the next handlers - // to be executed. Next handlers are being executed on iris because you can alt the - // error code and change it to a more specific one, i.e - // users := app.Party("/users") - // users.Done(func(ctx context.Context){ if ctx.StatusCode() == 400 { /* custom error code for /users */ }}) - NotFound() - - // +------------------------------------------------------------+ - // | Body Readers | - // +------------------------------------------------------------+ - - // SetMaxRequestBodySize sets a limit to the request body size - // should be called before reading the request body from the client. - SetMaxRequestBodySize(limitOverBytes int64) - - // UnmarshalBody reads the request's body and binds it to a value or pointer of any type. - // Examples of usage: context.ReadJSON, context.ReadXML. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-custom-via-unmarshaler/main.go - UnmarshalBody(outPtr interface{}, unmarshaler Unmarshaler) error - // ReadJSON reads JSON from request's body and binds it to a pointer of a value of any json-valid type. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-json/main.go - ReadJSON(jsonObjectPtr interface{}) error - // ReadXML reads XML from request's body and binds it to a pointer of a value of any xml-valid type. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-xml/main.go - ReadXML(xmlObjectPtr interface{}) error - // ReadForm binds the formObject with the form data - // it supports any kind of struct. - // - // Example: https://github.com/kataras/iris/blob/master/_examples/http_request/read-form/main.go - ReadForm(formObjectPtr interface{}) error - - // +------------------------------------------------------------+ - // | Body (raw) Writers | - // +------------------------------------------------------------+ - - // Write writes the data to the connection as part of an HTTP reply. - // - // If WriteHeader has not yet been called, Write calls - // WriteHeader(http.StatusOK) before writing the data. If the Header - // does not contain a Content-Type line, Write adds a Content-Type set - // to the result of passing the initial 512 bytes of written data to - // DetectContentType. - // - // Depending on the HTTP protocol version and the client, calling - // Write or WriteHeader may prevent future reads on the - // Request.Body. For HTTP/1.x requests, handlers should read any - // needed request body data before writing the response. Once the - // headers have been flushed (due to either an explicit Flusher.Flush - // call or writing enough data to trigger a flush), the request body - // may be unavailable. For HTTP/2 requests, the Go HTTP server permits - // handlers to continue to read the request body while concurrently - // writing the response. However, such behavior may not be supported - // by all HTTP/2 clients. Handlers should read before writing if - // possible to maximize compatibility. - Write(body []byte) (int, error) - // Writef formats according to a format specifier and writes to the response. - // - // Returns the number of bytes written and any write error encountered. - Writef(format string, args ...interface{}) (int, error) - // WriteString writes a simple string to the response. - // - // Returns the number of bytes written and any write error encountered. - WriteString(body string) (int, error) - - // SetLastModified sets the "Last-Modified" based on the "modtime" input. - // If "modtime" is zero then it does nothing. - // - // It's mostly internally on core/router and context packages. - // - // Note that modtime.UTC() is being used instead of just modtime, so - // you don't have to know the internals in order to make that works. - SetLastModified(modtime time.Time) - // CheckIfModifiedSince checks if the response is modified since the "modtime". - // Note that it has nothing to do with server-side caching. - // It does those checks by checking if the "If-Modified-Since" request header - // sent by client or a previous server response header - // (e.g with WriteWithExpiration or StaticEmbedded or Favicon etc.) - // is a valid one and it's before the "modtime". - // - // A check for !modtime && err == nil is necessary to make sure that - // it's not modified since, because it may return false but without even - // had the chance to check the client-side (request) header due to some errors, - // like the HTTP Method is not "GET" or "HEAD" or if the "modtime" is zero - // or if parsing time from the header failed. - // - // It's mostly used internally, e.g. `context#WriteWithExpiration`. - // - // Note that modtime.UTC() is being used instead of just modtime, so - // you don't have to know the internals in order to make that works. - CheckIfModifiedSince(modtime time.Time) (bool, error) - // WriteNotModified sends a 304 "Not Modified" status code to the client, - // it makes sure that the content type, the content length headers - // and any "ETag" are removed before the response sent. - // - // It's mostly used internally on core/router/fs.go and context methods. - WriteNotModified() - // WriteWithExpiration like Write but it sends with an expiration datetime - // which is refreshed every package-level `StaticCacheDuration` field. - WriteWithExpiration(body []byte, modtime time.Time) (int, error) - // StreamWriter registers the given stream writer for populating - // response body. - // - // Access to context's and/or its' members is forbidden from writer. - // - // This function may be used in the following cases: - // - // * if response body is too big (more than iris.LimitRequestBodySize(if setted)). - // * if response body is streamed from slow external sources. - // * if response body must be streamed to the client in chunks. - // (aka `http server push`). - // - // receives a function which receives the response writer - // and returns false when it should stop writing, otherwise true in order to continue - StreamWriter(writer func(w io.Writer) bool) - - // +------------------------------------------------------------+ - // | Body Writers with compression | - // +------------------------------------------------------------+ - // ClientSupportsGzip retruns true if the client supports gzip compression. - ClientSupportsGzip() bool - // WriteGzip accepts bytes, which are compressed to gzip format and sent to the client. - // returns the number of bytes written and an error ( if the client doesn' supports gzip compression) - // You may re-use this function in the same handler - // to write more data many times without any troubles. - WriteGzip(b []byte) (int, error) - // TryWriteGzip accepts bytes, which are compressed to gzip format and sent to the client. - // If client does not supprots gzip then the contents are written as they are, uncompressed. - TryWriteGzip(b []byte) (int, error) - // GzipResponseWriter converts the current response writer into a response writer - // which when its .Write called it compress the data to gzip and writes them to the client. - // - // Can be also disabled with its .Disable and .ResetBody to rollback to the usual response writer. - GzipResponseWriter() *GzipResponseWriter - // Gzip enables or disables (if enabled before) the gzip response writer,if the client - // supports gzip compression, so the following response data will - // be sent as compressed gzip data to the client. - Gzip(enable bool) - - // +------------------------------------------------------------+ - // | Rich Body Content Writers/Renderers | - // +------------------------------------------------------------+ - - // ViewLayout sets the "layout" option if and when .View - // is being called afterwards, in the same request. - // Useful when need to set or/and change a layout based on the previous handlers in the chain. - // - // Note that the 'layoutTmplFile' argument can be setted to iris.NoLayout || view.NoLayout - // to disable the layout for a specific view render action, - // it disables the engine's configuration's layout property. - // - // Look .ViewData and .View too. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ - ViewLayout(layoutTmplFile string) - // ViewData saves one or more key-value pair in order to be passed if and when .View - // is being called afterwards, in the same request. - // Useful when need to set or/and change template data from previous hanadlers in the chain. - // - // If .View's "binding" argument is not nil and it's not a type of map - // then these data are being ignored, binding has the priority, so the main route's handler can still decide. - // If binding is a map or context.Map then these data are being added to the view data - // and passed to the template. - // - // After .View, the data are not destroyed, in order to be re-used if needed (again, in the same request as everything else), - // to clear the view data, developers can call: - // ctx.Set(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey(), nil) - // - // If 'key' is empty then the value is added as it's (struct or map) and developer is unable to add other value. - // - // Look .ViewLayout and .View too. - // - // Example: https://github.com/kataras/iris/tree/master/_examples/view/context-view-data/ - ViewData(key string, value interface{}) - // GetViewData returns the values registered by `context#ViewData`. - // The return value is `map[string]interface{}`, this means that - // if a custom struct registered to ViewData then this function - // will try to parse it to map, if failed then the return value is nil - // A check for nil is always a good practise if different - // kind of values or no data are registered via `ViewData`. - // - // Similarly to `viewData := ctx.Values().Get("iris.viewData")` or - // `viewData := ctx.Values().Get(ctx.Application().ConfigurationReadOnly().GetViewDataContextKey())`. - GetViewData() map[string]interface{} - // View renders a template based on the registered view engine(s). - // First argument accepts the filename, relative to the view engine's Directory and Extension, - // i.e: if directory is "./templates" and want to render the "./templates/users/index.html" - // then you pass the "users/index.html" as the filename argument. - // - // The second optional argument can receive a single "view model" - // that will be binded to the view template if it's not nil, - // otherwise it will check for previous view data stored by the `ViewData` - // even if stored at any previous handler(middleware) for the same request. - // - // Look .ViewData` and .ViewLayout too. - // - // Examples: https://github.com/kataras/iris/tree/master/_examples/view - View(filename string, optionalViewModel ...interface{}) error - - // Binary writes out the raw bytes as binary data. - Binary(data []byte) (int, error) - // Text writes out a string as plain text. - Text(text string) (int, error) - // HTML writes out a string as text/html. - HTML(htmlContents string) (int, error) - // JSON marshals the given interface object and writes the JSON response. - JSON(v interface{}, options ...JSON) (int, error) - // JSONP marshals the given interface object and writes the JSON response. - JSONP(v interface{}, options ...JSONP) (int, error) - // XML marshals the given interface object and writes the XML response. - XML(v interface{}, options ...XML) (int, error) - // Markdown parses the markdown to html and renders its result to the client. - Markdown(markdownB []byte, options ...Markdown) (int, error) - // YAML parses the "v" using the yaml parser and renders its result to the client. - YAML(v interface{}) (int, error) - // +------------------------------------------------------------+ - // | Serve files | - // +------------------------------------------------------------+ - - // ServeContent serves content, headers are autoset - // receives three parameters, it's low-level function, instead you can use .ServeFile(string,bool)/SendFile(string,string) - // - // - // You can define your own "Content-Type" with `context#ContentType`, before this function call. - // - // This function doesn't support resuming (by range), - // use ctx.SendFile or router's `StaticWeb` instead. - ServeContent(content io.ReadSeeker, filename string, modtime time.Time, gzipCompression bool) error - // ServeFile serves a file (to send a file, a zip for example to the client you should use the `SendFile` instead) - // receives two parameters - // filename/path (string) - // gzipCompression (bool) - // - // You can define your own "Content-Type" with `context#ContentType`, before this function call. - // - // This function doesn't support resuming (by range), - // use ctx.SendFile or router's `StaticWeb` instead. - // - // Use it when you want to serve dynamic files to the client. - ServeFile(filename string, gzipCompression bool) error - // SendFile sends file for force-download to the client - // - // Use this instead of ServeFile to 'force-download' bigger files to the client. - SendFile(filename string, destinationName string) error - - // +------------------------------------------------------------+ - // | Cookies | - // +------------------------------------------------------------+ - - // SetCookie adds a cookie. - // Use of the "options" is not required, they can be used to amend the "cookie". - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - SetCookie(cookie *http.Cookie, options ...CookieOption) - // SetCookieKV adds a cookie, requires the name(string) and the value(string). - // - // By default it expires at 2 hours and it's added to the root path, - // use the `CookieExpires` and `CookiePath` to modify them. - // Alternatively: ctx.SetCookie(&http.Cookie{...}) - // - // If you want to set custom the path: - // ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored")) - // - // If you want to be visible only to current request path: - // ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath("")) - // More: - // iris.CookieExpires(time.Duration) - // iris.CookieHTTPOnly(false) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - SetCookieKV(name, value string, options ...CookieOption) - // GetCookie returns cookie's value by it's name - // returns empty string if nothing was found. - // - // If you want more than the value then: - // cookie, err := ctx.Request().Cookie("name") - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - GetCookie(name string, options ...CookieOption) string - // RemoveCookie deletes a cookie by it's name and path = "/". - // Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic - RemoveCookie(name string, options ...CookieOption) - // VisitAllCookies takes a visitor which loops - // on each (request's) cookies' name and value. - VisitAllCookies(visitor func(name string, value string)) - - // MaxAge returns the "cache-control" request header's value - // seconds as int64 - // if header not found or parse failed then it returns -1. - MaxAge() int64 - - // +------------------------------------------------------------+ - // | Advanced: Response Recorder and Transactions | - // +------------------------------------------------------------+ - - // Record transforms the context's basic and direct responseWriter to a ResponseRecorder - // which can be used to reset the body, reset headers, get the body, - // get & set the status code at any time and more. - Record() - // Recorder returns the context's ResponseRecorder - // if not recording then it starts recording and returns the new context's ResponseRecorder - Recorder() *ResponseRecorder - // IsRecording returns the response recorder and a true value - // when the response writer is recording the status code, body, headers and so on, - // else returns nil and false. - IsRecording() (*ResponseRecorder, bool) - - // BeginTransaction starts a scoped transaction. - // - // You can search third-party articles or books on how Business Transaction works (it's quite simple, especially here). - // - // Note that this is unique and new - // (=I haver never seen any other examples or code in Golang on this subject, so far, as with the most of iris features...) - // it's not covers all paths, - // such as databases, this should be managed by the libraries you use to make your database connection, - // this transaction scope is only for context's response. - // Transactions have their own middleware ecosystem also, look iris.go:UseTransaction. - // - // See https://github.com/kataras/iris/tree/master/_examples/ for more - BeginTransaction(pipe func(t *Transaction)) - // SkipTransactions if called then skip the rest of the transactions - // or all of them if called before the first transaction - SkipTransactions() - // TransactionsSkipped returns true if the transactions skipped or canceled at all. - TransactionsSkipped() bool - - // Exec calls the `context/Application#ServeCtx` - // based on this context but with a changed method and path - // like it was requested by the user, but it is not. - // - // Offline means that the route is registered to the iris and have all features that a normal route has - // BUT it isn't available by browsing, its handlers executed only when other handler's context call them - // it can validate paths, has sessions, path parameters and all. - // - // You can find the Route by app.GetRoute("theRouteName") - // you can set a route name as: myRoute := app.Get("/mypath", handler)("theRouteName") - // that will set a name to the route and returns its RouteInfo instance for further usage. - // - // It doesn't changes the global state, if a route was "offline" it remains offline. - // - // app.None(...) and app.GetRoutes().Offline(route)/.Online(route, method) - // - // Example: https://github.com/kataras/iris/tree/master/_examples/routing/route-state - // - // User can get the response by simple using rec := ctx.Recorder(); rec.Body()/rec.StatusCode()/rec.Header(). - // - // Context's Values and the Session are kept in order to be able to communicate via the result route. - // - // It's for extreme use cases, 99% of the times will never be useful for you. - Exec(method, path string) - - // RouteExists reports whether a particular route exists - // It will search from the current subdomain of context's host, if not inside the root domain. - RouteExists(method, path string) bool - - // Application returns the iris app instance which belongs to this context. - // Worth to notice that this function returns an interface - // of the Application, which contains methods that are safe - // to be executed at serve-time. The full app's fields - // and methods are not available here for the developer's safety. - Application() Application - - // String returns the string representation of this request. - // Each context has a unique string representation. - // It can be used for simple debugging scenarios, i.e print context as string. - // - // What it returns? A number which declares the length of the - // total `String` calls per executable application, followed - // by the remote IP (the client) and finally the method:url. - String() string -} -``` \ No newline at end of file diff --git a/routing/basic/.dockerignore b/routing/basic/.dockerignore new file mode 100644 index 00000000..ffdca42e --- /dev/null +++ b/routing/basic/.dockerignore @@ -0,0 +1,3 @@ +.git +node_modules +bin \ No newline at end of file diff --git a/routing/basic/Dockerfile b/routing/basic/Dockerfile new file mode 100644 index 00000000..09daa324 --- /dev/null +++ b/routing/basic/Dockerfile @@ -0,0 +1,17 @@ +# docker build -t myapp . +# docker run --rm -it -p 8080:8080 myapp:latest +FROM golang:latest AS builder +RUN apt-get update +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /go/src/app +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/app . +ENTRYPOINT ["./app"] \ No newline at end of file diff --git a/routing/basic/README.md b/routing/basic/README.md new file mode 100644 index 00000000..350562a9 --- /dev/null +++ b/routing/basic/README.md @@ -0,0 +1,27 @@ +# Basic Example + +The only requirement for this example is [Docker](https://docs.docker.com/install/). + +## Docker Compose + +The Docker Compose is pre-installed with Docker for Windows. For linux please follow the steps described at: https://docs.docker.com/compose/install/. + +Build and run the application for linux arch and expose it on http://localhost:8080. + +```sh +$ docker-compose up +``` + +See [docker-compose file](docker-compose.yml). + +## Without Docker Compose + +1. Build the image as "myapp" (docker build) +2. Run the image and map exposed ports (-p 8080:8080) +3. Attach the interactive mode so CTRL/CMD+C signals are respected to shutdown the Iris Server (-it) +4. Cleanup the image on finish (--rm) + +```sh +$ docker build -t myapp . +$ docker run --rm -it -p 8080:8080 myapp:latest +``` diff --git a/routing/basic/docker-compose.yml b/routing/basic/docker-compose.yml new file mode 100644 index 00000000..54c86b33 --- /dev/null +++ b/routing/basic/docker-compose.yml @@ -0,0 +1,8 @@ +# docker-compose up [--build] +version: '3' + +services: + app: + build: . + ports: + - 8080:8080 \ No newline at end of file diff --git a/routing/basic/main.go b/routing/basic/main.go index d694b20c..f1cd1af6 100644 --- a/routing/basic/main.go +++ b/routing/basic/main.go @@ -1,11 +1,12 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) -func main() { +func newApp() *iris.Application { app := iris.New() + app.Logger().SetLevel("debug") // registers a custom handler for 404 not found http (error) status code, // fires when route not found or manually by ctx.StatusCode(iris.StatusNotFound). @@ -17,8 +18,6 @@ func main() { // // Third receiver should contains the route's handler(s), they are executed by order. app.Handle("GET", "/", func(ctx iris.Context) { - // navigate to the middle of $GOPATH/src/github.com/kataras/iris/context/context.go - // to overview all context's method (there a lot of them, read that and you will learn how iris works too) ctx.HTML("Hello from " + ctx.Path()) // Hello from / }) @@ -26,15 +25,55 @@ func main() { ctx.Writef(`Same as app.Handle("GET", "/", [...])`) }) - app.Get("/donate", donateHandler, donateFinishHandler) + // Different path parameters types in the same path. + // Note that: fallback should registered first e.g. {path} {string}, + // because the handler on this case is executing from last to top. + app.Get("/u/{p:path}", func(ctx iris.Context) { + ctx.Writef(":string, :int, :uint, :alphabetical and :path in the same path pattern.") + }) - // Pssst, don't forget dynamic-path example for more "magic"! - app.Get("/api/users/{userid:int min(1)}", func(ctx iris.Context) { - userID, err := ctx.Params().GetInt("userid") + app.Get("/u/{username:string}", func(ctx iris.Context) { + ctx.Writef("before username (string), current route name: %s\n", ctx.RouteName()) + ctx.Next() + }, func(ctx iris.Context) { + ctx.Writef("username (string): %s", ctx.Params().Get("username")) + }) + + app.Get("/u/{firstname:alphabetical}", func(ctx iris.Context) { + ctx.Writef("before firstname (alphabetical), current route name: %s\n", ctx.RouteName()) + ctx.Next() + }, func(ctx iris.Context) { + ctx.Writef("firstname (alphabetical): %s", ctx.Params().Get("firstname")) + }) + + app.Get("/u/{id:int}", func(ctx iris.Context) { + ctx.Writef("before id (int), current route name: %s\n", ctx.RouteName()) + ctx.Next() + }, func(ctx iris.Context) { + ctx.Writef("id (int): %d", ctx.Params().GetIntDefault("id", 0)) + }) + + app.Get("/u/{uid:uint}", func(ctx iris.Context) { + ctx.Writef("before uid (uint), current route name: %s\n", ctx.RouteName()) + ctx.Next() + }, func(ctx iris.Context) { + ctx.Writef("uid (uint): %d", ctx.Params().GetUintDefault("uid", 0)) + }) + + /* + /u/some/path/here maps to :path + /u/abcd maps to :alphabetical (if :alphabetical registered otherwise :string) + /u/42 maps to :uint (if :uint registered otherwise :int) + /u/-1 maps to :int (if :int registered otherwise :string) + /u/abcd123 maps to :string + */ + // Pssst, don't forget dynamic-path example for more "magic"! + app.Get("/api/users/{userid:uint64 min(1)}", func(ctx iris.Context) { + userID, err := ctx.Params().GetUint64("userid") if err != nil { ctx.Writef("error while trying to parse userid parameter," + - "this will never happen if :int is being used because if it's not integer it will fire Not Found automatically.") + "this will never happen if :uint64 is being used because if it's not a valid uint64 it will fire Not Found automatically.") ctx.StatusCode(iris.StatusBadRequest) return } @@ -92,8 +131,9 @@ func main() { { // braces are optional, it's just type of style, to group the routes visually. // http://v1.localhost:8080 + // Note: for versioning-specific features checkout the _examples/routing/versioning instead. v1.Get("/", func(ctx iris.Context) { - ctx.HTML("Version 1 API. go to <a href='" + ctx.Path() + "/api" + "'>/api/users</a>") + ctx.HTML(`Version 1 API. go to <a href="/api/users">/api/users</a>`) }) usersAPI := v1.Party("/api/users") @@ -104,22 +144,27 @@ func main() { }) // http://v1.localhost:8080/api/users/42 usersAPI.Get("/{userid:int}", func(ctx iris.Context) { - ctx.Writef("user with id: %s", ctx.Params().Get("userid")) + ctx.Writef("user with id: %d", ctx.Params().GetIntDefault("userid", 0)) }) } } // wildcard subdomains. - wildcardSubdomain := app.Party("*.") + wildcardSubdomain := app.WildcardSubdomain() { wildcardSubdomain.Get("/", func(ctx iris.Context) { ctx.Writef("Subdomain can be anything, now you're here from: %s", ctx.Subdomain()) }) } + return app +} + +func main() { + app := newApp() + // http://localhost:8080 // http://localhost:8080/home - // http://localhost:8080/donate // http://localhost:8080/api/users/42 // http://localhost:8080/admin // http://localhost:8080/admin/login @@ -128,12 +173,18 @@ func main() { // http://localhost:8080/api/users/blabla // http://localhost:8080/wontfound // + // http://localhost:8080/u/abcd + // http://localhost:8080/u/42 + // http://localhost:8080/u/-1 + // http://localhost:8080/u/abcd123 + // http://localhost:8080/u/some/path/here + // // if hosts edited: // http://v1.localhost:8080 // http://v1.localhost:8080/api/users // http://v1.localhost:8080/api/users/42 // http://anything.localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func adminMiddleware(ctx iris.Context) { @@ -141,24 +192,6 @@ func adminMiddleware(ctx iris.Context) { ctx.Next() // to move to the next handler, or don't that if you have any auth logic. } -func donateHandler(ctx iris.Context) { - ctx.Writef("Just like an inline handler, but it can be " + - "used by other package, anywhere in your project.") - - // let's pass a value to the next handler - // Values is the way handlers(or middleware) are communicating between each other. - ctx.Values().Set("donate_url", "https://github.com/kataras/iris#-people") - ctx.Next() // in order to execute the next handler in the chain, look donate route. -} - -func donateFinishHandler(ctx iris.Context) { - // values can be any type of object so we could cast the value to a string - // but iris provides an easy to do that, if donate_url is not defined, then it returns an empty string instead. - donateURL := ctx.Values().GetString("donate_url") - ctx.Application().Logger().Infof("donate_url value was: " + donateURL) - ctx.Writef("\n\nDonate sent(?).") -} - func notFoundHandler(ctx iris.Context) { ctx.HTML("Custom route for 404 not found http code, here you can render a view, html, json <b>any valid response</b>.") } diff --git a/routing/basic/main_test.go b/routing/basic/main_test.go new file mode 100644 index 00000000..577c4ab8 --- /dev/null +++ b/routing/basic/main_test.go @@ -0,0 +1,88 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +// Shows a very basic usage of the httptest. +// The tests are written in a way to be easy to understand, +// for a more comprehensive testing examples check out the: +// _examples/routing/main_test.go, +// _examples/routing/subdomains/www/main_test.go +// _examples/file-server and e.t.c. +// Almost every example which covers +// a new feature from you to learn +// contains a test file as well. +func TestRoutingBasic(t *testing.T) { + expectedUResponse := func(paramName, paramType, paramValue string) string { + s := fmt.Sprintf("before %s (%s), current route name: GET/u/{%s:%s}\n", paramName, paramType, paramName, paramType) + s += fmt.Sprintf("%s (%s): %s", paramName, paramType, paramValue) + return s + } + + var ( + expectedNotFoundResponse = "Custom route for 404 not found http code, here you can render a view, html, json <b>any valid response</b>." + + expectedIndexResponse = "Hello from /" + expectedHomeResponse = `Same as app.Handle("GET", "/", [...])` + + expectedUpathResponse = ":string, :int, :uint, :alphabetical and :path in the same path pattern." + expectedUStringResponse = expectedUResponse("username", "string", "abcd123") + expectedUIntResponse = expectedUResponse("id", "int", "-1") + expectedUUintResponse = expectedUResponse("uid", "uint", "42") + expectedUAlphabeticalResponse = expectedUResponse("firstname", "alphabetical", "abcd") + + expectedAPIUsersIndexResponse = map[string]interface{}{"user_id": 42} + + expectedAdminIndexResponse = "<h1>Hello from admin/</h1>" + + expectedSubdomainV1IndexResponse = `Version 1 API. go to <a href="/api/users">/api/users</a>` + expectedSubdomainV1APIUsersIndexResponse = "All users" + expectedSubdomainV1APIUsersIndexWithParamResponse = "user with id: 42" + + expectedSubdomainWildcardIndexResponse = "Subdomain can be anything, now you're here from: any-subdomain-here" + ) + + app := newApp() + e := httptest.New(t, app) + + e.GET("/anotfound").Expect().Status(httptest.StatusNotFound). + Body().IsEqual(expectedNotFoundResponse) + + e.GET("/").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedIndexResponse) + e.GET("/home").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedHomeResponse) + + e.GET("/u/some/path/here").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedUpathResponse) + e.GET("/u/abcd123").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedUStringResponse) + e.GET("/u/-1").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedUIntResponse) + e.GET("/u/42").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedUUintResponse) + e.GET("/u/abcd").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedUAlphabeticalResponse) + + e.GET("/api/users/42").Expect().Status(httptest.StatusOK). + JSON().IsEqual(expectedAPIUsersIndexResponse) + + e.GET("/admin").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedAdminIndexResponse) + + e.Request("GET", "/").WithURL("http://v1.example.com").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedSubdomainV1IndexResponse) + + e.Request("GET", "/api/users").WithURL("http://v1.example.com").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedSubdomainV1APIUsersIndexResponse) + + e.Request("GET", "/api/users/42").WithURL("http://v1.example.com").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedSubdomainV1APIUsersIndexWithParamResponse) + + e.Request("GET", "/").WithURL("http://any-subdomain-here.example.com").Expect().Status(httptest.StatusOK). + Body().IsEqual(expectedSubdomainWildcardIndexResponse) +} diff --git a/routing/conditional-chain/main.go b/routing/conditional-chain/main.go new file mode 100644 index 00000000..4d0747f6 --- /dev/null +++ b/routing/conditional-chain/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func newApp() *iris.Application { + app := iris.New() + v1 := app.Party("/api/v1") + + myFilter := func(ctx iris.Context) bool { + // don't do that on production, use session or/and database calls and etc. + ok, _ := ctx.URLParamBool("admin") + return ok + } + + onlyWhenFilter1 := func(ctx iris.Context) { + ctx.Application().Logger().Infof("admin: %#+v", ctx.URLParams()) + ctx.Writef("<title>Admin</title>\n") + ctx.Next() + } + + onlyWhenFilter2 := func(ctx iris.Context) { + // You can always use the per-request storage + // to perform actions like this ofc. + // + // this handler: ctx.Values().Set("is_admin", true) + // next handler: isAdmin := ctx.Values().GetBoolDefault("is_admin", false) + // + // but, let's simplify it: + ctx.HTML("<h1>Hello Admin</h1><br>") + ctx.Next() + } + + // HERE: + // It can be registered anywhere, as a middleware. + // It will fire the `onlyWhenFilter1` and `onlyWhenFilter2` as middlewares (with ctx.Next()) + // if myFilter pass otherwise it will just continue the handler chain with ctx.Next() by ignoring + // the `onlyWhenFilter1` and `onlyWhenFilter2`. + myMiddleware := iris.NewConditionalHandler(myFilter, onlyWhenFilter1, onlyWhenFilter2) + + v1UsersRouter := v1.Party("/users", myMiddleware) + v1UsersRouter.Get("/", func(ctx iris.Context) { + ctx.HTML("requested: <b>/api/v1/users</b>") + }) + + return app +} + +func main() { + app := newApp() + + // http://localhost:8080/api/v1/users + // http://localhost:8080/api/v1/users?admin=true + app.Listen(":8080") +} diff --git a/routing/conditional-chain/main_test.go b/routing/conditional-chain/main_test.go new file mode 100644 index 00000000..0d2a0542 --- /dev/null +++ b/routing/conditional-chain/main_test.go @@ -0,0 +1,17 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestNewConditionalHandler(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + e.GET("/api/v1/users").Expect().Status(httptest.StatusOK). + Body().IsEqual("requested: <b>/api/v1/users</b>") + e.GET("/api/v1/users").WithQuery("admin", "true").Expect().Status(httptest.StatusOK). + Body().IsEqual("<title>Admin</title>\n<h1>Hello Admin</h1><br>requested: <b>/api/v1/users</b>") +} diff --git a/routing/custom-context/main.go b/routing/custom-context/main.go new file mode 100644 index 00000000..6148325d --- /dev/null +++ b/routing/custom-context/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "sync" + + "github.com/kataras/iris/v12" +) + +func main() { + // 1. Create the iris app instance. + app := iris.New() + + // 2. Create the Context Wrapper which will be used to wrap the handlers + // that expect a *myCustomContext instead of iris.Context. + w := iris.NewContextWrapper(&myCustomContextPool{}) + // OR: + // w := iris.NewContextWrapper(iris.NewContextPool[myCustomContext, *myCustomContext]()) + // The example custom context pool operates exactly the same as the result of iris.NewContextPool. + + // 3. Register the handler(s) which expects a *myCustomContext instead of iris.Context. + // The `w.Handler` will wrap the handler and will call the `Acquire` and `Release` + // methods of the `myCustomContextPool` to get and release the *myCustomContext. + app.Get("/", w.Handler(index)) + + // 4. Start the server. + app.Listen(":8080") +} + +func index(ctx *myCustomContext) { + ctx.HTML("<h1>Hello, World!</h1>") +} + +/* + Custom Context Pool +*/ +// Create the context sync pool for our custom context, +// the pool must implement Acquire() T and Release(T) methods to satisfy the iris.ContextPool interface. +type myCustomContextPool struct { + pool sync.Pool +} + +// Acquire returns a new custom context from the pool. +func (p *myCustomContextPool) Acquire(ctx iris.Context) *myCustomContext { + v := p.pool.Get() + if v == nil { + v = &myCustomContext{ + Context: ctx, + // custom fields here... + } + } + + return v.(*myCustomContext) +} + +// Release puts a custom context back to the pool. +func (p *myCustomContextPool) Release(t *myCustomContext) { + // You can take advantage of this method to clear the context + // and re-use it on the Acquire method, use the sync.Pool. + p.pool.Put(t) +} + +/* + Custom Context +*/ +// Create a custom context. +type myCustomContext struct { + // It's just an embedded field which is set on AcquireFunc, + // so you can use myCustomContext with the same methods as iris.Context, + // override existing iris.Context's methods or add custom methods. + // You can use the `Context` field to access the original context. + iris.Context +} + +// SetContext sets the original iris.Context, +// should be implemented by custom context type(s) when +// the ContextWrapper uses a context Pool through the iris.NewContextPool function. +// Comment line 15, uncomment line 17 and the method below. +func (c *myCustomContext) SetContext(ctx iris.Context) { + c.Context = ctx +} + +func (c *myCustomContext) HTML(format string, args ...interface{}) (int, error) { + c.Application().Logger().Info("HTML was called from custom Context") + + return c.Context.HTML(format, args...) +} diff --git a/routing/custom-context/method-overriding/main.go b/routing/custom-context/method-overriding/main.go deleted file mode 100644 index 8747be93..00000000 --- a/routing/custom-context/method-overriding/main.go +++ /dev/null @@ -1,90 +0,0 @@ -package main - -// In this package I'll show you how to override the existing Context's functions and methods. -// You can easly navigate to the custom-context example to see how you can add new functions -// to your own context (need a custom handler). -// -// This way is far easier to understand and it's faster when you want to override existing methods: -import ( - "reflect" - - "github.com/kataras/iris" - "github.com/kataras/iris/context" -) - -// Create your own custom Context, put any fields you wanna need. -type MyContext struct { - // Optional Part 1: embed (optional but required if you don't want to override all context's methods) - context.Context // it's the context/context.go#context struct but you don't need to know it. -} - -var _ context.Context = &MyContext{} // optionally: validate on compile-time if MyContext implements context.Context. - -// The only one important if you will override the Context -// with an embedded context.Context inside it. -// Required in order to run the handlers via this "*MyContext". -func (ctx *MyContext) Do(handlers context.Handlers) { - context.Do(ctx, handlers) -} - -// The second one important if you will override the Context -// with an embedded context.Context inside it. -// Required in order to run the chain of handlers via this "*MyContext". -func (ctx *MyContext) Next() { - context.Next(ctx) -} - -// Override any context's method you want... -// [...] - -func (ctx *MyContext) HTML(htmlContents string) (int, error) { - ctx.Application().Logger().Infof("Executing .HTML function from MyContext") - - ctx.ContentType("text/html") - return ctx.WriteString(htmlContents) -} - -func main() { - app := iris.New() - // app.Logger().SetLevel("debug") - - // The only one Required: - // here is how you define how your own context will - // be created and acquired from the iris' generic context pool. - app.ContextPool.Attach(func() context.Context { - return &MyContext{ - // Optional Part 3: - Context: context.NewContext(app), - } - }) - - // Register a view engine on .html files inside the ./view/** directory. - app.RegisterView(iris.HTML("./view", ".html")) - - // register your route, as you normally do - app.Handle("GET", "/", recordWhichContextJustForProofOfConcept, func(ctx context.Context) { - // use the context's overridden HTML method. - ctx.HTML("<h1> Hello from my custom context's HTML! </h1>") - }) - - // this will be executed by the MyContext.Context - // if MyContext is not directly define the View function by itself. - app.Handle("GET", "/hi/{firstname:alphabetical}", recordWhichContextJustForProofOfConcept, func(ctx context.Context) { - firstname := ctx.Values().GetString("firstname") - - ctx.ViewData("firstname", firstname) - ctx.Gzip(true) - - ctx.View("hi.html") - }) - - app.Run(iris.Addr(":8080")) -} - -// should always print "($PATH) Handler is executing from 'MyContext'" -func recordWhichContextJustForProofOfConcept(ctx context.Context) { - ctx.Application().Logger().Infof("(%s) Handler is executing from: '%s'", ctx.Path(), reflect.TypeOf(ctx).Elem().Name()) - ctx.Next() -} - -// Look "new-implementation" to see how you can create an entirely new Context with new functions. diff --git a/routing/custom-context/method-overriding/view/hi.html b/routing/custom-context/method-overriding/view/hi.html deleted file mode 100644 index 7999c305..00000000 --- a/routing/custom-context/method-overriding/view/hi.html +++ /dev/null @@ -1 +0,0 @@ -<h1> Hi {{.firstname}} </h1> \ No newline at end of file diff --git a/routing/custom-context/new-implementation/main.go b/routing/custom-context/new-implementation/main.go deleted file mode 100644 index fd3ba49a..00000000 --- a/routing/custom-context/new-implementation/main.go +++ /dev/null @@ -1,103 +0,0 @@ -package main - -import ( - "sync" - - "github.com/kataras/iris" - "github.com/kataras/iris/sessions" -) - -// Owner is our application structure, it contains the methods or fields we need, -// think it as the owner of our *Context. -type Owner struct { - // define here the fields that are global - // and shared to all clients. - sessionsManager *sessions.Sessions -} - -// this package-level variable "application" will be used inside context to communicate with our global Application. -var owner = &Owner{ - sessionsManager: sessions.New(sessions.Config{Cookie: "mysessioncookie"}), -} - -// Context is our custom context. -// Let's implement a context which will give us access -// to the client's Session with a trivial `ctx.Session()` call. -type Context struct { - iris.Context - session *sessions.Session -} - -// Session returns the current client's session. -func (ctx *Context) Session() *sessions.Session { - // this help us if we call `Session()` multiple times in the same handler - if ctx.session == nil { - // start a new session if not created before. - ctx.session = owner.sessionsManager.Start(ctx.Context) - } - - return ctx.session -} - -// Bold will send a bold text to the client. -func (ctx *Context) Bold(text string) { - ctx.HTML("<b>" + text + "</b>") -} - -var contextPool = sync.Pool{New: func() interface{} { - return &Context{} -}} - -func acquire(original iris.Context) *Context { - ctx := contextPool.Get().(*Context) - ctx.Context = original // set the context to the original one in order to have access to iris's implementation. - ctx.session = nil // reset the session - return ctx -} - -func release(ctx *Context) { - contextPool.Put(ctx) -} - -// Handler will convert our handler of func(*Context) to an iris Handler, -// in order to be compatible with the HTTP API. -func Handler(h func(*Context)) iris.Handler { - return func(original iris.Context) { - ctx := acquire(original) - h(ctx) - release(ctx) - } -} - -func newApp() *iris.Application { - app := iris.New() - - // Work as you did before, the only difference - // is that the original context.Handler should be wrapped with our custom - // `Handler` function. - app.Get("/", Handler(func(ctx *Context) { - ctx.Bold("Hello from our *Context") - })) - - app.Post("/set", Handler(func(ctx *Context) { - nameFieldValue := ctx.FormValue("name") - ctx.Session().Set("name", nameFieldValue) - ctx.Writef("set session = " + nameFieldValue) - })) - - app.Get("/get", Handler(func(ctx *Context) { - name := ctx.Session().GetString("name") - ctx.Writef(name) - })) - - return app -} - -func main() { - app := newApp() - - // GET: http://localhost:8080 - // POST: http://localhost:8080/set - // GET: http://localhost:8080/get - app.Run(iris.Addr(":8080")) -} diff --git a/routing/custom-context/new-implementation/main_test.go b/routing/custom-context/new-implementation/main_test.go deleted file mode 100644 index 35d8bb2c..00000000 --- a/routing/custom-context/new-implementation/main_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "testing" - - "github.com/kataras/iris/httptest" -) - -func TestCustomContextNewImpl(t *testing.T) { - app := newApp() - e := httptest.New(t, app, httptest.URL("http://localhost:8080")) - - e.GET("/").Expect(). - Status(httptest.StatusOK). - ContentType("text/html"). - Body().Equal("<b>Hello from our *Context</b>") - - expectedName := "iris" - e.POST("/set").WithFormField("name", expectedName).Expect(). - Status(httptest.StatusOK). - Body().Equal("set session = " + expectedName) - - e.GET("/get").Expect(). - Status(httptest.StatusOK). - Body().Equal(expectedName) -} diff --git a/routing/custom-router/main.go b/routing/custom-router/main.go new file mode 100644 index 00000000..37a24d4a --- /dev/null +++ b/routing/custom-router/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/core/router" +) + +/* + A Router should contain all three of the following methods: + - HandleRequest should handle the request based on the Context. + HandleRequest(ctx iris.Context) + - Build should builds the handler, it's being called on router's BuildRouter. + Build(provider router.RoutesProvider) error + - RouteExists reports whether a particular route exists. + RouteExists(ctx iris.Context, method, path string) bool + - FireErrorCode(ctx iris.Context) should handle the given ctx.GetStatusCode(). + +For a more detailed, complete and useful example +you can take a look at the iris' router itself which is located at: +https://github.com/kataras/iris/tree/main/core/router/handler.go +which completes this exact interface, the `router#RequestHandler`. +*/ +type customRouter struct { + // a copy of routes (safer because you will not be able to alter a route on serve-time without a `app.RefreshRouter` call): + // []router.Route + // or just expect the whole routes provider: + provider router.RoutesProvider +} + +// HandleRequest a silly example which finds routes based only on the first part of the requested path +// which must be a static one as well, the rest goes to fill the parameters. +func (r *customRouter) HandleRequest(ctx iris.Context) { + path := ctx.Path() + ctx.Application().Logger().Infof("Requested resource path: %s", path) + + parts := strings.Split(path, "/")[1:] + staticPath := "/" + parts[0] + for _, route := range r.provider.GetRoutes() { + if strings.HasPrefix(route.Path, staticPath) && route.Method == ctx.Method() { + paramParts := parts[1:] + for _, paramValue := range paramParts { + for _, p := range route.Tmpl().Params { + ctx.Params().Set(p.Name, paramValue) + } + } + + ctx.SetCurrentRoute(route.ReadOnly) + ctx.Do(route.Handlers) + return + } + } + + // if nothing found... + ctx.StatusCode(iris.StatusNotFound) +} + +func (r *customRouter) Build(provider router.RoutesProvider) error { + for _, route := range provider.GetRoutes() { + // do any necessary validation or conversations based on your custom logic here + // but always run the "BuildHandlers" for each registered route. + route.BuildHandlers() + // [...] r.routes = append(r.routes, *route) + } + + r.provider = provider + return nil +} + +func (r *customRouter) RouteExists(ctx iris.Context, method, path string) bool { + // [...] + return false +} + +func (r *customRouter) FireErrorCode(ctx iris.Context) { + // responseStatusCode := ctx.GetStatusCode() // set by prior ctx.StatusCode calls + // [...] +} + +func main() { + app := iris.New() + + // In case you are wondering, the parameter types and macros like "{param:string $func()}" still work inside + // your custom router if you fetch by the Route's Handler + // because they are middlewares under the hood, so you don't have to implement the logic of handling them manually, + // though you have to match what requested path is what route and fill the ctx.Params(), this is the work of your custom router. + app.Get("/hello/{name}", func(ctx iris.Context) { + name := ctx.Params().Get("name") + ctx.Writef("Hello %s\n", name) + }) + + app.Get("/cs/{num:uint64 min(10) else 400}", func(ctx iris.Context) { + num := ctx.Params().GetUint64Default("num", 0) + ctx.Writef("num is: %d\n", num) + }) + + // To replace the existing router with a customized one by using the iris/context.Context + // you have to use the `app.BuildRouter` method before `app.Run` and after the routes registered. + // You should pass your custom router's instance as the second input arg, which must completes the `router#RequestHandler` + // interface as shown above. + // + // To see how you can build something even more low-level without direct iris' context support (you can do that manually as well) + // navigate to the "custom-wrapper" example instead. + myCustomRouter := new(customRouter) + app.BuildRouter(app.ContextPool, myCustomRouter, app.APIBuilder, true) + + app.Listen(":8080") +} diff --git a/routing/custom-wrapper/main.go b/routing/custom-wrapper/main.go index dfcd0402..9f18cdf6 100644 --- a/routing/custom-wrapper/main.go +++ b/routing/custom-wrapper/main.go @@ -4,45 +4,28 @@ import ( "net/http" "strings" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // In this example you'll just see one use case of .WrapRouter. // You can use the .WrapRouter to add custom logic when or when not the router should // be executed in order to execute the registered routes' handlers. -// -// To see how you can serve files on root "/" without a custom wrapper -// just navigate to the "file-server/single-page-application" example. -// -// This is just for the proof of concept, you can skip this tutorial if it's too much for you. func newApp() *iris.Application { - app := iris.New() app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) { ctx.HTML("<b>Resource Not found</b>") }) - app.Get("/", func(ctx iris.Context) { - ctx.ServeFile("./public/index.html", false) - }) - app.Get("/profile/{username}", func(ctx iris.Context) { ctx.Writef("Hello %s", ctx.Params().Get("username")) }) - // serve files from the root "/", if we used .StaticWeb it could override - // all the routes because of the underline need of wildcard. - // Here we will see how you can by-pass this behavior - // by creating a new file server handler and - // setting up a wrapper for the router(like a "low-level" middleware) - // in order to manually check if we want to process with the router as normally - // or execute the file server handler instead. + app.HandleDir("/", iris.Dir("./public")) - // use of the .StaticHandler - // which is the same as StaticWeb but it doesn't - // registers the route, it just returns the handler. - fileServer := app.StaticHandler("./public", false, false) + myOtherHandler := func(ctx iris.Context) { + ctx.Writef("inside a handler which is fired manually by our custom router wrapper") + } // wrap the router with a native net/http handler. // if url does not contain any "." (i.e: .css, .js...) @@ -52,19 +35,18 @@ func newApp() *iris.Application { // if not then it will serve the files based on the root "/" path. app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) { path := r.URL.Path - // Note that if path has suffix of "index.html" it will auto-permant redirect to the "/", - // so our first handler will be executed instead. - if !strings.Contains(path, ".") { // if it's not a resource then continue to the router as normally. - router(w, r) + if strings.HasPrefix(path, "/other") { + // acquire and release a context in order to use it to execute + // our custom handler + // remember: we use net/http.Handler because here we are in the "low-level", before the router itself. + ctx := app.ContextPool.Acquire(w, r) + myOtherHandler(ctx) + app.ContextPool.Release(ctx) return } - // acquire and release a context in order to use it to execute - // our file server - // remember: we use net/http.Handler because here we are in the "low-level", before the router itself. - ctx := app.ContextPool.Acquire(w, r) - fileServer(ctx) - app.ContextPool.Release(ctx) + + router.ServeHTTP(w, r) // else continue serving routes as usual. }) return app @@ -78,14 +60,10 @@ func main() { // http://localhost:8080/app.js // http://localhost:8080/css/main.css // http://localhost:8080/profile/anyusername - app.Run(iris.Addr(":8080")) + // http://localhost:8080/other/random + app.Listen(":8080") // Note: In this example we just saw one use case, // you may want to .WrapRouter or .Downgrade in order to bypass the iris' default router, i.e: // you can use that method to setup custom proxies too. - // - // If you just want to serve static files on other path than root - // you can just use the StaticWeb, i.e: - // .StaticWeb("/static", "./public") - // ________________________________requestPath, systemPath } diff --git a/routing/custom-wrapper/main_test.go b/routing/custom-wrapper/main_test.go index 74d36bdf..40de3fdf 100644 --- a/routing/custom-wrapper/main_test.go +++ b/routing/custom-wrapper/main_test.go @@ -1,12 +1,12 @@ package main import ( - "io/ioutil" + "os" "path/filepath" "strings" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) type resource string @@ -29,7 +29,7 @@ func (r resource) loadFromBase(dir string) string { fullpath := filepath.Join(dir, filename) - b, err := ioutil.ReadFile(fullpath) + b, err := os.ReadFile(fullpath) if err != nil { panic(fullpath + " failed with error: " + err.Error()) } @@ -54,6 +54,8 @@ func TestCustomWrapper(t *testing.T) { e.GET(url).Expect(). Status(httptest.StatusOK). - Body().Equal(contents) + Body().IsEqual(contents) } + + e.GET("/other/something").Expect().Status(httptest.StatusOK) } diff --git a/routing/custom-wrapper/public/index.html b/routing/custom-wrapper/public/index.html index 78f89888..9e0c41f6 100644 --- a/routing/custom-wrapper/public/index.html +++ b/routing/custom-wrapper/public/index.html @@ -1,7 +1,7 @@ <html> <head> - <title>{{ .Page.Title }}</title> + <title>Index Page</title> </head> <body> diff --git a/routing/dynamic-path/at-username/main.go b/routing/dynamic-path/at-username/main.go new file mode 100644 index 00000000..e6496d01 --- /dev/null +++ b/routing/dynamic-path/at-username/main.go @@ -0,0 +1,30 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { + ctx.Writef("Hello %s", "world") + }) + + // This is an Iris-only feature across all web frameworks + // in every programming language for years. + // Dynamic Route Path Parameters Functions. + // Set min length characters to 2. + // Prefix of the username is '@' + // Otherwise 404. + // + // You can also use the regexp(...) function for more advanced expressions. + app.Get("/{username:string min(2) prefix(@)}", func(ctx iris.Context) { + username := ctx.Params().Get("username")[1:] + ctx.Writef("Username is %s", username) + }) + + // http://localhost:8080 -> FOUND (Hello world) + // http://localhost:8080/other -> NOT FOUND + // http://localhost:8080/@ -> NOT FOUND + // http://localhost:8080/@kataras -> FOUND (username is kataras) + app.Listen(":8080") +} diff --git a/routing/dynamic-path/main.go b/routing/dynamic-path/main.go index 5a3f0b57..12da42e7 100644 --- a/routing/dynamic-path/main.go +++ b/routing/dynamic-path/main.go @@ -2,9 +2,8 @@ package main import ( "regexp" - "strconv" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -14,15 +13,14 @@ func main() { // we've seen static routes, group of routes, subdomains, wildcard subdomains, a small example of parameterized path // with a single known paramete and custom http errors, now it's time to see wildcard parameters and macros. - // iris, like net/http std package registers route's handlers + // Iris, like net/http std package registers route's handlers // by a Handler, the iris' type of handler is just a func(ctx iris.Context) // where context comes from github.com/kataras/iris/context. - // Until go 1.9 you will have to import that package too, after go 1.9 this will be not be necessary. // - // iris has the easiest and the most powerful routing process you have ever meet. + // Iris has the easiest and the most powerful routing process you have ever meet. // // At the same time, - // iris has its own interpeter(yes like a programming language) + // Iris has its own interpeter(yes like a programming language) // for route's path syntax and their dynamic path parameters parsing and evaluation, // We call them "macros" for shortcut. // How? It calculates its needs and if not any special regexp needed then it just @@ -30,40 +28,88 @@ func main() { // otherwise it pre-compiles the regexp and adds the necessary middleware(s). // // Standard macro types for parameters: - // +------------------------+ - // | {param:string} | - // +------------------------+ + // +------------------------+ + // | {param:string} | + // +------------------------+ // string type - // anything + // anything (single path segmnent) // - // +------------------------+ - // | {param:int} | - // +------------------------+ + // +-------------------------------+ + // | {param:int} | + // +-------------------------------+ // int type - // only numbers (0-9) + // -9223372036854775808 to 9223372036854775807 (x64) or -2147483648 to 2147483647 (x32), depends on the host arch + // + // +------------------------+ + // | {param:int8} | + // +------------------------+ + // int8 type + // -128 to 127 + // + // +------------------------+ + // | {param:int16} | + // +------------------------+ + // int16 type + // -32768 to 32767 + // + // +------------------------+ + // | {param:int32} | + // +------------------------+ + // int32 type + // -2147483648 to 2147483647 // // +------------------------+ - // | {param:long} | + // | {param:int64} | // +------------------------+ // int64 type - // only numbers (0-9) + // -9223372036854775808 to 9223372036854775807 + // + // +------------------------+ + // | {param:uint} | + // +------------------------+ + // uint type + // 0 to 18446744073709551615 (x64) or 0 to 4294967295 (x32) + // + // +------------------------+ + // | {param:uint8} | + // +------------------------+ + // uint8 type + // 0 to 255 + // + // +------------------------+ + // | {param:uint16} | + // +------------------------+ + // uint16 type + // 0 to 65535 + // + // +------------------------+ + // | {param:uint32} | + // +------------------------+ + // uint32 type + // 0 to 4294967295 // // +------------------------+ - // | {param:boolean} | + // | {param:uint64} | // +------------------------+ + // uint64 type + // 0 to 18446744073709551615 + // + // +---------------------------------+ + // | {param:bool} or {param:boolean} | + // +---------------------------------+ // bool type // only "1" or "t" or "T" or "TRUE" or "true" or "True" // or "0" or "f" or "F" or "FALSE" or "false" or "False" // - // +------------------------+ - // | {param:alphabetical} | - // +------------------------+ + // +------------------------+ + // | {param:alphabetical} | + // +------------------------+ // alphabetical/letter type // letters only (upper or lowercase) // - // +------------------------+ - // | {param:file} | - // +------------------------+ + // +------------------------+ + // | {param:file} | + // +------------------------+ // file type // letters (upper or lowercase) // numbers (0-9) @@ -72,15 +118,43 @@ func main() { // point (.) // no spaces ! or other character // - // +------------------------+ - // | {param:path} | - // +------------------------+ + // +------------------------+ + // | {param:path} | + // +------------------------+ // path type - // anything, should be the last part, more than one path segment, - // i.e: /path1/path2/path3 , ctx.Params().Get("param") == "/path1/path2/path3" + // anything, should be the last part, can be more than one path segment, + // i.e: "/test/{param:path}" and request: "/test/path1/path2/path3" , ctx.Params().Get("param") == "path1/path2/path3" + // + // +------------------------+ + // | {param:uuid} | + // +------------------------+ + // UUIDv4 (and v1) path parameter validation. + // + // +------------------------+ + // | {param:mail} | + // +------------------------+ + // Email without domain validation. + // + // +------------------------+ + // | {param:email} | + // +------------------------+ + // Email with domain validation. + // // - // if type is missing then parameter's type is defaulted to string, so - // {param} == {param:string}. + // +------------------------+ + // | {param:date} | + // +------------------------+ + // yyyy/mm/dd format e.g. /blog/{param:date} matches /blog/2022/04/21. + // + // +------------------------+ + // | {param:weekday} | + // +------------------------+ + // positive integer 0 to 6 or + // string of time.Weekday longname format ("sunday" to "monday" or "Sunday" to "Monday") + // format e.g. /schedule/{param:weekday} matches /schedule/monday. + // + // If type is missing then parameter's type is defaulted to string, so + // {param} is identical to {param:string}. // // If a function not found on that type then the `string` macro type's functions are being used. // @@ -89,7 +163,7 @@ func main() { // you are able to register your own too!. // // Register a named path parameter function: - // app.Macros().Int.RegisterFunc("min", func(argument int) func(paramValue string) bool { + // app.Macros().Number.RegisterFunc("min", func(argument int) func(paramValue string) bool { // [...] // return true/false -> true means valid. // }) @@ -102,56 +176,109 @@ func main() { // return func(paramValue string) bool { return argument == paramValue } // }) + // Optionally, set custom handler on path parameter type error: + app.Macros().Get("uuid").HandleError(func(ctx iris.Context, paramIndex int, err error) { + ctx.StatusCode(iris.StatusBadRequest) + + param := ctx.Params().GetEntryAt(paramIndex) + ctx.JSON(iris.Map{ + "error": err.Error(), + "message": "invalid path parameter", + "parameter": param.Key, + "value": param.ValueRaw, + }) + }) + + // http://localhost:8080/user/bb4f33e4-dc08-40d8-9f2b-e8b2bb615c0e -> OK + // http://localhost:8080/user/dsadsa-invalid-uuid -> NOT FOUND + app.Get("/user/{id:uuid}", func(ctx iris.Context) { + id := ctx.Params().Get("id") + ctx.WriteString(id) + }) + + // +------------------------+ + // | {param:email} | + // +------------------------+ + // Email + mx look uppath parameter validation. + // Note that, you can also use the simpler ":mail" to accept any domain email. + + // http://localhost:8080/user/email/kataras2006@hotmail.com -> OK + // http://localhost:8080/user/email/b-c@ -> NOT FOUND + app.Get("/user/email/{user_email:email}", func(ctx iris.Context) { + email := ctx.Params().Get("user_email") + ctx.WriteString(email) + }) + + // http://localhost:8080/blog/2022/04/21 + app.Get("/blog/{date:date}", func(ctx iris.Context) { + // rawTimeValue := ctx.Params().GetEntry("d").ValueRaw.(time.Time) + // OR + rawTimeValue, _ := ctx.Params().GetTime("date") + // yearMonthDay := rawTimeValue.Format("2006/01/02") + // OR + yearMonthDay := ctx.Params().SimpleDate("date") + ctx.Writef("Raw time.Time.String value: %v\nyyyy/mm/dd: %s\n", rawTimeValue, yearMonthDay) + }) + + // 0 to 7 or "Sunday" to "Monday" or "sunday" to "monday". Leading zeros don't matter. + // http://localhost:8080/schedule/monday or http://localhost:8080/schedule/Monday or + // http://localhost:8080/schedule/1 or http://localhost:8080/schedule/0001. + app.Get("/schedule/{day:weekday}", func(ctx iris.Context) { + day, _ := ctx.Params().GetWeekday("day") + ctx.Writef("Weekday requested was: %v\n", day) + }) + // you can use the "string" type which is valid for a single path parameter that can be anything. app.Get("/username/{name}", func(ctx iris.Context) { ctx.Writef("Hello %s", ctx.Params().Get("name")) }) // type is missing = {name:string} - // Let's register our first macro attached to int macro type. + // Let's register our first macro attached to uint64 macro type. // "min" = the function // "minValue" = the argument of the function - // func(string) bool = the macro's path parameter evaluator, this executes in serve time when - // a user requests a path which contains the :int macro type with the min(...) macro parameter function. - app.Macros().Int.RegisterFunc("min", func(minValue int) func(string) bool { - // do anything before serve here [...] - // at this case we don't need to do anything - return func(paramValue string) bool { - n, err := strconv.Atoi(paramValue) - if err != nil { - return false - } - return n >= minValue + // func(uint64) bool = our func's evaluator, this executes in serve time when + // a user requests a path which contains the :uint64 macro parameter type with the min(...) macro parameter function. + app.Macros().Get("uint64").RegisterFunc("min", func(minValue uint64) func(uint64) bool { + // type of "paramValue" should match the type of the internal macro's evaluator function, which in this case is "uint64". + return func(paramValue uint64) bool { + return paramValue >= minValue } }) - // http://localhost:8080/profile/id>=1 + // http://localhost:8080/profile/id>=20 // this will throw 404 even if it's found as route on : /profile/0, /profile/blabla, /profile/-1 // macro parameter functions are optional of course. - app.Get("/profile/{id:int min(1)}", func(ctx iris.Context) { + app.Get("/profile/{id:uint64 min(20)}", func(ctx iris.Context) { // second parameter is the error but it will always nil because we use macros, // the validaton already happened. - id, _ := ctx.Params().GetInt("id") + id := ctx.Params().GetUint64Default("id", 0) ctx.Writef("Hello id: %d", id) }) // to change the error code per route's macro evaluator: - app.Get("/profile/{id:int min(1)}/friends/{friendid:int min(1) else 504}", func(ctx iris.Context) { - id, _ := ctx.Params().GetInt("id") - friendid, _ := ctx.Params().GetInt("friendid") - ctx.Writef("Hello id: %d looking for friend id: ", id, friendid) + app.Get("/profile/{id:uint64 min(1)}/friends/{friendid:uint64 min(1) else 504}", func(ctx iris.Context) { + id := ctx.Params().GetUint64Default("id", 0) + friendid := ctx.Params().GetUint64Default("friendid", 0) + ctx.Writef("Hello id: %d looking for friend id: %d", id, friendid) }) // this will throw e 504 error code instead of 404 if all route's macros not passed. - // Another example using a custom regexp and any custom logic. + // :uint8 0 to 255. + app.Get("/ages/{age:uint8 else 400}", func(ctx iris.Context) { + age, _ := ctx.Params().GetUint8("age") + ctx.Writef("age selected: %d", age) + }) + + // Another example using a custom regexp or any custom logic. + + // Register your custom argument-less macro function to the :string param type. latLonExpr := "^-?[0-9]{1,3}(?:\\.[0-9]{1,10})?$" latLonRegex, err := regexp.Compile(latLonExpr) if err != nil { panic(err) } - app.Macros().String.RegisterFunc("coordinate", func() func(paramName string) (ok bool) { - // MatchString is a type of func(string) bool, so we can return that as it's. - return latLonRegex.MatchString - }) + // MatchString is a type of func(string) bool, so we use it as it is. + app.Macros().Get("string").RegisterFunc("coordinate", latLonRegex.MatchString) app.Get("/coordinates/{lat:string coordinate() else 502}/{lon:string coordinate() else 502}", func(ctx iris.Context) { ctx.Writef("Lat: %s | Lon: %s", ctx.Params().Get("lat"), ctx.Params().Get("lon")) @@ -159,7 +286,43 @@ func main() { // - // http://localhost:8080/game/a-zA-Z/level/0-9 + // Another one is by using a custom body. + app.Macros().Get("string").RegisterFunc("range", func(minLength, maxLength int) func(string) bool { + return func(paramValue string) bool { + return len(paramValue) >= minLength && len(paramValue) <= maxLength + } + }) + + app.Get("/limitchar/{name:string range(1,200)}", func(ctx iris.Context) { + name := ctx.Params().Get("name") + ctx.Writef(`Hello %s | the name should be between 1 and 200 characters length + otherwise this handler will not be executed`, name) + }) + + // + + // Register your custom macro function which accepts a slice of strings `[...,...]`. + app.Macros().Get("string").RegisterFunc("has", func(validNames []string) func(string) bool { + return func(paramValue string) bool { + for _, validName := range validNames { + if validName == paramValue { + return true + } + } + + return false + } + }) + + app.Get("/static_validation/{name:string has([kataras,gerasimos,maropoulos])}", func(ctx iris.Context) { + name := ctx.Params().Get("name") + ctx.Writef(`Hello %s | the name should be "kataras" or "gerasimos" or "maropoulos" + otherwise this handler will not be executed`, name) + }) + + // + + // http://localhost:8080/game/a-zA-Z/level/42 // remember, alphabetical is lowercase or uppercase letters only. app.Get("/game/{name:alphabetical}/level/{level:int}", func(ctx iris.Context) { ctx.Writef("name: %s | level: %s", ctx.Params().Get("name"), ctx.Params().Get("level")) @@ -189,6 +352,17 @@ func main() { }) // for wildcard path (any number of path segments) without validation you can use: // /myfiles/* + // http://localhost:8080/trimmed/42.html + app.Get("/trimmed/{uid:string regexp(^[0-9]{1,20}.html$)}", iris.TrimParamFilePart, func(ctx iris.Context) { + // + // The above line is useless now that we've registered the TrimParamFilePart middleware: + // uid := ctx.Params().GetTrimFileUint64("uid") + // TrimParamFilePart can be registered to a Party (group of routes) too. + + uid := ctx.Params().GetUint64Default("uid", 0) + ctx.Writef("Param value: %d\n", uid) + }) + // "{param}"'s performance is exactly the same of ":param"'s. // alternatives -> ":param" for single path parameter and "*" for wildcard path parameter. @@ -197,10 +371,21 @@ func main() { // if "/mypath/{myparam:path}" then the parameter has two names, one is the "*" and the other is the user-defined "myparam". // WARNING: - // A path parameter name should contain only alphabetical letters. Symbols like '_' and numbers are NOT allowed. + // A path parameter name should contain only alphabetical letters or digits. Symbols like '_' are NOT allowed. // Last, do not confuse `ctx.Params()` with `ctx.Values()`. - // Path parameter's values goes to `ctx.Params()` and context's local storage - // that can be used to communicate between handlers and middleware(s) goes to - // `ctx.Values()`. - app.Run(iris.Addr(":8080")) + // Path parameter's values can be retrieved from `ctx.Params()`, + // context's local storage that can be used to communicate between handlers and middleware(s) can be stored to `ctx.Values()`. + // + // When registering different parameter types in the same exact path pattern, the path parameter's name + // should differ e.g. + // /path/{name:string} + // /path/{id:uint} + // + // Note: + // If * path part is declared at the end of the route path, then + // it's considered a wildcard (same as {p:path}). In order to declare + // literal * and over pass this limitation use the string's path parameter 'eq' function + // as shown below: + // app.Get("/*/*/{p:string eq(*)}", handler) <- This will match only: /*/*/* and not /*/*/anything. + app.Listen(":8080") } diff --git a/routing/dynamic-path/root-wildcard/main.go b/routing/dynamic-path/root-wildcard/main.go index bd1b462b..2ccb8489 100644 --- a/routing/dynamic-path/root-wildcard/main.go +++ b/routing/dynamic-path/root-wildcard/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -38,7 +38,7 @@ func main() { // this will handle only GET "/other2/static" app.Get("/other2/static2", staticPathOther2) - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app.Listen(":8080") } func h(ctx iris.Context) { diff --git a/routing/dynamic-path/same-pattern-different-func/main.go b/routing/dynamic-path/same-pattern-different-func/main.go new file mode 100644 index 00000000..e241a51b --- /dev/null +++ b/routing/dynamic-path/same-pattern-different-func/main.go @@ -0,0 +1,33 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := newApp() + app.Logger().SetLevel("debug") + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + app.HandleMany(iris.MethodGet, "/ /api/{page:string suffix(.html)}", handler1) + app.Get("/api/{name:string suffix(.zip)}", handler2) + + return app +} + +func handler1(ctx iris.Context) { + reply(ctx) +} + +func handler2(ctx iris.Context) { + reply(ctx) +} + +func reply(ctx iris.Context) { + ctx.JSON(iris.Map{ + "handler": ctx.HandlerName(), + "params": ctx.Params().Store, + }) +} diff --git a/routing/dynamic-path/same-pattern-different-func/main_test.go b/routing/dynamic-path/same-pattern-different-func/main_test.go new file mode 100644 index 00000000..c98a93d5 --- /dev/null +++ b/routing/dynamic-path/same-pattern-different-func/main_test.go @@ -0,0 +1,41 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/core/memstore" + "github.com/kataras/iris/v12/httptest" +) + +func TestSameParameterTypeDifferentMacroFunctions(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + type resp struct { + Handler string `json:"handler"` + Params memstore.Store `json:"params"` + } + + var ( + expectedIndex = resp{ + Handler: "iris/_examples/routing/dynamic-path/same-pattern-different-func.handler1", + Params: nil, + } + expectedHTMLPage = resp{ + Handler: "iris/_examples/routing/dynamic-path/same-pattern-different-func.handler1", + Params: memstore.Store{ + {Key: "page", ValueRaw: "random.html"}, + }, + } + expectedZipName = resp{ + Handler: "iris/_examples/routing/dynamic-path/same-pattern-different-func.handler2", + Params: memstore.Store{ + {Key: "name", ValueRaw: "random.zip"}, + }, + } + ) + + e.GET("/").Expect().Status(httptest.StatusOK).JSON().IsEqual(expectedIndex) + e.GET("/api/random.html").Expect().Status(httptest.StatusOK).JSON().IsEqual(expectedHTMLPage) + e.GET("/api/random.zip").Expect().Status(httptest.StatusOK).JSON().IsEqual(expectedZipName) +} diff --git a/routing/dynamic-path/same-pattern-different-func/use-global/main.go b/routing/dynamic-path/same-pattern-different-func/use-global/main.go new file mode 100644 index 00000000..2f18f84f --- /dev/null +++ b/routing/dynamic-path/same-pattern-different-func/use-global/main.go @@ -0,0 +1,42 @@ +package main // #1552 + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + app.UseGlobal(middleware("first")) + app.UseGlobal(middleware("second")) + app.DoneGlobal(onDone) + + app.Get("/{name prefix(one)}", handler("first route")) + app.Get("/{name prefix(two)}", handler("second route")) + app.Get("/{name prefix(three)}", handler("third route")) + + return app +} + +func middleware(str string) iris.Handler { + return func(ctx iris.Context) { + ctx.Writef("Called %s middleware\n", str) + ctx.Next() + } +} + +func handler(str string) iris.Handler { + return func(ctx iris.Context) { + ctx.Writef("%s\n", str) + ctx.Next() // or ignroe that and use app.SetRegisterRules. + } +} + +func onDone(ctx iris.Context) { + ctx.Writef("Called done: %s", ctx.Params().Get("name")) +} diff --git a/routing/dynamic-path/same-pattern-different-func/use-global/main_test.go b/routing/dynamic-path/same-pattern-different-func/use-global/main_test.go new file mode 100644 index 00000000..835765a8 --- /dev/null +++ b/routing/dynamic-path/same-pattern-different-func/use-global/main_test.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestSamePatternDifferentFuncUseGlobal(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + expectedResultFmt := "Called first middleware\nCalled second middleware\n%s\nCalled done: %s" + tests := map[string]string{ + "/one-num": "first route", + "/two-num": "second route", + "/three-num": "third route", + } + + for path, mainBody := range tests { + result := fmt.Sprintf(expectedResultFmt, mainBody, path[1:]) + e.GET(path).Expect().Status(httptest.StatusOK).Body().IsEqual(result) + } +} diff --git a/hello-world/main.go b/routing/hello-world/main.go similarity index 77% rename from hello-world/main.go rename to routing/hello-world/main.go index f9b4bc7e..2b0ec41d 100644 --- a/hello-world/main.go +++ b/routing/hello-world/main.go @@ -1,16 +1,16 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/middleware/logger" - "github.com/kataras/iris/middleware/recover" + "github.com/kataras/iris/v12/middleware/logger" + "github.com/kataras/iris/v12/middleware/recover" ) func main() { app := iris.New() app.Logger().SetLevel("debug") - // Optionally, add two built'n handlers + // Optionally, add two builtin handlers // that can recover from any http-relative panics // and log the requests to the terminal. app.Use(recover.New()) @@ -38,5 +38,5 @@ func main() { // http://localhost:8080 // http://localhost:8080/ping // http://localhost:8080/hello - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app.Listen(":8080") } diff --git a/routing/http-errors/main.go b/routing/http-errors/main.go index c41dfbf4..f5af0147 100644 --- a/routing/http-errors/main.go +++ b/routing/http-errors/main.go @@ -1,18 +1,22 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) +// See _examples/routing/http-wire-errors as well. func main() { app := iris.New() + // Catch a specific error code. app.OnErrorCode(iris.StatusInternalServerError, func(ctx iris.Context) { ctx.HTML("Message: <b>" + ctx.Values().GetString("message") + "</b>") }) + // Catch all error codes [app.OnAnyErrorCode...] + app.Get("/", func(ctx iris.Context) { - ctx.HTML(`Click <a href="/my500">here</a> to fire the 500 status code`) + ctx.HTML(`Click <a href="/my500">here</a> to pretend an HTTP error`) }) app.Get("/my500", func(ctx iris.Context) { @@ -24,5 +28,90 @@ func main() { ctx.Writef("Hello %s", ctx.Params().Get("firstname")) }) - app.Run(iris.Addr(":8080")) + // Read more at: https://github.com/kataras/iris/issues/1335 + app.Get("/product-problem", problemExample) + + app.Get("/product-error", func(ctx iris.Context) { + ctx.Writef("explain the error") + }) + + // http://localhost:8080 + // http://localhost:8080/my500 + // http://localhost:8080/u/gerasimos + // http://localhost:8080/product-problem + app.Listen(":8080") +} + +func newProductProblem(productName, detail string) iris.Problem { + return iris.NewProblem(). + // The type URI, if relative it automatically convert to absolute. + Type("/product-error"). + // The title, if empty then it gets it from the status code. + Title("Product validation problem"). + // Any optional details. + Detail(detail). + // The status error code, required. + Status(iris.StatusBadRequest). + // Any custom key-value pair. + Key("productName", productName) + // Optional cause of the problem, chain of Problems. + // Cause(iris.NewProblem().Type("/error").Title("cause of the problem").Status(400)) +} + +func problemExample(ctx iris.Context) { + /* + p := iris.NewProblem(). + Type("/validation-error"). + Title("Your request parameters didn't validate"). + Detail("Optional details about the error."). + Status(iris.StatusBadRequest). + Key("customField1", customValue1) + Key("customField2", customValue2) + ctx.Problem(p) + + // OR + ctx.Problem(iris.Problem{ + "type": "/validation-error", + "title": "Your request parameters didn't validate", + "detail": "Optional details about the error.", + "status": iris.StatusBadRequest, + "customField1": customValue1, + "customField2": customValue2, + }) + + // OR + */ + + // Response like JSON but with indent of " " and + // content type of "application/problem+json" + ctx.Problem(newProductProblem("product name", "problem error details"), iris.ProblemOptions{ + // Optional JSON renderer settings. + JSON: iris.JSON{ + Indent: " ", + }, + // OR + // Render as XML: + // + // RenderXML: true, + // XML: iris.XML{Indent: " "}, + // and ctx.StatusCode(200) to see the result on browser as a user. + // + // The below `RetryAfter` field sets the "Retry-After" response header. + // + // Can accept: + // time.Time for HTTP-Date, + // time.Duration, int64, float64, int for seconds + // or string for date or duration. + // Examples: + // time.Now().Add(5 * time.Minute), + // 300 * time.Second, + // "5m", + // + RetryAfter: 300, + // A function that, if specified, can dynamically set + // retry-after based on the request. Useful for ProblemOptions reusability. + // Overrides the RetryAfter field. + // + // RetryAfterFunc: func(iris.Context) interface{} { [...] } + }) } diff --git a/routing/http-errors/reset-body/main.go b/routing/http-errors/reset-body/main.go new file mode 100644 index 00000000..f00de102 --- /dev/null +++ b/routing/http-errors/reset-body/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(iris.Compression) + + app.OnAnyErrorCode(onErrorCode) + app.Get("/", handler) + + app.Configure(iris.WithResetOnFireErrorCode) + return app +} + +// This is the default error handler Iris uses for any error codes. +func onErrorCode(ctx iris.Context) { + if err := ctx.GetErr(); err != nil { + ctx.WriteString(err.Error()) + } else { + ctx.WriteString(iris.StatusText(ctx.GetStatusCode())) + } +} + +func handler(ctx iris.Context) { + ctx.Record() + + ctx.WriteString("This should NOT be written") + + // [....something bad happened after we "write"] + err := fmt.Errorf("custom error") + ctx.StopWithError(iris.StatusBadRequest, err) +} diff --git a/routing/http-errors/reset-body/main_test.go b/routing/http-errors/reset-body/main_test.go new file mode 100644 index 00000000..6add7c12 --- /dev/null +++ b/routing/http-errors/reset-body/main_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestResetCompressionAndFireError(t *testing.T) { // #1569 + app := newApp() + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusBadRequest).Body().IsEqual("custom error") +} diff --git a/routing/http-wire-errors/main.go b/routing/http-wire-errors/main.go new file mode 100644 index 00000000..1f5001e5 --- /dev/null +++ b/routing/http-wire-errors/main.go @@ -0,0 +1,110 @@ +package main + +import ( + "github.com/kataras/iris/v12" + // IMPORTANT, import this sub-package. + // Note tht it does NOT break compatibility with the + // standard "errors" package as the New, + // Is, As, Unwrap functions are aliases to the standard package. + "github.com/kataras/iris/v12/x/errors" +) + +// Optionally, register custom error codes. +// +// The default list of error code names: +// errors.Cancelled +// errors.Unknown +// errors.InvalidArgument +// errors.DeadlineExceeded +// errors.NotFound +// errors.AlreadyExists +// errors.PermissionDenied +// errors.Unauthenticated +// errors.ResourceExhausted +// errors.FailedPrecondition +// errors.Aborted +// errors.OutOfRange +// errors.Unimplemented +// errors.Internal +// errors.Unavailable +// errors.DataLoss +var ( + Custom = errors.Register("CUSTOM_CANONICAL_ERROR_NAME", iris.StatusBadRequest) +) + +func main() { + app := iris.New() + + // Custom error code name. + app.Get("/custom", fireCustomErrorCodeName) + + // Send a simple 400 request with message and an error + // or with more details and data. + app.Post("/invalid_argument", fireInvalidArgument) + + // Compatibility with the iris.Problem type (and any other custom type). + app.Get("/problem", fireErrorWithProblem) + + app.Listen(":8080") +} + +func fireCustomErrorCodeName(ctx iris.Context) { + Custom.Details(ctx, "message", "details with arguments: %s", "an argument") +} + +func fireInvalidArgument(ctx iris.Context) { + var req = struct { + Username string `json:"username"` + }{} + if err := ctx.ReadJSON(&req); err != nil { + errors.InvalidArgument.Err(ctx, err) + return + } + + ctx.WriteString(req.Username) + + // Other examples: errors.InvalidArgument/NotFound/Internal and e.t.c. + // .Message(ctx, "message %s", "optional argument") + // .Details(ctx, "message", "details %s", "optional details argument") + // .Data(ctx, "message", anyTypeOfValue) + // .DataWithDetails(ctx, "unable to read the body", "malformed json", iris.Map{"custom": "data of any type"}) + // .Log(ctx, "message %s", "optional argument") + // .LogErr(ctx, err) +} + +func fireErrorWithProblem(ctx iris.Context) { + myCondition := true + if myCondition { + problem := iris.NewProblem(). + // The type URI, if relative it automatically convert to absolute. + Type("/product-error"). + // The title, if empty then it gets it from the status code. + Title("Product validation problem"). + // Any optional details. + Detail("details about the product error"). + // The status error code of the problem, can be optional here. + // Status(iris.StatusBadRequest). + // Any custom key-value pair. + Key("product_name", "the product name") + + errors.InvalidArgument.Data(ctx, "unable to process the request", problem) + return + + /* Prints to the client: + { + "http_error_code": { + "canonical_name": "INVALID_ARGUMENT", + "status": 400 + }, + "message": "unable to process the request", + "data": { + "detail": "details about the product error", + "product_name": "the product name", + "title": "Product validation problem", + "type": "/product-error" + } + } + */ + } + +} diff --git a/routing/http-wire-errors/service/main.go b/routing/http-wire-errors/service/main.go new file mode 100644 index 00000000..e46f2a9d --- /dev/null +++ b/routing/http-wire-errors/service/main.go @@ -0,0 +1,249 @@ +package main + +import ( + "context" + "fmt" + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/errors" + "github.com/kataras/iris/v12/x/errors/validation" + "github.com/kataras/iris/v12/x/pagination" +) + +func main() { + app := iris.New() + + // Create a new service and pass it to the handlers. + service := new(myService) + + app.Post("/", errors.Intercept(afterServiceCallButBeforeDataSent), createHandler(service)) // OR: errors.CreateHandler(service.Create) + app.Get("/", listAllHandler(service)) // OR errors.Handler(service.ListAll, errors.Value(ListRequest{})) + app.Post("/page", listHandler(service)) // OR: errors.ListHandler(service.ListPaginated) + app.Delete("/{id:string}", deleteHandler(service)) // OR: errors.NoContentOrNotModifiedHandler(service.DeleteWithFeedback, errors.PathParam[string]("id")) + + app.Listen(":8080") +} + +func createHandler(service *myService) iris.Handler { + return func(ctx iris.Context) { + // What it does? + // 1. Reads the request body and binds it to the CreateRequest struct. + // 2. Calls the service.Create function with the given request body. + // 3. If the service.Create returns an error, it sends an appropriate error response to the client. + // 4. If the service.Create returns a response, it sets the status code to 201 (Created) and sends the response as a JSON payload to the client. + // + // Useful for create operations. + errors.Create(ctx, service.Create) + } +} + +func listAllHandler(service *myService) iris.Handler { + return func(ctx iris.Context) { + // What it does? + // 1. If the 3rd variadic (optional) parameter is empty (not our case here), it reads the request body and binds it to the ListRequest struct, + // otherwise (our case) it calls the service.ListAll function directly with the given input parameter (empty ListRequest struct value in our case). + // 2. Calls the service.ListAll function with the ListRequest value. + // 3. If the service.ListAll returns an error, it sends an appropriate error response to the client. + // 4. If the service.ListAll returns a response, it sets the status code to 200 (OK) and sends the response as a JSON payload to the client. + // + // Useful for get single, fetch multiple and search operations. + errors.OK(ctx, service.ListAll, ListRequest{}) + } +} + +func listHandler(service *myService) iris.Handler { + return func(ctx iris.Context) { + errors.List(ctx, service.ListPaginated) + } +} + +func deleteHandler(service *myService) iris.Handler { + return func(ctx iris.Context) { + id := ctx.Params().Get("id") + // What it does? + // 1. Calls the service.DeleteWithFeedback function with the given input parameter. + // 2. If the service.DeleteWithFeedback returns an error, it sends an appropriate error response to the client. + // 3.If the service.DeleteWithFeedback doesn't return an error then it sets the status code to 204 (No Content) and + // sends the response as a JSON payload to the client. + // errors.NoContent(ctx, service.Delete, id) + // OR: + // 1. Calls the service.DeleteWithFeedback function with the given input parameter. + // 2. If the service.DeleteWithFeedback returns an error, it sends an appropriate error response to the client. + // 3. If the service.DeleteWithFeedback returns true, it sets the status code to 204 (No Content). + // 4. If the service.DeleteWithFeedback returns false, it sets the status code to 304 (Not Modified). + // + // Useful for update and delete operations. + errors.NoContentOrNotModified(ctx, service.DeleteWithFeedback, id) + } +} + +type ( + myService struct{} + + CreateRequest struct { + Fullname string `json:"fullname"` + Age int `json:"age"` + Hobbies []string `json:"hobbies"` + } + + CreateResponse struct { + ID string `json:"id"` + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Age int `json:"age"` + Hobbies []string `json:"hobbies"` + } +) + +// HandleRequest implements the errors.RequestHandler interface. +// It validates the request body and returns an error if the request body is invalid. +// You can also alter the "r" CreateRequest before calling the service method, +// e.g. give a default value to a field if it's empty or set an ID based on a path parameter. +// OR +// Custom function per route: +// +// r.Post("/", errors.Validation(validateCreateRequest), createHandler(service)) +// [more code here...] +// +// func validateCreateRequest(ctx iris.Context, r *CreateRequest) error { +// return validation.Join( +// validation.String("fullname", r.Fullname).NotEmpty().Fullname().Length(3, 50), +// validation.Number("age", r.Age).InRange(18, 130), +// validation.Slice("hobbies", r.Hobbies).Length(1, 10), +// ) +// } +func (r *CreateRequest) HandleRequest(ctx iris.Context) error { + // To pass custom validation functions: + // return validation.Join( + // validation.String("fullname", r.Fullname).Func(customStringFuncHere), + // OR + // validation.Field("any_field", r.AnyFieldValue).Func(customAnyFuncHere)) + return validation.Join( + validation.String("fullname", r.Fullname).Fullname().Length(3, 50), + validation.Number("age", r.Age).InRange(18, 130), + validation.Slice("hobbies", r.Hobbies).Length(1, 10), + ) + + /* Example Output: + { + "http_error_code": { + "canonical_name": "INVALID_ARGUMENT", + "status": 400 + }, + "message": "validation failure", + "details": "fields were invalid", + "validation": [ + { + "field": "fullname", + "value": "", + "reason": "must not be empty, must contain first and last name, must be between 3 and 50 characters" + }, + { + "field": "age", + "value": 0, + "reason": "must be in range of [18, 130]" + }, + { + "field": "hobbies", + "value": null, + "reason": "must be between 1 and 10 elements" + } + ] + } + */ +} + +/* +// HandleResponse implements the errors.ResponseHandler interface. +func (r *CreateRequest) HandleResponse(ctx iris.Context, resp *CreateResponse) error { + fmt.Printf("request got: %+v\nresponse sent: %#+v\n", r, resp) + + return nil // fmt.Errorf("let's fire an internal server error just for the shake of the example") // return nil to continue. +} +*/ + +func afterServiceCallButBeforeDataSent(ctx iris.Context, req CreateRequest, resp *CreateResponse) error { + fmt.Printf("intercept: request got: %+v\nresponse sent: %#+v\n", req, resp) + return nil +} + +func (s *myService) Create(ctx context.Context, in CreateRequest) (CreateResponse, error) { + arr := strings.Split(in.Fullname, " ") + firstname, lastname := arr[0], arr[1] + id := "test_id" + + resp := CreateResponse{ + ID: id, + Firstname: firstname, + Lastname: lastname, + Age: in.Age, + Hobbies: in.Hobbies, + } + return resp, nil // , errors.New("create: test error") +} + +type ListRequest struct { +} + +func (s *myService) ListAll(ctx context.Context, in ListRequest) ([]CreateResponse, error) { + resp := []CreateResponse{ + { + ID: "test-id-1", + Firstname: "test first name 1", + Lastname: "test last name 1", + }, + { + ID: "test-id-2", + Firstname: "test first name 2", + Lastname: "test last name 2", + }, + { + ID: "test-id-3", + Firstname: "test first name 3", + Lastname: "test last name 3", + }, + } + + return resp, nil //, errors.New("list all: test error") +} + +type ListFilter struct { + Firstname string `json:"firstname"` +} + +func (s *myService) ListPaginated(ctx context.Context, opts pagination.ListOptions, filter ListFilter) ([]CreateResponse, int /* any number type */, error) { + all, err := s.ListAll(ctx, ListRequest{}) + if err != nil { + return nil, 0, err + } + + filteredResp := make([]CreateResponse, 0) + for _, v := range all { + if strings.Contains(v.Firstname, filter.Firstname) { + filteredResp = append(filteredResp, v) + } + + if len(filteredResp) == opts.GetLimit() { + break + } + } + + return filteredResp, len(all), nil // errors.New("list paginated: test error") +} + +func (s *myService) GetByID(ctx context.Context, id string) (CreateResponse, error) { + return CreateResponse{Firstname: "Gerasimos"}, nil // errors.New("get by id: test error") +} + +func (s *myService) Delete(ctx context.Context, id string) error { + return nil // errors.New("delete: test error") +} + +func (s *myService) Update(ctx context.Context, req CreateRequest) (bool, error) { + return true, nil // false, errors.New("update: test error") +} + +func (s *myService) DeleteWithFeedback(ctx context.Context, id string) (bool, error) { + return true, nil // false, errors.New("delete: test error") +} diff --git a/routing/intelligence/main.go b/routing/intelligence/main.go new file mode 100644 index 00000000..dbc2c631 --- /dev/null +++ b/routing/intelligence/main.go @@ -0,0 +1,24 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.Get("/home", handler) + app.Get("/contact", handler) + app.Get("/contract", handler) + + // http://localhost:8080/home + // http://localhost:8080/hom + // + // http://localhost:8080/contact + // http://localhost:8080/cont + // + // http://localhost:8080/contract + // http://localhost:8080/contr + app.Listen(":8080", iris.WithPathIntelligence) +} + +func handler(ctx iris.Context) { + ctx.Writef("Path: %s", ctx.Path()) +} diff --git a/routing/intelligence/manual/main.go b/routing/intelligence/manual/main.go new file mode 100644 index 00000000..b2bfb5a8 --- /dev/null +++ b/routing/intelligence/manual/main.go @@ -0,0 +1,37 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.OnErrorCode(iris.StatusNotFound, notFound) + + // [register some routes...] + app.Get("/home", handler) + app.Get("/news", handler) + app.Get("/news/politics", handler) + app.Get("/user/profile", handler) + app.Get("/user", handler) + app.Get("/newspaper", handler) + app.Get("/user/{id}", handler) + + app.Listen(":8080") +} + +func notFound(ctx iris.Context) { + suggestPaths := ctx.FindClosest(3) + if len(suggestPaths) == 0 { + ctx.WriteString("404 not found") + return + } + + ctx.HTML("Did you mean?<ul>") + for _, s := range suggestPaths { + ctx.HTML(`<li><a href="%s">%s</a></li>`, s, s) + } + ctx.HTML("</ul>") +} + +func handler(ctx iris.Context) { + ctx.Writef("Path: %s", ctx.Path()) +} diff --git a/routing/macros/main.go b/routing/macros/main.go new file mode 100644 index 00000000..9c4c9be1 --- /dev/null +++ b/routing/macros/main.go @@ -0,0 +1,77 @@ +// Package main shows how you can register a custom parameter type and macro functions that belongs to it. +// See _examples/routing/dynamic-path/main.go first. +package main + +import ( + "fmt" + "reflect" + "sort" + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/context" + "github.com/kataras/iris/v12/hero" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + app.Macros().Register("slice", "", []string{}, false, true, func(paramValue string) (interface{}, bool) { + return strings.Split(paramValue, "/"), true + }).RegisterFunc("contains", func(expectedItems []string) func(paramValue []string) bool { + sort.Strings(expectedItems) + return func(paramValue []string) bool { + if len(paramValue) != len(expectedItems) { + return false + } + + sort.Strings(paramValue) + for i := 0; i < len(paramValue); i++ { + if paramValue[i] != expectedItems[i] { + return false + } + } + + return true + } + }) + + // In order to use your new param type inside MVC controller's function input argument or a hero function input argument + // you have to tell the Iris what type it is, the `ValueRaw` of the parameter is the same type + // as you defined it above with the func(paramValue string) (interface{}, bool). + // The new value and its type(from string to your new custom type) it is stored only once now, + // you don't have to do any conversions for simple cases like this. + context.ParamResolvers[reflect.TypeOf([]string{})] = func(paramIndex int) interface{} { + return func(ctx iris.Context) []string { + // When you want to retrieve a parameter with a value type that it is not supported by-default, such as ctx.Params().GetInt + // then you can use the `GetEntry` or `GetEntryAt` and cast its underline `ValueRaw` to the desired type. + // The type should be the same as the macro's evaluator function (last argument on the Macros#Register) return value. + return ctx.Params().GetEntryAt(paramIndex).ValueRaw.([]string) + } + } + + /* + http://localhost:8080/test_slice_hero/myvaluei1/myavlue2 -> + myparam's value (a trailing path parameter type) is: []string{"myvalue1", "myavlue2"} + */ + app.Get("/test_slice_hero/{myparam:slice}", hero.Handler(func(myparam []string) string { + return fmt.Sprintf("myparam's value (a trailing path parameter type) is: %#v\n", myparam) + })) + + /* + http://localhost:8080/test_slice_contains/notcontains1/value2 -> + (404) Not Found + + http://localhost:8080/test_slice_contains/value1/value2 -> + myparam's value (a trailing path parameter type) is: []string{"value1", "value2"} + */ + app.Get("/test_slice_contains/{myparam:slice contains([value1,value2])}", func(ctx iris.Context) { + // When it is not a builtin function available to retrieve your value with the type you want, such as ctx.Params().GetInt + // then you can use the `GetEntry.ValueRaw` to get the real value, which is set-ed by your macro above. + myparam := ctx.Params().GetEntry("myparam").ValueRaw.([]string) + ctx.Writef("myparam's value (a trailing path parameter type) is: %#v\n", myparam) + }) + + app.Listen(":8080") +} diff --git a/routing/main.go b/routing/main.go index d9af5f3d..5dd843c0 100644 --- a/routing/main.go +++ b/routing/main.go @@ -1,9 +1,7 @@ package main import ( - "io/ioutil" - - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) /* @@ -35,25 +33,25 @@ func registerGamesRoutes(app *iris.Application) { { // braces are optional of course, it's just a style of code // "GET" method - games.Get("/{gameID:int}/clans", h) - games.Get("/{gameID:int}/clans/clan/{clanPublicID:int}", h) - games.Get("/{gameID:int}/clans/search", h) + games.Get("/{gameID:uint64}/clans", h) + games.Get("/{gameID:uint64}/clans/clan/{clanPublicID:uint64}", h) + games.Get("/{gameID:uint64}/clans/search", h) // "PUT" method - games.Put("/{gameID:int}/players/{clanPublicID:int}", h) - games.Put("/{gameID:int}/clans/clan/{clanPublicID:int}", h) + games.Put("/{gameID:uint64}/players/{clanPublicID:uint64}", h) + games.Put("/{gameID:uint64}/clans/clan/{clanPublicID:uint64}", h) // remember: "clanPublicID" should not be changed to other routes with the same prefix. // "POST" method - games.Post("/{gameID:int}/clans", h) - games.Post("/{gameID:int}/players", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/leave", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/application", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/application/{action}", h) // {action} == {action:string} - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/invitation", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/invitation/{action}", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/delete", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/promote", h) - games.Post("/{gameID:int}/clans/{clanPublicID:int}/memberships/demote", h) + games.Post("/{gameID:uint64}/clans", h) + games.Post("/{gameID:uint64}/players", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/leave", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/application", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/application/{action}", h) // {action} == {action:string} + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/invitation", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/invitation/{action}", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/delete", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/promote", h) + games.Post("/{gameID:uint64}/clans/{clanPublicID:uint64}/memberships/demote", h) gamesCh := games.Party("/challenge") { @@ -84,17 +82,18 @@ func registerGamesRoutes(app *iris.Application) { } func registerSubdomains(app *iris.Application) { - mysubdomain := app.Party("mysubdomain.") + mysubdomain := app.Subdomain("mysubdomain") // http://mysubdomain.myhost.com mysubdomain.Get("/", h) - willdcardSubdomain := app.Party("*.") + willdcardSubdomain := app.WildcardSubdomain() willdcardSubdomain.Get("/", h) willdcardSubdomain.Party("/party").Get("/", h) } func newApp() *iris.Application { app := iris.New() + registerErrors(app) registerGamesRoutes(app) registerSubdomains(app) @@ -108,7 +107,7 @@ func newApp() *iris.Application { // to protect ourselves from "over heating". app.Post("/", iris.LimitRequestBodySize(maxBodySize), func(ctx iris.Context) { // get request body - b, err := ioutil.ReadAll(ctx.Request().Body) + b, err := ctx.GetBody() // if is larger then send a bad request status if err != nil { ctx.StatusCode(iris.StatusBadRequest) @@ -179,5 +178,5 @@ func main() { // FIRE NOT FOUND http://localhost:8080/coudlntfound */ - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/routing/main_test.go b/routing/main_test.go index e588ea85..cf12c9fe 100644 --- a/routing/main_test.go +++ b/routing/main_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func calculatePathAndResponse(method, subdomain, path string, paramKeyValue ...string) (string, string) { @@ -75,7 +75,7 @@ func TestRouting(t *testing.T) { app := newApp() e := httptest.New(t, app) - var tests = []troute{ + tests := []troute{ // GET newTroute("GET", "", "/healthcheck", httptest.StatusOK), newTroute("GET", "", "/games/{gameID}/clans", httptest.StatusOK, "gameID", "42"), @@ -116,26 +116,26 @@ func TestRouting(t *testing.T) { if tt.subdomain != "" { et.WithURL("http://" + tt.subdomain + ".localhost:8080") } - et.Expect().Status(tt.status).Body().Equal(tt.expectedBody) + et.Expect().Status(tt.status).Body().IsEqual(tt.expectedBody) } // test POST "/" limit data and post data return // test with small body - e.POST("/").WithBytes([]byte("ok")).Expect().Status(httptest.StatusOK).Body().Equal("ok") + e.POST("/").WithBytes([]byte("ok")).Expect().Status(httptest.StatusOK).Body().IsEqual("ok") // test with equal to max body size limit bsent := make([]byte, maxBodySize, maxBodySize) e.POST("/").WithBytes(bsent).Expect().Status(httptest.StatusOK).Body().Length().Equal(len(bsent)) // test with larger body sent and wait for the custom response largerBSent := make([]byte, maxBodySize+1, maxBodySize+1) - e.POST("/").WithBytes(largerBSent).Expect().Status(httptest.StatusBadRequest).Body().Equal("http: request body too large") + e.POST("/").WithBytes(largerBSent).Expect().Status(httptest.StatusBadRequest).Body().IsEqual("http: request body too large") // test the post value (both post and put) and headers. e.PUT("/postvalue").WithFormField("name", "test_put"). WithHeader("headername", "headervalue_put").Expect(). - Status(httptest.StatusOK).Body().Equal("Hello test_put | headervalue_put") + Status(httptest.StatusOK).Body().IsEqual("Hello test_put | headervalue_put") e.POST("/postvalue").WithFormField("name", "test_post"). WithHeader("headername", "headervalue_post").Expect(). - Status(httptest.StatusOK).Body().Equal("Hello test_post | headervalue_post") + Status(httptest.StatusOK).Body().IsEqual("Hello test_post | headervalue_post") } diff --git a/overview/main.go b/routing/overview-2/main.go similarity index 83% rename from overview/main.go rename to routing/overview-2/main.go index 29e52560..c4b2e29b 100644 --- a/overview/main.go +++ b/routing/overview-2/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // User is just a bindable object structure. @@ -15,7 +15,8 @@ type User struct { func main() { app := iris.New() - // app.Logger().SetLevel("disable") to disable the logger + app.Logger().SetLevel("debug") + // app.Logger().SetLevel("disable") to disable the logger. // Define templates using the std html/template engine. // Parse and load all files inside "./views" folder with ".html" file extension. @@ -73,8 +74,16 @@ func main() { usersRoutes.Post("/create", createUser) } + app.Get("/", func(ctx iris.Context) { + ctx.HTML("<html><head></head><body><ul>") + for _, link := range []string{"/encode", "/profile/username", "/users/42"} { + ctx.HTML(`<li><a href="%s">%s</a></li>`, link, link) + } + ctx.HTML("</ul></body></html>") + }) + // Listen for incoming HTTP/1.x & HTTP/2 clients on localhost port 8080. - app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8"), iris.WithoutVersionChecker) + app.Listen(":8080", iris.WithCharset("utf-8")) } func logThisMiddleware(ctx iris.Context) { @@ -91,7 +100,10 @@ func profileByUsername(ctx iris.Context) { ctx.ViewData("Username", username) // renders "./views/user/profile.html" // with {{ .Username }} equals to the username dynamic path parameter. - ctx.View("user/profile.html") + if err := ctx.View("user/profile.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } func getUserByID(ctx iris.Context) { @@ -113,5 +125,8 @@ func createUser(ctx iris.Context) { // renders "./views/user/create_verification.html" // with {{ . }} equals to the User object, i.e {{ .Username }} , {{ .Firstname}} etc... ctx.ViewData("", user) - ctx.View("user/create_verification.html") + if err := ctx.View("user/create_verification.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } diff --git a/overview/views/user/create_verification.html b/routing/overview-2/views/user/create_verification.html similarity index 100% rename from overview/views/user/create_verification.html rename to routing/overview-2/views/user/create_verification.html diff --git a/overview/views/user/profile.html b/routing/overview-2/views/user/profile.html similarity index 100% rename from overview/views/user/profile.html rename to routing/overview-2/views/user/profile.html diff --git a/routing/overview/main.go b/routing/overview/main.go index 65c15dc6..0c42bfcd 100644 --- a/routing/overview/main.go +++ b/routing/overview/main.go @@ -1,11 +1,26 @@ package main import ( - "github.com/kataras/iris" + "os" + "time" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/logger" ) func main() { app := iris.New() + // Set Logger level to "debug", + // see your terminal and the created file. + app.Logger().SetLevel("debug") + + // Write logs to a file too. + f := newLogFile() + defer f.Close() + app.Logger().AddOutput(f) + + // Register a request logger middleware to the application. + app.Use(logger.New()) // GET: http://localhost:8080 app.Get("/", info) @@ -31,21 +46,19 @@ func main() { // Static assets - // GET: http://localhost:8080/assets/css/bootstrap.min.css - // maps to ./public/assets/css/bootstrap.min.css file at system location. - // GET: http://localhost:8080/assets/js/react.min.js - // maps to ./public/assets/js/react.min.js file at system location. - app.StaticWeb("/assets", "./public/assets") + // GET: http://localhost:8080/assets/css/main.css + // maps to ./public/assets/css/main.css file at system location. + app.HandleDir("/assets", iris.Dir("./public/assets")) /* OR - // GET: http://localhost:8080/js/react.min.js - // maps to ./public/assets/js/react.min.js file at system location. - app.StaticWeb("/js", "./public/assets/js") + // GET: http://localhost:8080/css/main.css + // maps to ./public/assets/css/main.css file at system location. + app.HandleDir("/css", iris.Dir("./public/assets/css")) // GET: http://localhost:8080/css/bootstrap.min.css // maps to ./public/assets/css/bootstrap.min.css file at system location. - app.StaticWeb("/css", "./public/assets/css") + app.HandleDir("/css", iris.Dir("./public/assets/css")) */ @@ -68,8 +81,8 @@ func main() { // GET: http://localhost:8080/users/42 // **/users/42 and /users/help works after iris version 7.0.5** - usersRoutes.Get("/{id:int}", func(ctx iris.Context) { - id, _ := ctx.Params().GetInt("id") + usersRoutes.Get("/{id:uint64}", func(ctx iris.Context) { + id, _ := ctx.Params().GetUint64("id") ctx.Writef("get user by id: %d", id) }) @@ -80,21 +93,21 @@ func main() { }) // PUT: http://localhost:8080/users - usersRoutes.Put("/{id:int}", func(ctx iris.Context) { - id, _ := ctx.Params().GetInt("id") // or .Get to get its string represatantion. + usersRoutes.Put("/{id:uint64}", func(ctx iris.Context) { + id, _ := ctx.Params().GetUint64("id") // or .Get to get its string represatantion. username := ctx.PostValue("username") ctx.Writef("update user for id= %d and new username= %s", id, username) }) // DELETE: http://localhost:8080/users/42 - usersRoutes.Delete("/{id:int}", func(ctx iris.Context) { - id, _ := ctx.Params().GetInt("id") + usersRoutes.Delete("/{id:uint64}", func(ctx iris.Context) { + id, _ := ctx.Params().GetUint64("id") ctx.Writef("delete user by id: %d", id) - }) + }).Describe("deletes a user") // Subdomains, depends on the host, you have to edit the hosts or nginx/caddy's configuration if you use them. // - // See more subdomains examples at _examples/subdomains folder. + // See more subdomains examples at _examples/routing/subdomains folder. adminRoutes := app.Party("admin.") // GET: http://admin.localhost:8080 @@ -103,7 +116,7 @@ func main() { adminRoutes.Get("/settings", info) // Wildcard/dynamic subdomain - dynamicSubdomainRoutes := app.Party("*.") + dynamicSubdomainRoutes := app.WildcardSubdomain() // GET: http://any_thing_here.localhost:8080 dynamicSubdomainRoutes.Get("/", info) @@ -113,6 +126,9 @@ func main() { ctx.Writef(name) }) + app.None("/secret", privateHandler) + app.Get("/public", execPrivateHandler) + // GET: http://localhost:8080/ // GET: http://localhost:8080/profile/anyusername // GET: http://localhost:8080/profile/anyusername/backups/any/number/of/paths/here @@ -128,7 +144,16 @@ func main() { // GET: http://admin.localhost:8080 // GET: http://admin.localhost:8080/settings // GET: http://any_thing_here.localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") +} + +func privateHandler(ctx iris.Context) { + ctx.WriteString(`This can only be executed programmatically through server's another route: +ctx.Exec(iris.MethodNone, "/secret")`) +} + +func execPrivateHandler(ctx iris.Context) { + ctx.Exec(iris.MethodNone, "/secret") } func info(ctx iris.Context) { @@ -147,3 +172,21 @@ func info(ctx iris.Context) { ctx.Writef("\nInfo\n\n") ctx.Writef("Method: %s\nSubdomain: %s\nPath: %s\nParameters length: %d", method, subdomain, path, paramsLen) } + +// get a filename based on the date, file logs works that way the most times +// but these are just a sugar. +func todayFilename() string { + today := time.Now().Format("Jan 02 2006") + return today + ".txt" +} + +func newLogFile() *os.File { + filename := todayFilename() + // open an output file, this will append to the today's file if server restarted. + f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + panic(err) + } + + return f +} diff --git a/routing/overview/public/assets/css/main.css b/routing/overview/public/assets/css/main.css new file mode 100644 index 00000000..7db3df1d --- /dev/null +++ b/routing/overview/public/assets/css/main.css @@ -0,0 +1,3 @@ +body { + background-color: black; +} diff --git a/routing/party-controller/go.mod b/routing/party-controller/go.mod new file mode 100644 index 00000000..0862cc9b --- /dev/null +++ b/routing/party-controller/go.mod @@ -0,0 +1,51 @@ +module github.com/kataras/iris/_examples/routing/party-controller + +go 1.22 + +require github.com/kataras/iris/v12 v12.2.11 + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/routing/party-controller/go.sum b/routing/party-controller/go.sum new file mode 100644 index 00000000..94127478 --- /dev/null +++ b/routing/party-controller/go.sum @@ -0,0 +1,178 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/routing/party-controller/main.go b/routing/party-controller/main.go new file mode 100644 index 00000000..b97b0daa --- /dev/null +++ b/routing/party-controller/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/_examples/routing/party-controller/pkg/weatherapi" +) + +// Example of usage of Party Controllers. +// The method of zero-performance cost at serve-time, APIs run as fast as common Iris handlers. +func main() { + app := iris.New() + + // Define a group under /api request path. + api := app.Party("/api") + // Register one or more dependencies. + api.RegisterDependency(weatherapi.NewClient(weatherapi.Options{ + APIKey: "{YOUR_API_KEY}", + })) + + // Register a party controller under the "/weather" sub request path. + api.PartyConfigure("/weather", new(WeatherController)) + + // Start the local server at 8080 port. + app.Listen(":8080") +} + +// Just like the MVC controllers, route group(aka Party) controller's +// fields are injected by the parent or current party's RegisterDependency method. +// +// This controller structure could be live to another sub-package of our application as well. +type WeatherController struct { + Client *weatherapi.Client // This is automatically injected by .RegisterDependency. +} + +func (api *WeatherController) Configure(r iris.Party) { + // Register routes under /api/weather. + r.Get("/current", api.getCurrentData) +} + +// Normal Iris Handler. +func (api *WeatherController) getCurrentData(ctx iris.Context) { + city := ctx.URLParamDefault("city", "Athens") + + // Call the controller's "Client"'s GetCurrentByCity method + // to retrieve data from external provider and push them to our clients. + data, err := api.Client.GetCurrentByCity(ctx, city) + if err != nil { + ctx.StatusCode(iris.StatusBadRequest) + ctx.JSON(iris.Map{ + "error": err.Error(), + }) + return + } + + ctx.JSON(data) +} diff --git a/routing/party-controller/pkg/weatherapi/client.go b/routing/party-controller/pkg/weatherapi/client.go new file mode 100644 index 00000000..52c02dc0 --- /dev/null +++ b/routing/party-controller/pkg/weatherapi/client.go @@ -0,0 +1,43 @@ +package weatherapi + +import ( + "context" + "net/url" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/x/client" +) + +// The BaseURL of our API client. +const BaseURL = "https://api.weatherapi.com/v1" + +type ( + Options struct { + APIKey string `json:"api_key" yaml:"APIKey" toml:"APIKey"` + } + + Client struct { + *client.Client + } +) + +func NewClient(opts Options) *Client { + apiKeyParameterSetter := client.RequestParam("key", opts.APIKey) + + c := client.New(client.BaseURL(BaseURL), + client.PersistentRequestOptions(apiKeyParameterSetter)) + + return &Client{c} +} + +func (c *Client) GetCurrentByCity(ctx context.Context, city string) (resp Response, err error) { + urlpath := "/current.json" + // ?q=Athens&aqi=no + params := client.RequestQuery(url.Values{ + "q": []string{city}, + "aqi": []string{"no"}, + }) + + err = c.Client.ReadJSON(ctx, &resp, iris.MethodGet, urlpath, nil, params) + return +} diff --git a/routing/party-controller/pkg/weatherapi/response.go b/routing/party-controller/pkg/weatherapi/response.go new file mode 100644 index 00000000..e6903a26 --- /dev/null +++ b/routing/party-controller/pkg/weatherapi/response.go @@ -0,0 +1,43 @@ +package weatherapi + +type Response struct { + Location struct { + Name string `json:"name"` + Region string `json:"region"` + Country string `json:"country"` + Lat float64 `json:"lat"` + Lon float64 `json:"lon"` + TzID string `json:"tz_id"` + LocaltimeEpoch int `json:"localtime_epoch"` + Localtime string `json:"localtime"` + } `json:"location"` + Current struct { + LastUpdatedEpoch int `json:"last_updated_epoch"` + LastUpdated string `json:"last_updated"` + TempC float64 `json:"temp_c"` + TempF float64 `json:"temp_f"` + IsDay int `json:"is_day"` + Condition struct { + Text string `json:"text"` + Icon string `json:"icon"` + Code int `json:"code"` + } `json:"condition"` + WindMph float64 `json:"wind_mph"` + WindKph float64 `json:"wind_kph"` + WindDegree int `json:"wind_degree"` + WindDir string `json:"wind_dir"` + PressureMb float64 `json:"pressure_mb"` + PressureIn float64 `json:"pressure_in"` + PrecipMm float64 `json:"precip_mm"` + PrecipIn float64 `json:"precip_in"` + Humidity int `json:"humidity"` + Cloud int `json:"cloud"` + FeelslikeC float64 `json:"feelslike_c"` + FeelslikeF float64 `json:"feelslike_f"` + VisKm float64 `json:"vis_km"` + VisMiles float64 `json:"vis_miles"` + Uv float64 `json:"uv"` + GustMph float64 `json:"gust_mph"` + GustKph float64 `json:"gust_kph"` + } `json:"current"` +} diff --git a/routing/remove-handler/main.go b/routing/remove-handler/main.go new file mode 100644 index 00000000..7aca5fd2 --- /dev/null +++ b/routing/remove-handler/main.go @@ -0,0 +1,29 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := newApp() + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + + api := app.Party("/api") + api.Use(myMiddleware) + users := api.Party("/users") + users.Get("/", usersIndex).RemoveHandler(myMiddleware) + // OR for all routes under a Party (or Application): + // users.RemoveHandler(...) + + return app +} + +func myMiddleware(ctx iris.Context) { + ctx.WriteString("Middleware\n") +} + +func usersIndex(ctx iris.Context) { + ctx.WriteString("OK") +} diff --git a/routing/remove-handler/main_test.go b/routing/remove-handler/main_test.go new file mode 100644 index 00000000..b9978345 --- /dev/null +++ b/routing/remove-handler/main_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestSimpleRouteRemoveHandler(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + e.GET("/api/users").Expect().Status(httptest.StatusOK).Body().IsEqual("OK") +} diff --git a/routing/remove-route/main.go b/routing/remove-route/main.go new file mode 100644 index 00000000..8c684ca1 --- /dev/null +++ b/routing/remove-route/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.Get("/", index) + app.Get("/about", about).SetName("about_page") + app.RemoveRoute("about_page") + + // http://localhost:8080 + // http://localhost:8080/about (Not Found) + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.WriteString("Hello, Gophers!") +} + +func about(ctx iris.Context) { + ctx.HTML("<h1>About Page</h1>") +} diff --git a/routing/reverse/main.go b/routing/reverse/main.go index 1ab53c11..e6ae7413 100644 --- a/routing/reverse/main.go +++ b/routing/reverse/main.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/core/router" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/core/router" ) func main() { @@ -35,6 +35,5 @@ func main() { // // See view/template_html_4 example for more reverse routing examples // using the reverse router component and the {{url}} and {{urlpath}} template functions. - app.Run(iris.Addr(":8080")) - + app.Listen(":8080") } diff --git a/routing/rewrite/hosts b/routing/rewrite/hosts new file mode 100644 index 00000000..d31e56d9 --- /dev/null +++ b/routing/rewrite/hosts @@ -0,0 +1,4 @@ +127.0.0.1 mydomain.com +127.0.0.1 www.mydomain.com +127.0.0.1 test.mydomain.com +127.0.0.1 newtest.mydomain.com diff --git a/routing/rewrite/main.go b/routing/rewrite/main.go new file mode 100644 index 00000000..d6d48ee3 --- /dev/null +++ b/routing/rewrite/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/rewrite" +) + +func main() { + app := iris.New() + + app.Get("/", index) + app.Get("/about", about) + app.Get("/docs", docs) + app.Get("/users", listUsers) + + app.Subdomain("test").Get("/", testIndex) + + newtest := app.Subdomain("newtest") + newtest.Get("/", newTestIndex) + newtest.Get("/about", newTestAbout) + + redirects := rewrite.Load("redirects.yml") + app.WrapRouter(redirects) + + // http://mydomain.com:8080/seo/about -> http://www.mydomain.com:8080/about + // http://test.mydomain.com:8080 -> http://newtest.mydomain.com:8080 + // http://test.mydomain.com:8080/seo/about -> http://newtest.mydomain.com:8080/about + // http://mydomain.com:8080/seo -> http://www.mydomain.com:8080 + // http://mydomain.com:8080/about + // http://mydomain.com:8080/docs/v12/hello -> http://www.mydomain.com:8080/docs + // http://mydomain.com:8080/docs/v12some -> http://www.mydomain.com:8080/docs + // http://mydomain.com:8080/oldsome -> http://www.mydomain.com:8080 + // http://mydomain.com:8080/oldindex/random -> http://www.mydomain.com:8080 + // http://mydomain.com:8080/users.json -> http://www.mydomain.com:8080/users?format=json + app.Listen(":8080") +} + +func index(ctx iris.Context) { + ctx.WriteString("Index") +} + +func about(ctx iris.Context) { + ctx.WriteString("About") +} + +func docs(ctx iris.Context) { + ctx.WriteString("Docs") +} + +func listUsers(ctx iris.Context) { + format := ctx.URLParamDefault("format", "text") + /* + switch format{ + case "json": + ctx.JSON(response) + case "xml": + ctx.XML(response) + // [...] + } + */ + ctx.Writef("Format: %s", format) +} + +func testIndex(ctx iris.Context) { + ctx.WriteString(`Test Subdomain Index + (This should never be executed, + redirects to newtest subdomain)`) +} + +func newTestIndex(ctx iris.Context) { + ctx.WriteString("New Test Subdomain Index") +} + +func newTestAbout(ctx iris.Context) { + ctx.WriteString("New Test Subdomain About") +} + +/* More... +rewriteOptions := rewrite.Options{ + RedirectMatch: []string{ + "301 /seo/(.*) /$1", + "301 /docs/v12(.*) /docs", + "301 /old(.*) /", + "301 ^(http|https)://test.(.*) $1://newtest.$2", + "0 /(.*).(json|xml) /$1?format=$2", + }, + PrimarySubdomain: "www", +} +rewriteEngine, err := rewrite.New(rewriteOptions) + +// To use it per-party use its `Handler` method. Even if not route match: +app.UseRouter(rewriteEngine.Handler) +// To use it per-party when route match: +app.Use(rewriteEngine.Handler) +// +// To use it on a single route just pass it to the Get/Post method. +// +// To make the entire application respect the redirect rules +// you have to wrap the Iris Router and pass the `Rewrite` method instead +// as we did at this example: +// app.WrapRouter(rewriteEngine.Rewrite) +*/ diff --git a/routing/rewrite/redirects.yml b/routing/rewrite/redirects.yml new file mode 100644 index 00000000..389bb522 --- /dev/null +++ b/routing/rewrite/redirects.yml @@ -0,0 +1,24 @@ +RedirectMatch: # REDIRECT_CODE_DIGITS | PATTERN_REGEX | TARGET_REPL + # Redirects /seo/* to /* + - 301 /seo/(.*) /$1 + + # Redirects /docs/v12* to /docs + - 301 /docs/v12(.*) /docs + + # Redirects /old(.*) to / + - 301 /old(.*) / + + # Redirects http or https://test.* to http or https://newtest.* + - 301 ^(http|https)://test.(.*) $1://newtest.$2 + + # Handles /*.json or .xml as *?format=json or xml, + # WITHOUT redirect. See /users route. + # When Code is 0 then it does not redirect the request, + # instead it changes the request URL + # and leaves a route handle the request. + - 0 /(.*).(json|xml) /$1?format=$2 + +# Redirects root domain to www. +# Creation of a www subdomain inside the Application is unnecessary, +# all requests are handled by the root Application itself. +PrimarySubdomain: www diff --git a/routing/route-handlers-execution-rules/main.go b/routing/route-handlers-execution-rules/main.go new file mode 100644 index 00000000..73675729 --- /dev/null +++ b/routing/route-handlers-execution-rules/main.go @@ -0,0 +1,61 @@ +/* +Package main is a simple example of the behavior change of the execution flow of the handlers, +normally we need the `ctx.Next()` to call the next handler in a route's handler chain, +but with the `ExecutionRules` we can change this default behavior. +Please read below before continue. + +The `Party#SetExecutionRules` alters the execution flow of the route handlers. + +For example, if for some reason the desired result is the (done or all) handlers +to be executed no matter what, even if no `ctx.Next()` is called in the previous handlers: + + app.SetExecutionRules(iris.ExecutionRules { + Begin: iris.ExecutionOptions{Force: true}, # begin handlers(.Use) + Main: iris.ExecutionOptions{Force: true}, # main handler (.Handle/Get...) + Done: iris.ExecutionOptions{Force: true}, # done handlers (.Done) + }) + +Note that if `true` then the only remained way to "break" the handler chain +is by calling the `ctx.StopExecution()` (now that `ctx.Next()` doesn't even matter). + +These rules are per-party, so if a `Party` creates a child one then +the same rules will be applied to that as well. + +Reset of these rules to their defaults (before `Party#Handle`) can be done +with `Party#SetExecutionRules(iris.ExecutionRules{})`. +*/ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.SetExecutionRules(iris.ExecutionRules{ + // * From `Use[all]` to `Handle[last]` future route handlers, + // execute all (even if `ctx.Next()` is missing): + // Begin: true, + // + // * All `Handle` future route handlers, execute all: + // Main: true, + // + // * From `Handle[last]` to `Done[last]` future route handlers, execute all: + Done: iris.ExecutionOptions{Force: true}, + }) + app.Done(doneHandler) + + app.Get("/", mainHandler) + + // http://localhost:8080 + app.Listen(":8080") +} + +func mainHandler(ctx iris.Context) { + ctx.WriteString("From Main Handler\n") + // ctx.Next() is not required now that we have declared + // Done: iris.ExecutionOptions{Force: true}. +} + +func doneHandler(ctx iris.Context) { + ctx.WriteString("From Done Handler\n") +} diff --git a/routing/route-register-rule/main.go b/routing/route-register-rule/main.go new file mode 100644 index 00000000..31f5cb08 --- /dev/null +++ b/routing/route-register-rule/main.go @@ -0,0 +1,45 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := newApp() + // Navigate through https://github.com/kataras/iris/issues/1448 for details. + // + // GET: http://localhost:8080 + // POST, PUT, DELETE, CONNECT, HEAD, PATCH, OPTIONS, TRACE : http://localhost:8080 + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + // Skip and do NOT override existing regitered route, continue normally. + // Applies to a Party and its children, in this case the whole application's routes. + app.SetRegisterRule(iris.RouteSkip) + + /* Read also: + // The default behavior, will override the getHandler to anyHandler on `app.Any` call. + app.SetRegistRule(iris.RouteOverride) + + // Stops the execution and fires an error before server boot. + app.SetRegisterRule(iris.RouteError) + + // If ctx.StopExecution or StopWithXXX then the next route will be executed + // (see mvc/authenticated-controller example too). + app.SetRegisterRule(iris.RouteOverlap) + */ + + app.Get("/", getHandler) + // app.Any does NOT override the previous GET route because of `iris.RouteSkip` rule. + app.Any("/", anyHandler) + + return app +} + +func getHandler(ctx iris.Context) { + ctx.Writef("From GET: %s", ctx.GetCurrentRoute().MainHandlerName()) +} + +func anyHandler(ctx iris.Context) { + ctx.Writef("From %s: %s", ctx.Method(), ctx.GetCurrentRoute().MainHandlerName()) +} diff --git a/routing/route-register-rule/main_test.go b/routing/route-register-rule/main_test.go new file mode 100644 index 00000000..9ac5ed9f --- /dev/null +++ b/routing/route-register-rule/main_test.go @@ -0,0 +1,22 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/core/router" + "github.com/kataras/iris/v12/httptest" +) + +func TestRouteRegisterRuleExample(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + for _, method := range router.AllMethods { + tt := e.Request(method, "/").Expect().Status(httptest.StatusOK).Body() + if method == "GET" { + tt.Equal("From GET: iris/_examples/routing/route-register-rule.getHandler") + } else { + tt.Equal("From " + method + ": iris/_examples/routing/route-register-rule.anyHandler") + } + } +} diff --git a/routing/route-state/main.go b/routing/route-state/main.go index ec4f03db..d59b8c81 100644 --- a/routing/route-state/main.go +++ b/routing/route-state/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -16,7 +16,6 @@ func main() { }) app.Get("/change", func(ctx iris.Context) { - if none.IsOnline() { none.Method = iris.MethodNone } else { @@ -28,11 +27,19 @@ func main() { }) app.Get("/execute", func(ctx iris.Context) { + if !none.IsOnline() { + ctx.Values().Set("from", "/execute with offline access") + ctx.Exec("NONE", "/invisible/iris") + return + } + // same as navigating to "http://localhost:8080/invisible/iris" when /change has being invoked and route state changed // from "offline" to "online" ctx.Values().Set("from", "/execute") // values and session can be shared when calling Exec from a "foreign" context. + // ctx.Exec("NONE", "/invisible/iris") + // or after "/change": ctx.Exec("GET", "/invisible/iris") }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080", iris.WithDynamicHandler) } diff --git a/routing/sitemap/main.go b/routing/sitemap/main.go new file mode 100644 index 00000000..fa7c9f7d --- /dev/null +++ b/routing/sitemap/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" +) + +const startURL = "http://localhost:8080" + +func main() { + app := newApp() + + // http://localhost:8080/sitemap.xml + // Lists only online GET static routes. + // + // Reference: https://www.sitemaps.org/protocol.html + app.Listen(":8080", iris.WithSitemap(startURL)) +} + +func newApp() *iris.Application { + app := iris.New() + app.Logger().SetLevel("debug") + + lastModified, _ := time.Parse("2006-01-02T15:04:05-07:00", "2019-12-13T21:50:33+02:00") + app.Get("/home", handler).SetLastMod(lastModified).SetChangeFreq("hourly").SetPriority(1) + app.Get("/articles", handler).SetChangeFreq("daily") + app.Get("/path1", handler) + app.Get("/path2", handler) + + app.Post("/this-should-not-be-listed", handler) + app.Get("/this/{myparam}/should/not/be/listed", handler) + app.Get("/this-should-not-be-listed-offline", handler).SetStatusOffline() + + // These should be excluded as well + app.Get("/about", handler).ExcludeSitemap() + app.Get("/offline", handler).SetStatusOffline() + + return app +} + +func handler(ctx iris.Context) { ctx.WriteString(ctx.Path()) } diff --git a/routing/sitemap/main_test.go b/routing/sitemap/main_test.go new file mode 100644 index 00000000..9ec53af1 --- /dev/null +++ b/routing/sitemap/main_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" +) + +func TestSitemap(t *testing.T) { + const expectedFullSitemapXML = `<?xml version="1.0" encoding="utf-8" standalone="yes"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>http://localhost:8080/home</loc><lastmod>2019-12-13T21:50:33+02:00</lastmod><changefreq>hourly</changefreq><priority>1</priority></url><url><loc>http://localhost:8080/articles</loc><changefreq>daily</changefreq></url><url><loc>http://localhost:8080/path1</loc></url><url><loc>http://localhost:8080/path2</loc></url></urlset>` + + app := newApp() + app.Configure(iris.WithSitemap(startURL)) + + e := httptest.New(t, app) + e.GET("/sitemap.xml").Expect().Status(httptest.StatusOK).Body().IsEqual(expectedFullSitemapXML) +} diff --git a/routing/subdomains/http-errors-view/main.go b/routing/subdomains/http-errors-view/main.go new file mode 100644 index 00000000..34fe93e4 --- /dev/null +++ b/routing/subdomains/http-errors-view/main.go @@ -0,0 +1,41 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + newApp().Listen("mydomain.com:80", iris.WithLogLevel("debug")) +} + +func newApp() *iris.Application { + app := iris.New() + + // Create the "test.mydomain.com" subdomain. + test := app.Subdomain("test") + // Register views for the test subdomain. + test.RegisterView(iris.HTML("./views", ".html"). + Layout("layouts/test.layout.html")) + + // Optionally, to minify the HTML5 error response. + // Note that minification might be slower, caching is advised. + // test.UseError(iris.Minify) + // or pass it to OnErrorCode: + // Register error code 404 handler. + test.OnErrorCode(iris.StatusNotFound, iris.Minify, handleNotFoundTestSubdomain) + + test.Get("/", testIndex) + + return app +} + +func handleNotFoundTestSubdomain(ctx iris.Context) { + if err := ctx.View("error.html", iris.Map{ + "ErrorCode": ctx.GetStatusCode(), + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func testIndex(ctx iris.Context) { + ctx.Writef("%s index page\n", ctx.Subdomain()) +} diff --git a/routing/subdomains/http-errors-view/main_test.go b/routing/subdomains/http-errors-view/main_test.go new file mode 100644 index 00000000..7af2fa03 --- /dev/null +++ b/routing/subdomains/http-errors-view/main_test.go @@ -0,0 +1,40 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestSubdomainsHTTPErrorsView(t *testing.T) { + app := newApp() + // hard coded. + expectedHTMLResponse := `<html> + <head> + <title>Test Subdomain</title> + + </head> + <body> + + <div style="background-color: black; color: red"> + <h1>Oups, you've got an error!</h1> + + + <div style="background-color: white; color: red"> + <h1>Not Found</h1> + </div> + + + </div> + + </body> + </html>` + + e := httptest.New(t, app) + got := e.GET("/not_found").WithURL("http://test.mydomain.com").Expect().Status(httptest.StatusNotFound). + ContentType("text/html", "utf-8").Body().Raw() + + if expected, _ := app.Minifier().String("text/html", expectedHTMLResponse); expected != got { + t.Fatalf("expected:\n'%s'\nbut got:\n'%s'", expected, got) + } +} diff --git a/routing/subdomains/http-errors-view/views/error.html b/routing/subdomains/http-errors-view/views/error.html new file mode 100644 index 00000000..bad88d5b --- /dev/null +++ b/routing/subdomains/http-errors-view/views/error.html @@ -0,0 +1,9 @@ +<div style="background-color: black; color: red"> + <h1>Oups, you've got an error!</h1> + {{ if .ErrorCode }} + {{ $tmplName := print "partials/" .ErrorCode ".html"}} + {{ render $tmplName . }} + {{ else }} + {{ render "partials/500.html" . }} + {{ end }} +</div> diff --git a/routing/subdomains/http-errors-view/views/index.html b/routing/subdomains/http-errors-view/views/index.html new file mode 100644 index 00000000..736e3395 --- /dev/null +++ b/routing/subdomains/http-errors-view/views/index.html @@ -0,0 +1,3 @@ +<div style="background-color: black; color: blue"> + Index Page +</div> diff --git a/routing/subdomains/http-errors-view/views/layouts/layout.html b/routing/subdomains/http-errors-view/views/layouts/layout.html new file mode 100644 index 00000000..cd6fa3d5 --- /dev/null +++ b/routing/subdomains/http-errors-view/views/layouts/layout.html @@ -0,0 +1,12 @@ +<html> +<head> +<title>Website Layout</title> + +</head> +<body> + <h1>This is the global layout</h1> + <br /> + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/routing/subdomains/http-errors-view/views/layouts/test.layout.html b/routing/subdomains/http-errors-view/views/layouts/test.layout.html new file mode 100644 index 00000000..957cee95 --- /dev/null +++ b/routing/subdomains/http-errors-view/views/layouts/test.layout.html @@ -0,0 +1,10 @@ +<html> +<head> +<title>Test Subdomain</title> + +</head> +<body> + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/routing/subdomains/http-errors-view/views/partials/404.html b/routing/subdomains/http-errors-view/views/partials/404.html new file mode 100644 index 00000000..1a621016 --- /dev/null +++ b/routing/subdomains/http-errors-view/views/partials/404.html @@ -0,0 +1,3 @@ +<div style="background-color: white; color: red"> + <h1>Not Found</h1> +</div> diff --git a/routing/subdomains/http-errors-view/views/partials/500.html b/routing/subdomains/http-errors-view/views/partials/500.html new file mode 100644 index 00000000..355dace2 --- /dev/null +++ b/routing/subdomains/http-errors-view/views/partials/500.html @@ -0,0 +1,3 @@ +<div style="background-color: white; color: red"> + <h1>Internal Server Error</h1> +</div> diff --git a/subdomains/multi/hosts b/routing/subdomains/multi/hosts similarity index 100% rename from subdomains/multi/hosts rename to routing/subdomains/multi/hosts diff --git a/subdomains/multi/main.go b/routing/subdomains/multi/main.go similarity index 75% rename from subdomains/multi/main.go rename to routing/subdomains/multi/main.go index 5878f5f3..aa16296f 100644 --- a/subdomains/multi/main.go +++ b/routing/subdomains/multi/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -11,8 +11,8 @@ func main() { * Setup static files */ - app.StaticWeb("/assets", "./public/assets") - app.StaticWeb("/upload_resources", "./public/upload_resources") + app.HandleDir("/assets", iris.Dir("./public/assets")) + app.HandleDir("/upload_resources", iris.Dir("./public/upload_resources")) dashboard := app.Party("dashboard.") { @@ -36,5 +36,5 @@ func main() { // Make sure you prepend the "http" in your browser // because .local is a virtual domain we think to show case you // that you can declare any syntactical correct name as a subdomain in iris. - app.Run(iris.Addr("domain.local:80")) // for beginners: look ../hosts file + app.Listen("domain.local:80") // for beginners: look ../hosts file } diff --git a/subdomains/multi/public/assets/images/test.ico b/routing/subdomains/multi/public/assets/images/test.ico similarity index 100% rename from subdomains/multi/public/assets/images/test.ico rename to routing/subdomains/multi/public/assets/images/test.ico diff --git a/routing/subdomains/multi/public/upload_resources/favicon.ico b/routing/subdomains/multi/public/upload_resources/favicon.ico new file mode 100644 index 00000000..c370da51 Binary files /dev/null and b/routing/subdomains/multi/public/upload_resources/favicon.ico differ diff --git a/subdomains/redirect/hosts b/routing/subdomains/redirect/hosts similarity index 82% rename from subdomains/redirect/hosts rename to routing/subdomains/redirect/hosts index c4c06478..b4cd51fe 100644 --- a/subdomains/redirect/hosts +++ b/routing/subdomains/redirect/hosts @@ -1,4 +1,5 @@ 127.0.0.1 mydomain.com 127.0.0.1 www.mydomain.com +127.0.0.1 otherdomain.com # Windows: Drive:/Windows/system32/drivers/etc/hosts, on Linux: /etc/hosts \ No newline at end of file diff --git a/routing/subdomains/redirect/main.go b/routing/subdomains/redirect/main.go new file mode 100644 index 00000000..132f90e7 --- /dev/null +++ b/routing/subdomains/redirect/main.go @@ -0,0 +1,59 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/rewrite" +) + +func main() { + app := newApp() + + // http://mydomain.com -> http://www.mydomain.com + // http://mydomain.com/user -> http://www.mydomain.com/user + // http://mydomain.com/user/login -> http://www.mydomain.com/user/login + app.Listen(":80") +} + +func newApp() *iris.Application { + app := iris.New() + app.Logger().SetLevel("debug") + + static := app.Subdomain("static") + static.Get("/", staticIndex) + + app.Get("/", index) + userRouter := app.Party("/user") + userRouter.Get("/", userGet) + userRouter.Get("/login", userGetLogin) + + // redirects := rewrite.Load("redirects.yml") + // ^ see _examples/routing/rewrite example for that. + // + // Now let's do that by code. + rewriteEngine, _ := rewrite.New(rewrite.Options{ + PrimarySubdomain: "www", + }) + // Enable this line for debugging: + // rewriteEngine.SetLogger(app.Logger()) + app.WrapRouter(rewriteEngine.Rewrite) + + return app +} + +func staticIndex(ctx iris.Context) { + ctx.Writef("This is the static.mydomain.com index.") +} + +func index(ctx iris.Context) { + ctx.Writef("This is the www.mydomain.com index.") +} + +func userGet(ctx iris.Context) { + // Also, ctx.Subdomain(), ctx.SubdomainFull(), ctx.Host() and ctx.Path() + // can be helpful when working with subdomains. + ctx.Writef("This is the www.mydomain.com/user endpoint.") +} + +func userGetLogin(ctx iris.Context) { + ctx.Writef("This is the www.mydomain.com/user/login endpoint.") +} diff --git a/routing/subdomains/redirect/multi-instances/go.mod b/routing/subdomains/redirect/multi-instances/go.mod new file mode 100644 index 00000000..d68bbeea --- /dev/null +++ b/routing/subdomains/redirect/multi-instances/go.mod @@ -0,0 +1,51 @@ +module github.com/kataras/iris/_examples/routing/subdomains/redirect/multi-instances + +go 1.22 + +require github.com/kataras/iris/v12 v12.2.11 + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/routing/subdomains/redirect/multi-instances/go.sum b/routing/subdomains/redirect/multi-instances/go.sum new file mode 100644 index 00000000..94127478 --- /dev/null +++ b/routing/subdomains/redirect/multi-instances/go.sum @@ -0,0 +1,178 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/routing/subdomains/redirect/multi-instances/main.go b/routing/subdomains/redirect/multi-instances/main.go new file mode 100644 index 00000000..d3e59279 --- /dev/null +++ b/routing/subdomains/redirect/multi-instances/main.go @@ -0,0 +1,70 @@ +package main + +import ( + _ "github.com/kataras/iris/_examples/routing/subdomains/redirect/multi-instances/other" + _ "github.com/kataras/iris/_examples/routing/subdomains/redirect/multi-instances/root" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/apps" +) + +// In this example, you wanna use three different applications exposed as one. +// The first one is the "other" package, the second is the "root", +// the third is the switcher application which will expose the above. +// Unlike the previous example, on this one we will NOT redirect, +// the Hosts switcher will just pass the request to the matched Application to handle. +// This is NOT an alternative of your favorite load balancer. +// Read the comments carefully, if you need more information +// you can head over to the "apps" package's godocs and tests. +func main() { + // The `apps.Hosts` switch provider: + // The pattern. A regexp for matching the host part of incoming requests. + // The target. An iris.Application instance (created by iris.New()) + // OR + // You can use the Application's name (app.SetName("myapp")). + // Example: + // package rootdomain + // func init() { + // app := iris.New().SetName("root app") + // ... + // } + // On the main package add an empty import statement: ` _ import "rootdomain"` + // And set the "root app" as the key to reference that application (of the same program). + // Thats the target we wanna use now ^ (see ../hosts file). + // OR + // An external host or a local running in the same machine but different port or host behind proxy. + switcher := apps.Switch(apps.Hosts{ + {"^(www.)?mydomain.com$", "root app"}, + {"^otherdomain.com$", "other app"}, + }) + // The registration order matters, so we can register a fallback server (when host no match) + // using "*". However, you have alternatives by using the Switch Iris Application value + // (let's call it "switcher"): + // 1. Handle the not founds, e.g. switcher.OnErrorCode(404, ...) + // 2. Use the switcher.WrapRouter, e.g. to log the flow of a request of all hosts exposed. + // 3. Just register routes to match, e.g. switcher.Get("/", ...) + switcher.Get("/", fallback) + // OR + // Change the response code to 502 + // instead of 404 and write a message: + // switcher.OnErrorCode(iris.StatusNotFound, fallback) + + // The switcher is a common Iris Application, so you have access to the Iris features. + // And it should be listening to a host:port in order to match and serve its apps. + // + // http://mydomain.com (OK) + // http://www.mydomain.com (OK) + // http://mydomain.com/dsa (404) + // http://no.mydomain.com (502 Bad Host) + // + // http://otherdomain.com (OK) + // http://www.otherdomain.com (502 Bad Host) + // http://otherdomain.com/dsa (404 JSON) + // ... + switcher.Listen(":80") +} + +func fallback(ctx iris.Context) { + ctx.StatusCode(iris.StatusBadGateway) + ctx.Writef("Bad Host %s", ctx.Host()) +} diff --git a/routing/subdomains/redirect/multi-instances/other/server.go b/routing/subdomains/redirect/multi-instances/other/server.go new file mode 100644 index 00000000..7452a406 --- /dev/null +++ b/routing/subdomains/redirect/multi-instances/other/server.go @@ -0,0 +1,30 @@ +package other + +import ( + "time" + + "github.com/kataras/iris/v12" +) + +func init() { + app := iris.New() + app.SetName("other app") + + app.OnAnyErrorCode(handleErrors) + app.Get("/", index) +} + +func index(ctx iris.Context) { + ctx.HTML("Other Index (App Name: <b>%s</b> | Host: <b>%s</b>)", + ctx.Application().String(), ctx.Host()) +} + +func handleErrors(ctx iris.Context) { + errCode := ctx.GetStatusCode() + ctx.JSON(iris.Map{ + "Server": ctx.Application().String(), + "Code": errCode, + "Message": iris.StatusText(errCode), + "Timestamp": time.Now().Unix(), + }) +} diff --git a/routing/subdomains/redirect/multi-instances/root/server.go b/routing/subdomains/redirect/multi-instances/root/server.go new file mode 100644 index 00000000..79aa9792 --- /dev/null +++ b/routing/subdomains/redirect/multi-instances/root/server.go @@ -0,0 +1,15 @@ +package root + +import "github.com/kataras/iris/v12" + +func init() { + app := iris.New() + app.SetName("root app") + + app.Get("/", index) +} + +func index(ctx iris.Context) { + ctx.HTML("Main Root Index (App Name: <b>%s</b> | Host: <b>%s</b>)", + ctx.Application().String(), ctx.Host()) +} diff --git a/subdomains/single/hosts b/routing/subdomains/single/hosts similarity index 100% rename from subdomains/single/hosts rename to routing/subdomains/single/hosts diff --git a/subdomains/single/main.go b/routing/subdomains/single/main.go similarity index 75% rename from subdomains/single/main.go rename to routing/subdomains/single/main.go index 2c70510d..ef972c05 100644 --- a/subdomains/single/main.go +++ b/routing/subdomains/single/main.go @@ -2,16 +2,14 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { app := iris.New() - // subdomains works with all available routers, like other features too. - - // no order, you can register subdomains at the end also. - admin := app.Party("admin.") + // Subdomain method is just another Party. + admin := app.Subdomain("admin") { // admin.mydomain.com admin.Get("/", func(c iris.Context) { @@ -27,7 +25,7 @@ func main() { }) } - // mydomain.com/ + // mydomain.com app.Get("/", func(c iris.Context) { c.Writef("INDEX FROM no-subdomain hey") }) @@ -42,5 +40,5 @@ func main() { // http://admin.mydomain.com/hey2 // http://mydomain.com // http://mydomain.com/hey - app.Run(iris.Addr("mydomain.com:80")) // for beginners: look ../hosts file + app.Listen("mydomain.com:80") // for beginners: look ../hosts file } diff --git a/subdomains/wildcard/hosts b/routing/subdomains/wildcard/hosts similarity index 96% rename from subdomains/wildcard/hosts rename to routing/subdomains/wildcard/hosts index 3b3b5664..a2cd47cf 100644 --- a/subdomains/wildcard/hosts +++ b/routing/subdomains/wildcard/hosts @@ -26,5 +26,5 @@ 127.0.0.1 username3.mydomain.com 127.0.0.1 username4.mydomain.com 127.0.0.1 username5.mydomain.com - +127.0.0.1 en-us.test.mydomain.com #-END iris- diff --git a/subdomains/wildcard/main.go b/routing/subdomains/wildcard/main.go similarity index 82% rename from subdomains/wildcard/main.go rename to routing/subdomains/wildcard/main.go index 2735ab5d..fb12f8f0 100644 --- a/subdomains/wildcard/main.go +++ b/routing/subdomains/wildcard/main.go @@ -1,10 +1,10 @@ // Package main an example on how to catch dynamic subdomains - wildcard. -// On the first example (subdomains_1) we saw how to create routes for static subdomains, subdomains you know that you will have. +// On the first example we learnt how to create routes for static subdomains, subdomains you know that you will have. // Here we will see an example how to catch unknown subdomains, dynamic subdomains, like username.mydomain.com:8080. package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // register a dynamic-wildcard subdomain to your server machine(dns/...) first, check ./hosts if you use windows. @@ -33,7 +33,7 @@ func main() { }*/ // no order, you can register subdomains at the end also. - dynamicSubdomains := app.Party("*.") + dynamicSubdomains := app.WildcardSubdomain() { dynamicSubdomains.Get("/", dynamicSubdomainHandler) @@ -54,7 +54,8 @@ func main() { // http://username1.mydomain.com:8080 // http://username2.mydomain.com:8080/something // http://username3.mydomain.com:8080/something/yourname - app.Run(iris.Addr("mydomain.com:8080")) // for beginners: look ../hosts file + // http://en-us.test.mydomain.com:8080/something/42 + app.Listen("mydomain.com:8080") // for beginners: look ../hosts file } func dynamicSubdomainHandler(ctx iris.Context) { @@ -66,6 +67,6 @@ func dynamicSubdomainHandler(ctx iris.Context) { func dynamicSubdomainHandlerWithParam(ctx iris.Context) { username := ctx.Subdomain() - ctx.Writef("Hello from dynamic subdomain path: %s, here you can handle the route for dynamic subdomains, handle the user: %s", ctx.Path(), username) + ctx.Writef("Hello from dynamic (full) subdomain: %s and path: %s, here you can handle the route for dynamic subdomains, handle the user: %s", ctx.SubdomainFull(), ctx.Path(), username) ctx.Writef("The paramfirst is: %s", ctx.Params().Get("paramfirst")) } diff --git a/subdomains/www/hosts b/routing/subdomains/www/hosts similarity index 100% rename from subdomains/www/hosts rename to routing/subdomains/www/hosts diff --git a/subdomains/www/main.go b/routing/subdomains/www/main.go similarity index 84% rename from subdomains/www/main.go rename to routing/subdomains/www/main.go index c41e343d..0215f6fa 100644 --- a/subdomains/www/main.go +++ b/routing/subdomains/www/main.go @@ -1,8 +1,6 @@ package main -import ( - "github.com/kataras/iris" -) +import "github.com/kataras/iris/v12" func newApp() *iris.Application { app := iris.New() @@ -13,11 +11,11 @@ func newApp() *iris.Application { app.PartyFunc("/api/users", func(r iris.Party) { r.Get("/", info) - r.Get("/{id:int}", info) + r.Get("/{id:uint64}", info) r.Post("/", info) - r.Put("/{id:int}", info) + r.Put("/{id:uint64}", info) }) /* <- same as: usersAPI := app.Party("/api/users") { // those brackets are just syntactic-sugar things. @@ -34,7 +32,7 @@ func newApp() *iris.Application { // party or subdomain: // Get all routes that are registered so far, including all "Parties" and subdomains: currentRoutes := app.GetRoutes() - // Register them to the www subdomain/vhost as well: + // Register them to the www subdomain/VHost as well: for _, r := range currentRoutes { www.Handle(r.Method, r.Tmpl().Src, r.Handlers...) } @@ -44,9 +42,9 @@ func newApp() *iris.Application { ctx.Writef("hi from www.mydomain.com") }) } - // See also the "subdomains/redirect" to register redirect router wrappers between subdomains, + // See "subdomains/redirect" to register redirect router wrappers between subdomains, // i.e mydomain.com to www.mydomain.com (like facebook does for SEO reasons(;)). - + // And ./www-method example. return app } @@ -64,9 +62,7 @@ func main() { // http://www.mydomain.com/contact // http://www.mydomain.com/api/users // http://www.mydomain.com/api/users/42 - if err := app.Run(iris.Addr("mydomain.com:80")); err != nil { - panic(err) - } + app.Listen("mydomain.com:80") } func info(ctx iris.Context) { diff --git a/subdomains/www/main_test.go b/routing/subdomains/www/main_test.go similarity index 87% rename from subdomains/www/main_test.go rename to routing/subdomains/www/main_test.go index db6c9421..7fd4c95d 100644 --- a/subdomains/www/main_test.go +++ b/routing/subdomains/www/main_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) type testRoute struct { @@ -41,7 +41,7 @@ func TestSubdomainWWW(t *testing.T) { } host := "localhost:1111" - e := httptest.New(t, app, httptest.URL("http://"+host), httptest.Debug(false)) + e := httptest.New(t, app, httptest.Debug(false)) for _, test := range tests { @@ -52,7 +52,6 @@ func TestSubdomainWWW(t *testing.T) { req.Expect(). Status(httptest.StatusOK). - Body().Equal(test.response()) + Body().IsEqual(test.response()) } - } diff --git a/routing/subdomains/www/www-method/main.go b/routing/subdomains/www/www-method/main.go new file mode 100644 index 00000000..b2fd4b65 --- /dev/null +++ b/routing/subdomains/www/www-method/main.go @@ -0,0 +1,51 @@ +package main + +import "github.com/kataras/iris/v12" + +func newApp() *iris.Application { + app := iris.New() + // This will create a new "www" subdomain + // and redirect root-level domain requests + // to that one: + www := app.WWW() + www.Get("/", info) + www.Get("/about", info) + www.Get("/contact", info) + + www.PartyFunc("/api/users", func(r iris.Party) { + r.Get("/", info) + r.Get("/{id:uint64}", info) + + r.Post("/", info) + + r.Put("/{id:uint64}", info) + }) + + return app +} + +func main() { + app := newApp() + // http://mydomain.com + // http://mydomain.com/about + // http://imydomain.com/contact + // http://mydomain.com/api/users + // http://mydomain.com/api/users/42 + + // http://www.mydomain.com + // http://www.mydomain.com/hi + // http://www.mydomain.com/about + // http://www.mydomain.com/contact + // http://www.mydomain.com/api/users + // http://www.mydomain.com/api/users/42 + app.Listen("mydomain.com:80") +} + +func info(ctx iris.Context) { + method := ctx.Method() + subdomain := ctx.Subdomain() + path := ctx.Path() + + ctx.Writef("\nInfo\n\n") + ctx.Writef("Method: %s\nSubdomain: %s\nPath: %s", method, subdomain, path) +} diff --git a/routing/versioning/main.go b/routing/versioning/main.go new file mode 100644 index 00000000..052a87a3 --- /dev/null +++ b/routing/versioning/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/versioning" +) + +func main() { + app := iris.New() + + app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) { + ctx.WriteString(`Root not found handler. + This will be applied everywhere except the /api/* requests.`) + }) + + api := app.Party("/api") + // Optional, set version aliases (literal strings). + // We use `UseRouter` instead of `Use` + // to handle HTTP errors per version, but it's up to you. + api.UseRouter(versioning.Aliases(versioning.AliasMap{ + // If no version provided by the client, default it to the "1.0.0". + versioning.Empty: "1.0.0", + // If a "latest" version is provided by the client, + // set the version to be compared to "3.0.0". + "latest": "3.0.0", + })) + + /* + A version is extracted through the versioning.GetVersion function, + request headers: + - Accept-Version: 1.0.0 + - Accept: application/json; version=1.0.0 + You can customize it by setting a version based on the request context: + api.Use(func(ctx *context.Context) { + if version := ctx.URLParam("version"); version != "" { + versioning.SetVersion(ctx, version) + } + + ctx.Next() + }) + OR: api.Use(versioning.FromQuery("version", "")) + */ + + // |----------------| + // | The fun begins | + // |----------------| + + // Create a new Group, which is a compatible Party, + // based on version constraints. + v1 := versioning.NewGroup(api, ">=1.0.0 <2.0.0") + // To mark an API version as deprecated use the Deprecated method. + // v1.Deprecated(versioning.DefaultDeprecationOptions) + + // Optionally, set custom view engine and path + // for templates based on the version. + v1.RegisterView(iris.HTML("./v1", ".html")) + + // Optionally, set custom error handler(s) based on the version. + // Keep in mind that if you do this, you will + // have to register error handlers + // for the rest of the parties as well. + v1.OnErrorCode(iris.StatusNotFound, testError("v1")) + + // Register resources based on the version. + v1.Get("/", testHandler("v1")) + v1.Get("/render", testView) + + // Do the same for version 2 and version 3, + // for the sake of the example. + v2 := versioning.NewGroup(api, ">=2.0.0 <3.0.0") + v2.RegisterView(iris.HTML("./v2", ".html")) + v2.OnErrorCode(iris.StatusNotFound, testError("v2")) + v2.Get("/", testHandler("v2")) + v2.Get("/render", testView) + + v3 := versioning.NewGroup(api, ">=3.0.0 <4.0.0") + v3.RegisterView(iris.HTML("./v3", ".html")) + v3.OnErrorCode(iris.StatusNotFound, testError("v3")) + v3.Get("/", testHandler("v3")) + v3.Get("/render", testView) + + app.Listen(":8080") +} + +func testHandler(v string) iris.Handler { + return func(ctx iris.Context) { + ctx.JSON(iris.Map{ + "version": v, + "message": "Hello, world!", + }) + } +} + +func testError(v string) iris.Handler { + return func(ctx iris.Context) { + ctx.Writef("not found: %s", v) + } +} + +func testView(ctx iris.Context) { + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/routing/versioning/v1/index.html b/routing/versioning/v1/index.html new file mode 100644 index 00000000..efe99490 --- /dev/null +++ b/routing/versioning/v1/index.html @@ -0,0 +1 @@ +<h1>This is the directory for version 1 templates</h1> \ No newline at end of file diff --git a/routing/versioning/v2/index.html b/routing/versioning/v2/index.html new file mode 100644 index 00000000..802d7081 --- /dev/null +++ b/routing/versioning/v2/index.html @@ -0,0 +1 @@ +<h1>This is the directory for version 2 templates</h1> \ No newline at end of file diff --git a/routing/versioning/v3/index.html b/routing/versioning/v3/index.html new file mode 100644 index 00000000..b1e3fdc7 --- /dev/null +++ b/routing/versioning/v3/index.html @@ -0,0 +1 @@ +<h1>This is the directory for version 3 templates</h1> \ No newline at end of file diff --git a/routing/writing-a-middleware/globally/main.go b/routing/writing-a-middleware/globally/main.go index b89ac7f1..2cd92e94 100644 --- a/routing/writing-a-middleware/globally/main.go +++ b/routing/writing-a-middleware/globally/main.go @@ -1,6 +1,6 @@ package main -import "github.com/kataras/iris" +import "github.com/kataras/iris/v12" func main() { app := iris.New() @@ -22,14 +22,14 @@ func main() { // are applied to existing routes and future routes. // // Remember: the `Use` and `Done` are applied to the current party's and its children, - // so if we used the `app.Use/Don`e before the routes registration + // so if we used the `app.Use/Done` before the routes registration // it would work like UseGlobal/DoneGlobal in this case, because the `app` is the root party. // // See `app.Party/PartyFunc` for more. app.UseGlobal(before) app.DoneGlobal(after) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func before(ctx iris.Context) { diff --git a/routing/writing-a-middleware/per-route/main.go b/routing/writing-a-middleware/per-route/main.go index 38440561..223a019f 100644 --- a/routing/writing-a-middleware/per-route/main.go +++ b/routing/writing-a-middleware/per-route/main.go @@ -1,6 +1,6 @@ package main -import "github.com/kataras/iris" +import "github.com/kataras/iris/v12" func main() { app := iris.New() @@ -38,7 +38,7 @@ are applied here as well.`) ctx.Next() // call the done handlers. }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func before(ctx iris.Context) { diff --git a/routing/writing-a-middleware/share-funcs/main.go b/routing/writing-a-middleware/share-funcs/main.go new file mode 100644 index 00000000..0b9be30d --- /dev/null +++ b/routing/writing-a-middleware/share-funcs/main.go @@ -0,0 +1,109 @@ +// Package main shows how you can share a +// function between handlers of the same chain. +// Note that, this case is very rarely used and it exists, +// mostly, for 3rd-party middleware creators. +// +// The middleware creator registers a dynamic function by Context.SetFunc and +// the route handler just needs to call Context.CallFunc(funcName, arguments), +// without knowning what is the specific middleware's implementation or who was the creator +// of that function, it may be a basicauth middleware's logout or session's logout. +// +// See Context.SetLogoutFunc and Context.Logout methods too (these are not covered here). +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + + // GET: http://localhost:8080 + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(middleware) + // OR app.UseRouter(middleware) + // to register it everywhere, + // including the HTTP errors. + + app.Get("/", handler) + app.Get("/2", middleware2, handler2) + app.Get("/3", middleware3, handler3) + + return app +} + +// Assume: this is a middleware which does not export +// the 'hello' function for several reasons +// but we offer a 'greeting' optional feature to the route handler. +func middleware(ctx iris.Context) { + ctx.SetFunc("greet", hello) + ctx.Next() +} + +// Assume: this is a handler which needs to "greet" the client but +// the function for that job is not predictable, +// it may change - dynamically (SetFunc) - depending on +// the middlewares registered before this route handler. +// E.g. it may be a "Hello $name" or "Greetings $Name". +func handler(ctx iris.Context) { + outputs, err := ctx.CallFunc("greet", "Gophers") + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + response := outputs[0].Interface().(string) + ctx.WriteString(response) +} + +func middleware2(ctx iris.Context) { + ctx.SetFunc("greet", sayHello) + ctx.Next() +} + +func handler2(ctx iris.Context) { + _, err := ctx.CallFunc("greet", "Gophers [2]") + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } +} + +func middleware3(ctx iris.Context) { + ctx.SetFunc("job", function3) + ctx.Next() +} + +func handler3(ctx iris.Context) { + _, err := ctx.CallFunc("job") + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + ctx.WriteString("OK, job was executed.\nSee the command prompt.") +} + +/* +| ------------------------ | +| function implementations | +| ------------------------ | +*/ + +func hello(name string) string { + return fmt.Sprintf("Hello, %s!", name) +} + +func sayHello(ctx iris.Context, name string) { + ctx.WriteString(hello(name)) +} + +func function3() { + fmt.Printf("function3 called\n") +} diff --git a/routing/writing-a-middleware/share-funcs/main_test.go b/routing/writing-a-middleware/share-funcs/main_test.go new file mode 100644 index 00000000..2dbc261d --- /dev/null +++ b/routing/writing-a-middleware/share-funcs/main_test.go @@ -0,0 +1,16 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestShareFuncs(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + e.GET("/").Expect().Status(httptest.StatusOK).Body().IsEqual("Hello, Gophers!") + e.GET("/2").Expect().Status(httptest.StatusOK).Body().IsEqual("Hello, Gophers [2]!") + e.GET("/3").Expect().Status(httptest.StatusOK).Body().IsEqual("OK, job was executed.\nSee the command prompt.") +} diff --git a/routing/writing-a-middleware/share-services/main.go b/routing/writing-a-middleware/share-services/main.go new file mode 100644 index 00000000..9deab8a8 --- /dev/null +++ b/routing/writing-a-middleware/share-services/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + + // GET: http://localhost:8080 + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(middleware) + // OR app.UseRouter(middleware) + // to register it everywhere, + // including the HTTP errors. + + app.Get("/", handler) + + return app +} + +func middleware(ctx iris.Context) { + service := &helloService{ + Greeting: "Hello", + } + setService(ctx, service) + + ctx.Next() +} + +func handler(ctx iris.Context) { + service, ok := getService(ctx) + if !ok { + ctx.StopWithStatus(iris.StatusInternalServerError) + return + } + + response := service.Greet("Gophers") + ctx.WriteString(response) +} + +/* +| ---------------------- | +| service implementation | +| ---------------------- | +*/ + +const serviceContextKey = "app.service" + +func setService(ctx iris.Context, service GreetService) { + ctx.Values().Set(serviceContextKey, service) +} + +func getService(ctx iris.Context) (GreetService, bool) { + v := ctx.Values().Get(serviceContextKey) + if v == nil { + return nil, false + } + + service, ok := v.(GreetService) + if !ok { + return nil, false + } + + return service, true +} + +// A GreetService example. +type GreetService interface { + Greet(name string) string +} + +type helloService struct { + Greeting string +} + +func (m *helloService) Greet(name string) string { + return fmt.Sprintf("%s, %s!", m.Greeting, name) +} diff --git a/routing/writing-a-middleware/share-services/main_test.go b/routing/writing-a-middleware/share-services/main_test.go new file mode 100644 index 00000000..e4024c31 --- /dev/null +++ b/routing/writing-a-middleware/share-services/main_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestShareServices(t *testing.T) { + app := newApp() + e := httptest.New(t, app) + + e.GET("/").Expect().Status(httptest.StatusOK).Body().IsEqual("Hello, Gophers!") +} diff --git a/sessions/README.md b/sessions/README.md deleted file mode 100644 index 0b25deb4..00000000 --- a/sessions/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# Sessions - -Iris provides a fast, fully featured and easy to use sessions manager. - -Iris sessions manager lives on its own [kataras/iris/sessions](https://github.com/kataras/iris/tree/master/sessions) package. - -Some trivial examples, - -- [Overview](https://github.com/kataras/iris/blob/master/_examples/sessions/overview/main.go) -- [Standalone](https://github.com/kataras/iris/blob/master/_examples/sessions/standalone/main.go) -- [Secure Cookie](https://github.com/kataras/iris/blob/master/_examples/sessions/securecookie/main.go) -- [Flash Messages](https://github.com/kataras/iris/blob/master/_examples/sessions/flash-messages/main.go) -- [Databases](https://github.com/kataras/iris/tree/master/_examples/sessions/database) - * [Badger](https://github.com/kataras/iris/blob/master/_examples/sessions/database/badger/main.go) **fastest** - * [BoltDB](https://github.com/kataras/iris/blob/master/_examples/sessions/database/boltdb/main.go) - * [Redis](https://github.com/kataras/iris/blob/master/_examples/sessions/database/redis/main.go) - -## Overview - -```go -import "github.com/kataras/iris/sessions" - -manager := sessions.Start(iris.Context) -manager. - ID() string - Get(string) interface{} - HasFlash() bool - GetFlash(string) interface{} - GetFlashString(string) string - GetString(key string) string - GetInt(key string) (int, error) - GetInt64(key string) (int64, error) - GetFloat32(key string) (float32, error) - GetFloat64(key string) (float64, error) - GetBoolean(key string) (bool, error) - GetAll() map[string]interface{} - GetFlashes() map[string]interface{} - VisitAll(cb func(k string, v interface{})) - Set(string, interface{}) - SetImmutable(key string, value interface{}) - SetFlash(string, interface{}) - Delete(string) - Clear() - ClearFlashes() -``` - -This example will show how to store data from a session. - -You don't need any third-party library except Iris, but if you want you can use anything, remember Iris is fully compatible with the standard library. You can find a more detailed examples by pressing [here](https://github.com/kataras/iris/tree/master/_examples/sessions). - -In this example we will only allow authenticated users to view our secret message on the `/secret` age. To get access to it, the will first have to visit `/login` to get a valid session cookie, hich logs him in. Additionally he can visit `/logout` to revoke his access to our secret message. - -```go -// sessions.go -package main - -import ( - "github.com/kataras/iris" - - "github.com/kataras/iris/sessions" -) - -var ( - cookieNameForSessionID = "mycookiesessionnameid" - sess = sessions.New(sessions.Config{Cookie: cookieNameForSessionID, AllowReclaim: true}) -) - -func secret(ctx iris.Context) { - // Check if user is authenticated - if auth, _ := sess.Start(ctx).GetBoolean("authenticated"); !auth { - ctx.StatusCode(iris.StatusForbidden) - return - } - - // Print secret message - ctx.WriteString("The cake is a lie!") -} - -func login(ctx iris.Context) { - session := sess.Start(ctx) - - // Authentication goes here - // ... - - // Set user as authenticated - session.Set("authenticated", true) -} - -func logout(ctx iris.Context) { - session := sess.Start(ctx) - - // Revoke users authentication - session.Set("authenticated", false) -} - -func main() { - app := iris.New() - - app.Get("/secret", secret) - app.Get("/login", login) - app.Get("/logout", logout) - - app.Run(iris.Addr(":8080")) -} - -``` - -```bash -$ go run sessions.go - -$ curl -s http://localhost:8080/secret -Forbidden - -$ curl -s -I http://localhost:8080/login -Set-Cookie: mysessionid=MTQ4NzE5Mz... - -$ curl -s --cookie "mysessionid=MTQ4NzE5Mz..." http://localhost:8080/secret -The cake is a lie! -``` \ No newline at end of file diff --git a/sessions/basic/main.go b/sessions/basic/main.go new file mode 100644 index 00000000..93944c40 --- /dev/null +++ b/sessions/basic/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/v12/sessions" +) + +const cookieNameForSessionID = "session_id_cookie" + +func secret(ctx iris.Context) { + // Check if user is authenticated + if auth, _ := sessions.Get(ctx).GetBoolean("authenticated"); !auth { + ctx.StatusCode(iris.StatusForbidden) + return + } + + // Print secret message + ctx.WriteString("The cake is a lie!") +} + +func login(ctx iris.Context) { + session := sessions.Get(ctx) + + // Authentication goes here + // ... + + // Set user as authenticated + session.Set("authenticated", true) +} + +func logout(ctx iris.Context) { + session := sessions.Get(ctx) + + // Revoke users authentication + session.Set("authenticated", false) +} + +func main() { + app := iris.New() + sess := sessions.New(sessions.Config{ + Cookie: cookieNameForSessionID, + // CookieSecureTLS: true, + AllowReclaim: true, + }) + app.Use(sess.Handler()) + // ^ or comment this line and use sess.Start(ctx) inside your handlers + // instead of sessions.Get(ctx). + + app.Get("/secret", secret) + app.Get("/login", login) + app.Get("/logout", logout) + + app.Listen(":8080") +} diff --git a/sessions/database/badger/main.go b/sessions/database/badger/main.go index 400d2969..d49c1dbb 100644 --- a/sessions/database/badger/main.go +++ b/sessions/database/badger/main.go @@ -3,10 +3,12 @@ package main import ( "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/sessions/sessiondb/badger" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/sessions/sessiondb/badger" + + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) func main() { @@ -22,75 +24,33 @@ func main() { defer db.Close() // close and unlock the database if application errored. + // The default transcoder is the JSON one, + // based on the https://golang.org/pkg/encoding/json/#Unmarshal + // you can only retrieve numbers as float64 types: + // * bool, for booleans + // * float64, for numbers + // * string, for strings + // * []interface{}, for arrays + // * map[string]interface{}, for objects. + // If you want to save the data per go-specific types + // you should change the DefaultTranscoder to the GobTranscoder one: + // sessions.DefaultTranscoder = sessions.GobTranscoder{} + sess := sessions.New(sessions.Config{ Cookie: "sessionscookieid", - Expires: 45 * time.Minute, // <=0 means unlimited life. Defaults to 0. + Expires: 1 * time.Minute, // <=0 means unlimited life. Defaults to 0. AllowReclaim: true, }) + sess.OnDestroy(func(sid string) { + println(sid + " expired and destroyed from memory and its values from database") + }) + // // IMPORTANT: // sess.UseDatabase(db) - // the rest of the code stays the same. - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) - //set session values - s.Set("name", "iris") - - //test if setted here - ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - - // test if setted here - ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key)) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString("name") - - ctx.Writef("The 'name' on the /set was: %s", name) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sess.Start(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - //destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - - app.Get("/update", func(ctx iris.Context) { - // updates expire date with a new date - sess.ShiftExpiration(ctx) - }) - - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app := example.NewApp(sess) + app.Listen(":8080") } diff --git a/sessions/database/boltdb/main.go b/sessions/database/boltdb/main.go index 9e7d6d41..11bc9621 100644 --- a/sessions/database/boltdb/main.go +++ b/sessions/database/boltdb/main.go @@ -4,10 +4,12 @@ import ( "os" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/sessions/sessiondb/boltdb" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/sessions/sessiondb/boltdb" + + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) func main() { @@ -22,7 +24,6 @@ func main() { }) defer db.Close() // close and unlock the database if application errored. - sess := sessions.New(sessions.Config{ Cookie: "sessionscookieid", Expires: 45 * time.Minute, // <=0 means unlimited life. Defaults to 0. @@ -34,64 +35,29 @@ func main() { // sess.UseDatabase(db) - // the rest of the code stays the same. - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) - //set session values - s.Set("name", "iris") - - //test if setted here - ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - - // test if setted here - ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key)) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString("name") - - ctx.Writef("The 'name' on the /set was: %s", name) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sess.Start(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - //destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - - app.Get("/update", func(ctx iris.Context) { - // updates expire date with a new date - sess.ShiftExpiration(ctx) - }) + // The default database's values encoder and decoder + // calls the value's `Marshal/Unmarshal` methods (if any) + // otherwise JSON is selected, + // the JSON format can be stored to any database and + // it supports both builtin language types(e.g. string, int) and custom struct values. + // Also, and the most important, the values can be + // retrieved/logged/monitored by a third-party program + // written in any other language as well. + // + // You can change this behavior by registering a custom `Transcoder`. + // Iris provides a `GobTranscoder` which is mostly suitable + // if your session values are going to be custom Go structs. + // Select this if you always retrieving values through Go. + // Don't forget to initialize a call of gob.Register when necessary. + // Read https://golang.org/pkg/encoding/gob/ for more. + // + // You can also implement your own `sessions.Transcoder` and use it, + // i.e: a transcoder which will allow(on Marshal: return its byte representation and nil error) + // or dissalow(on Marshal: return non nil error) certain types. + // + // gob.Register(example.BusinessModel{}) + // sessions.DefaultTranscoder = sessions.GobTranscoder{} - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app := example.NewApp(sess) + app.Listen(":8080") } diff --git a/sessions/database/redis/Dockerfile b/sessions/database/redis/Dockerfile new file mode 100644 index 00000000..a1d50355 --- /dev/null +++ b/sessions/database/redis/Dockerfile @@ -0,0 +1,16 @@ +FROM golang:latest AS builder +RUN apt-get update +WORKDIR /go/src/app +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 +# Caching go modules and build the binary. +COPY go.mod . +RUN go mod download +COPY . . +RUN go install + +FROM scratch +COPY --from=builder /go/bin/app . +ENTRYPOINT ["./app"] \ No newline at end of file diff --git a/sessions/database/redis/docker-compose.yml b/sessions/database/redis/docker-compose.yml new file mode 100644 index 00000000..324b7534 --- /dev/null +++ b/sessions/database/redis/docker-compose.yml @@ -0,0 +1,24 @@ +# docker-compose up [--build] +version: '3' + +services: + redis-server: + image: redis + app1: + build: . + depends_on: + - redis-server + ports: + - 8080:8080 + environment: + - PORT=8080 + - REDIS_ADDR=redis-server:6379 + app2: + build: . + depends_on: + - redis-server + ports: + - 9090:9090 + environment: + - PORT=9090 + - REDIS_ADDR=redis-server:6379 \ No newline at end of file diff --git a/sessions/database/redis/go.mod b/sessions/database/redis/go.mod new file mode 100644 index 00000000..ae3800d7 --- /dev/null +++ b/sessions/database/redis/go.mod @@ -0,0 +1,54 @@ +module app + +go 1.22 + +require github.com/kataras/iris/v12 v12.2.11 + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/redis/go-redis/v9 v9.5.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/sessions/database/redis/go.sum b/sessions/database/redis/go.sum new file mode 100644 index 00000000..fea21bc8 --- /dev/null +++ b/sessions/database/redis/go.sum @@ -0,0 +1,188 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/sessions/database/redis/main.go b/sessions/database/redis/main.go index 88257c8d..e7f7cea5 100644 --- a/sessions/database/redis/main.go +++ b/sessions/database/redis/main.go @@ -1,124 +1,78 @@ package main import ( + "fmt" + "os" + "strings" "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12/sessions" + "github.com/kataras/iris/v12/sessions/sessiondb/redis" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/sessions/sessiondb/redis" - "github.com/kataras/iris/sessions/sessiondb/redis/service" + "github.com/kataras/iris/v12/_examples/sessions/overview/example" ) -// tested with redis version 3.0.503. -// for windows see: https://github.com/ServiceStack/redis-windows +// 1. Install Redis: +// 1.1 Windows: https://github.com/ServiceStack/redis-windows +// 1.2 Other: https://redis.io/download +// 2. Run command: go run -mod=mod main.go +// +// Tested with redis version 3.0.503. func main() { - // replace with your running redis' server settings: - db := redis.New(service.Config{ - Network: "tcp", - Addr: "127.0.0.1:6379", - Password: "", - Database: "", - MaxIdle: 0, - MaxActive: 0, - IdleTimeout: time.Duration(5) * time.Minute, - Prefix: ""}) // optionally configure the bridge between your redis server - - // close connection when control+C/cmd+C - iris.RegisterOnInterrupt(func() { - db.Close() + // These are the default values, + // you can replace them based on your running redis' server settings: + db := redis.New(redis.Config{ + Network: "tcp", + Addr: getenv("REDIS_ADDR", "127.0.0.1:6379"), + Timeout: time.Duration(30) * time.Second, + MaxActive: 10, + Username: "", + Password: "", + Database: "", + Prefix: "myapp-", + Driver: redis.GoRedis(), // defaults to this driver. + // To set a custom, existing go-redis client, use the "SetClient" method: + // Driver: redis.GoRedis().SetClient(customGoRedisClient) }) + // Optionally configure the underline driver: + // driver := redis.GoRedis() + // // To set a custom client: + // driver.SetClient(customGoRedisClient) + // OR: + // driver.ClientOptions = redis.Options{...} + // driver.ClusterOptions = redis.ClusterOptions{...} + // redis.New(redis.Config{Driver: driver, ...}) + defer db.Close() // close the database connection if application errored. sess := sessions.New(sessions.Config{ - Cookie: "sessionscookieid", - Expires: 45 * time.Minute, // <=0 means unlimited life. Defaults to 0. - AllowReclaim: true, - }, - ) + Cookie: "_session_id", + Expires: 0, // defaults to 0: unlimited life. Another good value is: 45 * time.Minute, + AllowReclaim: true, + CookieSecureTLS: true, + }) // // IMPORTANT: // sess.UseDatabase(db) - // the rest of the code stays the same. - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) - //set session values - s.Set("name", "iris") - - //test if setted here - ctx.Writef("All ok session value of the 'name' is: %s", s.GetString("name")) - }) - - app.Get("/set/{key}/{value}", func(ctx iris.Context) { - key, value := ctx.Params().Get("key"), ctx.Params().Get("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - - // test if setted here - ctx.Writef("All ok session value of the '%s' is: %s", key, s.GetString(key)) - }) - - app.Get("/set/int/{key}/{value}", func(ctx iris.Context) { - key := ctx.Params().Get("key") - value, _ := ctx.Params().GetInt("value") - s := sess.Start(ctx) - // set session values - s.Set(key, value) - valueSet := s.Get(key) - // test if setted here - ctx.Writef("All ok session value of the '%s' is: %v", key, valueSet) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - key := ctx.Params().Get("key") - value := sess.Start(ctx).Get(key) - - ctx.Writef("The '%s' on the /set was: %v", key, value) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString("name") - - ctx.Writef("The 'name' on the /set was: %s", name) - }) - - app.Get("/get/{key}", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - name := sess.Start(ctx).GetString(ctx.Params().Get("key")) - - ctx.Writef("The name on the /set was: %s", name) - }) + app := example.NewApp(sess) - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - sess.Start(ctx).Clear() - }) - - app.Get("/destroy", func(ctx iris.Context) { - //destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) + // TIP scaling-out Iris sessions using redis: + // $ docker-compose up + // http://localhost:8080/set/$key/$value + // The value will be available on all Iris servers as well. + // E.g. http://localhost:9090/get/$key and vice versa. + addr := fmt.Sprintf(":%s", getenv("PORT", "8080")) + app.Listen(addr) +} - app.Get("/update", func(ctx iris.Context) { - // updates expire date with a new date - sess.ShiftExpiration(ctx) - }) +func getenv(key string, def string) string { + if v := os.Getenv(strings.ToUpper(key)); v != "" { + return v + } - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + return def } diff --git a/sessions/flash-messages/main.go b/sessions/flash-messages/main.go index 55be2594..acd2a5dd 100644 --- a/sessions/flash-messages/main.go +++ b/sessions/flash-messages/main.go @@ -1,23 +1,25 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12/sessions" ) func main() { app := iris.New() - sess := sessions.New(sessions.Config{Cookie: "myappsessionid", AllowReclaim: true}) + + sess := sessions.New(sessions.Config{Cookie: "_session_id", AllowReclaim: true}) + app.Use(sess.Handler()) app.Get("/set", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) s.SetFlash("name", "iris") - ctx.Writef("Message setted, is available for the next request") + ctx.Writef("Message set, is available for the next request") }) app.Get("/get", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) name := s.GetFlashString("name") if name == "" { ctx.Writef("Empty name!!") @@ -27,7 +29,7 @@ func main() { }) app.Get("/test", func(ctx iris.Context) { - s := sess.Start(ctx) + s := sessions.Get(ctx) name := s.GetFlashString("name") if name == "" { ctx.Writef("Empty name!!") @@ -38,5 +40,5 @@ func main() { ctx.Writef(", and again from the same context: %s", name) }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/sessions/overview/example/example.go b/sessions/overview/example/example.go new file mode 100644 index 00000000..48c349c3 --- /dev/null +++ b/sessions/overview/example/example.go @@ -0,0 +1,203 @@ +package example + +import ( + "errors" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/sessions" +) + +// BusinessModel is just a Go struct value that we will use in our session example, +// never save sensitive information, like passwords, here. +type BusinessModel struct { + Name string +} + +// NewApp returns a new application for showcasing the sessions feature. +func NewApp(sess *sessions.Sessions) *iris.Application { + app := iris.New() + app.Use(sess.Handler()) // register the session manager on a group of routes or the root app. + + app.Get("/", func(ctx iris.Context) { + session := sessions.Get(ctx) // same as sess.Start(ctx, cookieOptions...) + if session.Len() == 0 { + ctx.HTML(`no session values stored yet. Navigate to: <a href="/set">set page</a>`) + return + } + + ctx.HTML("<ul>") + session.Visit(func(key string, value interface{}) { + ctx.HTML("<li> %s = %v </li>", key, value) + }) + + ctx.HTML("</ul>") + }) + + // set session values. + app.Get("/set", func(ctx iris.Context) { + session := sessions.Get(ctx) + isNew := session.IsNew() + + session.Set("username", "iris") + + ctx.Writef("All ok session set to: %s [isNew=%t]", session.GetString("username"), isNew) + }) + + app.Get("/get", func(ctx iris.Context) { + session := sessions.Get(ctx) + + // get a specific value, as string, + // if not found then it returns just an empty string. + name := session.GetString("username") + + ctx.Writef("The username on the /set was: %s", name) + }) + + app.Get("/set-struct", func(ctx iris.Context) { + session := sessions.Get(ctx) + session.Set("struct", BusinessModel{Name: "John Doe"}) + + ctx.WriteString("All ok session value of the 'struct' was set.") + }) + + app.Get("/get-struct", func(ctx iris.Context) { + session := sessions.Get(ctx) + var v BusinessModel + if err := session.Decode("struct", &v); err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + ctx.Writef("Session value of the 'struct' is: %#+v", v) + }) + + app.Get("/set/{key}/{value}", func(ctx iris.Context) { + session := sessions.Get(ctx) + + key := ctx.Params().Get("key") + value := ctx.Params().Get("value") + isNew := session.IsNew() + + session.Set(key, value) + + ctx.Writef("All ok session value of the '%s' is: %s [isNew=%t]", key, session.GetString(key), isNew) + }) + + app.Get("/get/{key}", func(ctx iris.Context) { + session := sessions.Get(ctx) + // get a specific key, as string, if no found returns just an empty string + key := ctx.Params().Get("key") + value := session.Get(key) + + ctx.Writef("The [%s:%T] on the /set was: %v", key, value, value) + }) + + app.Get("/set/{type}/{key}/{value}", func(ctx iris.Context) { + session := sessions.Get(ctx) + + key := ctx.Params().Get("key") + var value interface{} + + switch ctx.Params().Get("type") { + case "int": + value = ctx.Params().GetIntDefault("value", 0) + case "float64": + value = ctx.Params().GetFloat64Default("value", 0.0) + default: + value = ctx.Params().Get("value") + } + session.Set(key, value) + + value = session.Get(key) + ctx.Writef("Key: %s, Type: %T, Value: %v", key, value, value) + }) + + app.Get("/delete", func(ctx iris.Context) { + session := sessions.Get(ctx) + // delete a specific key + session.Delete("username") + }) + + app.Get("/clear", func(ctx iris.Context) { + session := sessions.Get(ctx) + // removes all entries. + session.Clear() + }) + + app.Get("/update", func(ctx iris.Context) { + session := sessions.Get(ctx) + // shifts the expiration based on the session's `Lifetime`. + if err := session.Man.ShiftExpiration(ctx); err != nil { + if errors.Is(err, sessions.ErrNotFound) { + ctx.StatusCode(iris.StatusNotFound) + } else if errors.Is(err, sessions.ErrNotImplemented) { + ctx.StatusCode(iris.StatusNotImplemented) + } else { + ctx.StatusCode(iris.StatusNotModified) + } + + ctx.Writef("%v", err) + ctx.Application().Logger().Error(err) + } + }) + + app.Get("/destroy", func(ctx iris.Context) { + session := sessions.Get(ctx) + // Man(anager)'s Destroy, removes the entire session data and cookie + session.Man.Destroy(ctx) + }) + + // Note about Destroy: + // + // You can destroy a session outside of a handler too, using the: + // sess.DestroyByID + // sess.DestroyAll + + // remember: slices and maps are muttable by-design + // The `SetImmutable` makes sure that they will be stored and received + // as immutable, so you can't change them directly by mistake. + // + // Use `SetImmutable` consistently, it's slower than `Set`. + // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 + app.Get("/set-immutable", func(ctx iris.Context) { + session := sessions.Get(ctx) + + business := []BusinessModel{{Name: "Edward"}, {Name: "value 2"}} + session.SetImmutable("businessEdit", business) + var businessGet []BusinessModel + err := session.Decode("businessEdit", &businessGet) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + // try to change it, if we used `Set` instead of `SetImmutable` this + // change will affect the underline array of the session's value "businessEdit", but now it will not. + businessGet[0].Name = "Gabriel" + }) + + app.Get("/get-immutable", func(ctx iris.Context) { + var models []BusinessModel + err := sessions.Get(ctx).Decode("businessEdit", &models) + if err != nil { + ctx.StopWithError(iris.StatusInternalServerError, err) + return + } + + if models == nil { + ctx.HTML("please navigate to the <a href='/set_immutable'>/set-immutable</a> first") + return + } + + firstModel := models[0] + // businessGet[0].Name is equal to Edward initially + if firstModel.Name != "Edward" { + panic("Report this as a bug, immutable data cannot be changed from the caller without re-SetImmutable") + } + + ctx.Writef("[]businessModel[0].Name remains: %s", firstModel.Name) + + // the name should remains "Edward" + }) + + return app +} diff --git a/sessions/overview/main.go b/sessions/overview/main.go index b4ee0121..d04462ae 100644 --- a/sessions/overview/main.go +++ b/sessions/overview/main.go @@ -1,51 +1,42 @@ package main import ( - "github.com/kataras/iris" + "time" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12/_examples/sessions/overview/example" + "github.com/kataras/iris/v12/sessions" ) -var ( - cookieNameForSessionID = "mycookiesessionnameid" - sess = sessions.New(sessions.Config{Cookie: cookieNameForSessionID, AllowReclaim: true}) -) - -func secret(ctx iris.Context) { - - // Check if user is authenticated - if auth, _ := sess.Start(ctx).GetBoolean("authenticated"); !auth { - ctx.StatusCode(iris.StatusForbidden) - return - } - - // Print secret message - ctx.WriteString("The cake is a lie!") -} - -func login(ctx iris.Context) { - session := sess.Start(ctx) - - // Authentication goes here - // ... - - // Set user as authenticated - session.Set("authenticated", true) -} - -func logout(ctx iris.Context) { - session := sess.Start(ctx) - - // Revoke users authentication - session.Set("authenticated", false) -} - func main() { - app := iris.New() - - app.Get("/secret", secret) - app.Get("/login", login) - app.Get("/logout", logout) - - app.Run(iris.Addr(":8080")) + sess := sessions.New(sessions.Config{ + // Cookie string, the session's client cookie name, for example: "_session_id" + // + // Defaults to "irissessionid" + Cookie: "_session_id", + // it's time.Duration, from the time cookie is created, how long it can be alive? + // 0 means no expire, unlimited life. + // -1 means expire when browser closes + // or set a value, like 2 hours: + Expires: time.Hour * 2, + // if you want to invalid cookies on different subdomains + // of the same host, then enable it. + // Defaults to false. + DisableSubdomainPersistence: false, + // Allow getting the session value stored by the request from the same request. + AllowReclaim: true, + /* + SessionIDGenerator: func(ctx iris.Context) string { + id:= ctx.GetHeader("X-Session-Id") + if id == "" { + id = // [generate ID here and set the header] + ctx.Header("X-Session-Id", id) + } + + return id + }, + */ + }) + + app := example.NewApp(sess) + app.Listen(":8080") } diff --git a/sessions/securecookie/main.go b/sessions/securecookie/main.go index f4e1730d..d33c69e0 100644 --- a/sessions/securecookie/main.go +++ b/sessions/securecookie/main.go @@ -6,81 +6,33 @@ package main // $ go run main.go import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/sessions" - "github.com/kataras/iris/sessions" + "github.com/kataras/iris/v12/_examples/sessions/overview/example" "github.com/gorilla/securecookie" ) func newApp() *iris.Application { - app := iris.New() - - cookieName := "mycustomsessionid" + cookieName := "_session_id" // AES only supports key sizes of 16, 24 or 32 bytes. // You either need to provide exactly that amount or you derive the key from what you type in. - hashKey := []byte("the-big-and-secret-fash-key-here") - blockKey := []byte("lot-secret-of-characters-big-too") - secureCookie := securecookie.New(hashKey, blockKey) - + hashKey := securecookie.GenerateRandomKey(64) + blockKey := securecookie.GenerateRandomKey(32) + s := securecookie.New(hashKey, blockKey) mySessions := sessions.New(sessions.Config{ Cookie: cookieName, - Encode: secureCookie.Encode, - Decode: secureCookie.Decode, + Encoding: s, AllowReclaim: true, }) - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - - //set session values - s := mySessions.Start(ctx) - s.Set("name", "iris") - - //test if setted here - ctx.Writef("All ok session setted to: %s", s.GetString("name")) - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific key, as string, if no found returns just an empty string - s := mySessions.Start(ctx) - name := s.GetString("name") - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - s := mySessions.Start(ctx) - s.Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries - mySessions.Start(ctx).Clear() - }) - - app.Get("/update", func(ctx iris.Context) { - // updates expire date with a new date - mySessions.ShiftExpiration(ctx) - }) - - app.Get("/destroy", func(ctx iris.Context) { - //destroy, removes the entire session data and cookie - mySessions.Destroy(ctx) - }) - // Note about destroy: - // - // You can destroy a session outside of a handler too, using the: - // mySessions.DestroyByID - // mySessions.DestroyAll + // mySessions.UseDatabase(...see sessions/database example folder) - return app + return example.NewApp(mySessions) } func main() { app := newApp() - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/sessions/securecookie/main_test.go b/sessions/securecookie/main_test.go index e9b40797..43af58db 100644 --- a/sessions/securecookie/main_test.go +++ b/sessions/securecookie/main_test.go @@ -3,8 +3,8 @@ package main import ( "testing" - "github.com/kataras/iris" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" ) func TestSessionsEncodeDecode(t *testing.T) { @@ -14,14 +14,14 @@ func TestSessionsEncodeDecode(t *testing.T) { es := e.GET("/set").Expect() es.Status(iris.StatusOK) es.Cookies().NotEmpty() - es.Body().Equal("All ok session setted to: iris") + es.Body().IsEqual("All ok session set to: iris [isNew=true]") - e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: iris") + e.GET("/get").Expect().Status(iris.StatusOK).Body().IsEqual("The username on the /set was: iris") // delete and re-get e.GET("/delete").Expect().Status(iris.StatusOK) - e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: ") + e.GET("/get").Expect().Status(iris.StatusOK).Body().IsEqual("The username on the /set was: ") // set, clear and re-get - e.GET("/set").Expect().Body().Equal("All ok session setted to: iris") + e.GET("/set").Expect().Body().IsEqual("All ok session set to: iris [isNew=false]") e.GET("/clear").Expect().Status(iris.StatusOK) - e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal("The name on the /set was: ") + e.GET("/get").Expect().Status(iris.StatusOK).Body().IsEqual("The username on the /set was: ") } diff --git a/sessions/standalone/main.go b/sessions/standalone/main.go deleted file mode 100644 index 343ac5e6..00000000 --- a/sessions/standalone/main.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/sessions" -) - -type businessModel struct { - Name string -} - -func main() { - app := iris.New() - sess := sessions.New(sessions.Config{ - // Cookie string, the session's client cookie name, for example: "mysessionid" - // - // Defaults to "irissessionid" - Cookie: "mysessionid", - // it's time.Duration, from the time cookie is created, how long it can be alive? - // 0 means no expire. - // -1 means expire when browser closes - // or set a value, like 2 hours: - Expires: time.Hour * 2, - // if you want to invalid cookies on different subdomains - // of the same host, then enable it. - // Defaults to false. - DisableSubdomainPersistence: true, - // AllowReclaim will allow to - // Destroy and Start a session in the same request handler. - // All it does is that it removes the cookie for both `Request` and `ResponseWriter` while `Destroy` - // or add a new cookie to `Request` while `Start`. - // - // Defaults to false. - AllowReclaim: true, - }) - - app.Get("/", func(ctx iris.Context) { - ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead") - }) - app.Get("/set", func(ctx iris.Context) { - //set session values. - s := sess.Start(ctx) - s.Set("name", "iris") - - //test if setted here. - ctx.Writef("All ok session setted to: %s", s.GetString("name")) - - // Set will set the value as-it-is, - // if it's a slice or map - // you will be able to change it on .Get directly! - // Keep note that I don't recommend saving big data neither slices or maps on a session - // but if you really need it then use the `SetImmutable` instead of `Set`. - // Use `SetImmutable` consistently, it's slower. - // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 - }) - - app.Get("/get", func(ctx iris.Context) { - // get a specific value, as string, - // if not found then it returns just an empty string. - name := sess.Start(ctx).GetString("name") - - ctx.Writef("The name on the /set was: %s", name) - }) - - app.Get("/delete", func(ctx iris.Context) { - // delete a specific key - sess.Start(ctx).Delete("name") - }) - - app.Get("/clear", func(ctx iris.Context) { - // removes all entries. - sess.Start(ctx).Clear() - }) - - app.Get("/update", func(ctx iris.Context) { - // updates expire date. - sess.ShiftExpiration(ctx) - }) - - app.Get("/destroy", func(ctx iris.Context) { - //destroy, removes the entire session data and cookie - sess.Destroy(ctx) - }) - // Note about Destroy: - // - // You can destroy a session outside of a handler too, using the: - // mySessions.DestroyByID - // mySessions.DestroyAll - - // remember: slices and maps are muttable by-design - // The `SetImmutable` makes sure that they will be stored and received - // as immutable, so you can't change them directly by mistake. - // - // Use `SetImmutable` consistently, it's slower than `Set`. - // Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081 - app.Get("/set_immutable", func(ctx iris.Context) { - business := []businessModel{{Name: "Edward"}, {Name: "value 2"}} - s := sess.Start(ctx) - s.SetImmutable("businessEdit", business) - businessGet := s.Get("businessEdit").([]businessModel) - - // try to change it, if we used `Set` instead of `SetImmutable` this - // change will affect the underline array of the session's value "businessEdit", but now it will not. - businessGet[0].Name = "Gabriel" - - }) - - app.Get("/get_immutable", func(ctx iris.Context) { - valSlice := sess.Start(ctx).Get("businessEdit") - if valSlice == nil { - ctx.HTML("please navigate to the <a href='/set_immutable'>/set_immutable</a> first") - return - } - - firstModel := valSlice.([]businessModel)[0] - // businessGet[0].Name is equal to Edward initially - if firstModel.Name != "Edward" { - panic("Report this as a bug, immutable data cannot be changed from the caller without re-SetImmutable") - } - - ctx.Writef("[]businessModel[0].Name remains: %s", firstModel.Name) - - // the name should remains "Edward" - }) - - app.Run(iris.Addr(":8080")) -} diff --git a/sessions/viewdata/main.go b/sessions/viewdata/main.go new file mode 100644 index 00000000..e20424b0 --- /dev/null +++ b/sessions/viewdata/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/sessions" +) + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + + sess := sessions.New(sessions.Config{Cookie: "session_cookie", AllowReclaim: true}) + app.Use(sess.Handler()) + // ^ use app.UseRouter instead to access sessions on HTTP errors too. + + // Register our custom middleware, after the sessions middleware. + app.Use(setSessionViewData) + + app.Get("/", index) + app.Listen(":8080") +} + +func setSessionViewData(ctx iris.Context) { + session := sessions.Get(ctx) + ctx.ViewData("session", session) + ctx.Next() +} + +func index(ctx iris.Context) { + session := sessions.Get(ctx) + session.Set("username", "kataras") + if err := ctx.View("index"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + /* OR without middleware: + if err := ctx.View("index", iris.Map{ + "session": session, + // {{.session.Get "username"}} + // OR to pass only the 'username': + // "username": session.Get("username"), + // {{.username}} + }) + */ +} diff --git a/sessions/viewdata/views/index.html b/sessions/viewdata/views/index.html new file mode 100644 index 00000000..f93e5a38 --- /dev/null +++ b/sessions/viewdata/views/index.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Sessions View Data</title> +</head> +<body> + Hello {{.session.Get "username"}} +</body> +</html> \ No newline at end of file diff --git a/structuring/bootstrap/routes/routes.go b/structuring/bootstrap/routes/routes.go deleted file mode 100644 index 37f82edb..00000000 --- a/structuring/bootstrap/routes/routes.go +++ /dev/null @@ -1,13 +0,0 @@ -package routes - -import ( - "github.com/iris-contrib/examples/structuring/bootstrap/bootstrap" -) - -// Configure registers the necessary routes to the app. -func Configure(b *bootstrap.Bootstrapper) { - b.Get("/", GetIndexHandler) - b.Get("/follower/{id:long}", GetFollowerHandler) - b.Get("/following/{id:long}", GetFollowingHandler) - b.Get("/like/{id:long}", GetLikeHandler) -} diff --git a/structuring/login-mvc-single-responsibility-package/main.go b/structuring/login-mvc-single-responsibility-package/main.go deleted file mode 100644 index 6a071ff0..00000000 --- a/structuring/login-mvc-single-responsibility-package/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "time" - - "github.com/iris-contrib/examples/structuring/login-mvc-single-responsibility-package/user" - - "github.com/kataras/iris" - "github.com/kataras/iris/mvc" - "github.com/kataras/iris/sessions" -) - -func main() { - app := iris.New() - // You got full debug messages, useful when using MVC and you want to make - // sure that your code is aligned with the Iris' MVC Architecture. - app.Logger().SetLevel("debug") - - app.RegisterView(iris.HTML("./views", ".html").Layout("shared/layout.html")) - - app.StaticWeb("/public", "./public") - - mvc.Configure(app, configureMVC) - - // http://localhost:8080/user/register - // http://localhost:8080/user/login - // http://localhost:8080/user/me - // http://localhost:8080/user/logout - // http://localhost:8080/user/1 - app.Run(iris.Addr(":8080"), configure) -} - -func configureMVC(app *mvc.Application) { - manager := sessions.New(sessions.Config{ - Cookie: "sessioncookiename", - Expires: 24 * time.Hour, - }) - - userApp := app.Party("/user") - userApp.Register( - user.NewDataSource(), - manager.Start, - ) - userApp.Handle(new(user.Controller)) -} - -func configure(app *iris.Application) { - app.Configure( - iris.WithoutServerError(iris.ErrServerClosed), - ) -} diff --git a/structuring/login-mvc/README.md b/structuring/login-mvc/README.md deleted file mode 100644 index c6cbf0a5..00000000 --- a/structuring/login-mvc/README.md +++ /dev/null @@ -1 +0,0 @@ -# Please navigate to the [_examples/mvc/login](https://github.com/kataras/iris/tree/master/_examples/mvc/login) \ No newline at end of file diff --git a/structuring/mvc-plus-repository-and-service-layers/README.md b/structuring/mvc-plus-repository-and-service-layers/README.md deleted file mode 100644 index 692e63c6..00000000 --- a/structuring/mvc-plus-repository-and-service-layers/README.md +++ /dev/null @@ -1 +0,0 @@ -# Please navigate to the [_examples/mvc/overview](https://github.com/kataras/iris/tree/master/_examples/mvc/overview) \ No newline at end of file diff --git a/subdomains/redirect/main.go b/subdomains/redirect/main.go deleted file mode 100644 index 87ec7a66..00000000 --- a/subdomains/redirect/main.go +++ /dev/null @@ -1,73 +0,0 @@ -// Package main shows how to register a simple 'www' subdomain, -// using the `app.WWW` method, which will register a router wrapper which will -// redirect all 'mydomain.com' requests to 'www.mydomain.com'. -// Check the 'hosts' file to see how to test the 'mydomain.com' on your local machine. -package main - -import "github.com/kataras/iris" - -const addr = "mydomain.com:80" - -func main() { - app := newApp() - - // http(s)://mydomain.com, will be redirect to http(s)://www.mydomain.com. - // The `www` variable is the `app.Subdomain("www")`. - // - // app.WWW() wraps the router so it can redirect all incoming requests - // that comes from 'http(s)://mydomain.com/%path%' (www is missing) - // to `http(s)://www.mydomain.com/%path%`. - // - // Try: - // http://mydomain.com -> http://www.mydomain.com - // http://mydomain.com/users -> http://www.mydomain.com/users - // http://mydomain.com/users/login -> http://www.mydomain.com/users/login - app.Run(iris.Addr(addr)) -} - -func newApp() *iris.Application { - app := iris.New() - app.Get("/", func(ctx iris.Context) { - ctx.Writef("This will never be executed.") - }) - - www := app.Subdomain("www") // <- same as app.Party("www.") - www.Get("/", index) - - // www is an `iris.Party`, use it like you already know, like grouping routes. - www.PartyFunc("/users", func(p iris.Party) { // <- same as www.Party("/users").Get(...) - p.Get("/", usersIndex) - p.Get("/login", getLogin) - }) - - // redirects mydomain.com/%anypath% to www.mydomain.com/%anypath%. - // First argument is the 'from' and second is the 'to/target'. - app.SubdomainRedirect(app, www) - - // SubdomainRedirect works for multi-level subdomains as well: - // subsub := www.Subdomain("subsub") // subsub.www.mydomain.com - // subsub.Get("/", func(ctx iris.Context) { ctx.Writef("subdomain is: " + ctx.Subdomain()) }) - // app.SubdomainRedirect(subsub, www) - // - // If you need to redirect any subdomain to 'www' then: - // app.SubdomainRedirect(app.WildcardSubdomain(), www) - // If you need to redirect from a subdomain to the root domain then: - // app.SubdomainRedirect(app.Subdomain("mysubdomain"), app) - // - // Note that app.Party("mysubdomain.") and app.Subdomain("mysubdomain") - // is the same exactly thing, the difference is that the second can omit the last dot('.'). - - return app -} - -func index(ctx iris.Context) { - ctx.Writef("This is the www.mydomain.com endpoint.") -} - -func usersIndex(ctx iris.Context) { - ctx.Writef("This is the www.mydomain.com/users endpoint.") -} - -func getLogin(ctx iris.Context) { - ctx.Writef("This is the www.mydomain.com/users/login endpoint.") -} diff --git a/subdomains/redirect/main_test.go b/subdomains/redirect/main_test.go deleted file mode 100644 index 4f2a62cf..00000000 --- a/subdomains/redirect/main_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "fmt" - "strings" - "testing" - - "github.com/kataras/iris/httptest" -) - -func TestSubdomainRedirectWWW(t *testing.T) { - app := newApp() - root := strings.TrimSuffix(addr, ":80") - - e := httptest.New(t, app) - - tests := []struct { - path string - response string - }{ - {"/", fmt.Sprintf("This is the www.%s endpoint.", root)}, - {"/users", fmt.Sprintf("This is the www.%s/users endpoint.", root)}, - {"/users/login", fmt.Sprintf("This is the www.%s/users/login endpoint.", root)}, - } - - for _, test := range tests { - e.GET(test.path).Expect().Status(httptest.StatusOK).Body().Equal(test.response) - } - -} diff --git a/testing/ginkgotest/ginkgotest_suite_test.go b/testing/ginkgotest/ginkgotest_suite_test.go new file mode 100644 index 00000000..d921fae2 --- /dev/null +++ b/testing/ginkgotest/ginkgotest_suite_test.go @@ -0,0 +1,49 @@ +package main_test + +import ( + "github.com/kataras/iris/v12" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestGinkgotest(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Ginkgotest Suite") +} + +func newApp(authentication iris.Handler) *iris.Application { + app := iris.New() + + app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") }) + + // to party + + needAuth := app.Party("/admin", authentication) + { + //http://localhost:8080/admin + needAuth.Get("/", h) + // http://localhost:8080/admin/profile + needAuth.Get("/profile", h) + + // http://localhost:8080/admin/settings + needAuth.Get("/settings", h) + } + + return app +} +func h(ctx iris.Context) { + username, password, _ := ctx.Request().BasicAuth() + // third parameter it will be always true because the middleware + // makes sure for that, otherwise this handler will not be executed. + // OR: + // + // user := ctx.User().(*myUserType) + // ctx.Writef("%s %s:%s", ctx.Path(), user.Username, user.Password) + // OR if you don't have registered custom User structs: + // + // ctx.User().GetUsername() + // ctx.User().GetPassword() + ctx.Writef("%s %s:%s", ctx.Path(), username, password) +} diff --git a/testing/ginkgotest/go.mod b/testing/ginkgotest/go.mod new file mode 100644 index 00000000..f19ad790 --- /dev/null +++ b/testing/ginkgotest/go.mod @@ -0,0 +1,82 @@ +module ginkgotest + +go 1.22 + +require ( + github.com/kataras/iris/v12 v12.2.11 + github.com/onsi/ginkgo/v2 v2.11.0 + github.com/onsi/gomega v1.27.10 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/ajg/form v1.5.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/imkira/go-interpol v1.1.0 // indirect + github.com/iris-contrib/httpexpect/v2 v2.15.2 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sanity-io/litter v1.5.5 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sergi/go-diff v1.0.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.20.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + moul.io/http2curl/v2 v2.3.0 // indirect +) diff --git a/testing/ginkgotest/go.sum b/testing/ginkgotest/go.sum new file mode 100644 index 00000000..21886235 --- /dev/null +++ b/testing/ginkgotest/go.sum @@ -0,0 +1,230 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/authentication/basicauth/main.go b/testing/ginkgotest/main.go similarity index 55% rename from authentication/basicauth/main.go rename to testing/ginkgotest/main.go index 8a7caadb..35dcf78c 100644 --- a/authentication/basicauth/main.go +++ b/testing/ginkgotest/main.go @@ -1,28 +1,18 @@ package main import ( - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/basicauth" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" ) func newApp() *iris.Application { app := iris.New() - authConfig := basicauth.Config{ - Users: map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"}, - Realm: "Authorization Required", // defaults to "Authorization Required" - Expires: time.Duration(30) * time.Minute, + opts := basicauth.Options{ + Allow: basicauth.AllowUsers(map[string]string{"myusername": "mypassword"}), } - authentication := basicauth.New(authConfig) - - // to global app.Use(authentication) (or app.UseGlobal before the .Run) - // to routes - /* - app.Get("/mysecret", authentication, h) - */ + authentication := basicauth.New(opts) // or just: basicauth.Default(map...) app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") }) @@ -42,16 +32,22 @@ func newApp() *iris.Application { return app } -func main() { - app := newApp() - // open http://localhost:8080/admin - app.Run(iris.Addr(":8080")) -} - func h(ctx iris.Context) { username, password, _ := ctx.Request().BasicAuth() // third parameter it will be always true because the middleware // makes sure for that, otherwise this handler will not be executed. - + // OR: + // + // user := ctx.User().(*myUserType) + // ctx.Writef("%s %s:%s", ctx.Path(), user.Username, user.Password) + // OR if you don't have registered custom User structs: + // + // ctx.User().GetUsername() + // ctx.User().GetPassword() ctx.Writef("%s %s:%s", ctx.Path(), username, password) } + +func main() { + app := newApp() + app.Listen(":8080") +} diff --git a/testing/ginkgotest/main_test.go b/testing/ginkgotest/main_test.go new file mode 100644 index 00000000..ca725b60 --- /dev/null +++ b/testing/ginkgotest/main_test.go @@ -0,0 +1,65 @@ +package main_test + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" + "github.com/kataras/iris/v12/middleware/basicauth" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Ginkgotest", func() { + var ( + e *httptest.Expect + app *iris.Application + opts basicauth.Options + authentication iris.Handler // or just: basicauth.Default(map...) + ) + + BeforeEach(func() { + opts = basicauth.Options{ + Allow: basicauth.AllowUsers(map[string]string{"myusername": "mypassword"}), + } + authentication = basicauth.New(opts) + app = newApp(authentication) + e = httptest.New(GinkgoT(), app, httptest.Strict(true)) + }) + + When("no basic auth", Ordered, func() { + It("redirects to /admin without basic auth", func() { + response := e.GET("/").Expect().Raw() + Expect(httptest.StatusUnauthorized).To(Equal(response.StatusCode)) + }) + It("without basic auth", func() { + // without basic auth + response := e.GET("/").Expect().Raw() + Expect(httptest.StatusUnauthorized).To(Equal(response.StatusCode)) + }) + + }) + + When("valid basic auth", func() { + It("with basic auth /admin", func() { + expect := e.GET("/admin").WithBasicAuth("myusername", "mypassword").Expect() + Expect(httptest.StatusOK).To(Equal(expect.Raw().StatusCode)) + Expect("/admin myusername:mypassword").To(Equal(expect.Body().Raw())) + }) + It("with basic auth /admin/profile", func() { + expect := e.GET("/admin/profile").WithBasicAuth("myusername", "mypassword").Expect() + Expect(httptest.StatusOK).To(Equal(expect.Raw().StatusCode)) + Expect("/admin/profile myusername:mypassword").To(Equal(expect.Body().Raw())) + }) + It("with basic auth /admin/profile", func() { + expect := e.GET("/admin/settings").WithBasicAuth("myusername", "mypassword").Expect() + Expect(httptest.StatusOK).To(Equal(expect.Raw().StatusCode)) + Expect("/admin/settings myusername:mypassword").To(Equal(expect.Body().Raw())) + }) + }) + + When("invalid basic auth", func() { + It("invalid basic auth /admin/settings", func() { + expect := e.GET("/admin/settings").WithBasicAuth("invalidusername", "invalidpassword").Expect() + Expect(httptest.StatusUnauthorized).To(Equal(expect.Raw().StatusCode)) + }) + }) +}) diff --git a/testing/httptest/main.go b/testing/httptest/main.go index 8aa1b020..35dcf78c 100644 --- a/testing/httptest/main.go +++ b/testing/httptest/main.go @@ -1,18 +1,18 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/middleware/basicauth" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/middleware/basicauth" ) func newApp() *iris.Application { app := iris.New() - authConfig := basicauth.Config{ - Users: map[string]string{"myusername": "mypassword"}, + opts := basicauth.Options{ + Allow: basicauth.AllowUsers(map[string]string{"myusername": "mypassword"}), } - authentication := basicauth.New(authConfig) + authentication := basicauth.New(opts) // or just: basicauth.Default(map...) app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") }) @@ -36,11 +36,18 @@ func h(ctx iris.Context) { username, password, _ := ctx.Request().BasicAuth() // third parameter it will be always true because the middleware // makes sure for that, otherwise this handler will not be executed. - + // OR: + // + // user := ctx.User().(*myUserType) + // ctx.Writef("%s %s:%s", ctx.Path(), user.Username, user.Password) + // OR if you don't have registered custom User structs: + // + // ctx.User().GetUsername() + // ctx.User().GetPassword() ctx.Writef("%s %s:%s", ctx.Path(), username, password) } func main() { app := newApp() - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/testing/httptest/main_test.go b/testing/httptest/main_test.go index 492826b3..bc39a0dd 100644 --- a/testing/httptest/main_test.go +++ b/testing/httptest/main_test.go @@ -3,13 +3,14 @@ package main import ( "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/httptest" ) // $ go test -v func TestNewApp(t *testing.T) { app := newApp() - e := httptest.New(t, app) + e := httptest.New(t, app, httptest.Strict(true)) // redirects to /admin without basic auth e.GET("/").Expect().Status(httptest.StatusUnauthorized) @@ -18,14 +19,28 @@ func TestNewApp(t *testing.T) { // with valid basic auth e.GET("/admin").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin myusername:mypassword") e.GET("/admin/profile").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin/profile myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin/profile myusername:mypassword") e.GET("/admin/settings").WithBasicAuth("myusername", "mypassword").Expect(). - Status(httptest.StatusOK).Body().Equal("/admin/settings myusername:mypassword") + Status(httptest.StatusOK).Body().IsEqual("/admin/settings myusername:mypassword") // with invalid basic auth e.GET("/admin/settings").WithBasicAuth("invalidusername", "invalidpassword"). Expect().Status(httptest.StatusUnauthorized) +} + +func TestHandlerUsingNetHTTP(t *testing.T) { + handler := func(ctx iris.Context) { + ctx.WriteString("Hello, World!") + } + + // A shortcut for net/http/httptest.NewRecorder/NewRequest. + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + httptest.Do(w, r, handler) + if expected, got := "Hello, World!", w.Body.String(); expected != got { + t.Fatalf("expected body: %s but got: %s", expected, got) + } } diff --git a/tutorial/online-visitors/main.go b/tutorial/online-visitors/main.go deleted file mode 100644 index e6f3fa11..00000000 --- a/tutorial/online-visitors/main.go +++ /dev/null @@ -1,161 +0,0 @@ -package main - -import ( - "sync/atomic" - - "github.com/kataras/iris" - - "github.com/kataras/iris/websocket" -) - -func main() { - // init the web application instance - // app := iris.New() - app := iris.Default() - - // load templates - app.RegisterView(iris.HTML("./templates", ".html").Reload(true)) - // setup the websocket server - ws := websocket.New(websocket.Config{}) - ws.OnConnection(HandleWebsocketConnection) - - app.Get("/my_endpoint", ws.Handler()) - app.Any("/iris-ws.js", websocket.ClientHandler()) - - // register static assets request path and system directory - app.StaticWeb("/js", "./static/assets/js") - - h := func(ctx iris.Context) { - ctx.ViewData("", page{PageID: "index page"}) - ctx.View("index.html") - } - - h2 := func(ctx iris.Context) { - ctx.ViewData("", page{PageID: "other page"}) - ctx.View("other.html") - } - - // Open some browser tabs/or windows - // and navigate to - // http://localhost:8080/ and http://localhost:8080/other multiple times. - // Each page has its own online-visitors counter. - app.Get("/", h) - app.Get("/other", h2) - app.Run(iris.Addr(":8080")) -} - -type page struct { - PageID string -} - -type pageView struct { - source string - count uint64 -} - -func (v *pageView) increment() { - atomic.AddUint64(&v.count, 1) -} - -func (v *pageView) decrement() { - atomic.AddUint64(&v.count, ^uint64(0)) -} - -func (v *pageView) getCount() uint64 { - return atomic.LoadUint64(&v.count) -} - -type ( - pageViews []pageView -) - -func (v *pageViews) Add(source string) { - args := *v - n := len(args) - for i := 0; i < n; i++ { - kv := &args[i] - if kv.source == source { - kv.increment() - return - } - } - - c := cap(args) - if c > n { - args = args[:n+1] - kv := &args[n] - kv.source = source - kv.count = 1 - *v = args - return - } - - kv := pageView{} - kv.source = source - kv.count = 1 - *v = append(args, kv) -} - -func (v *pageViews) Get(source string) *pageView { - args := *v - n := len(args) - for i := 0; i < n; i++ { - kv := &args[i] - if kv.source == source { - return kv - } - } - return nil -} - -func (v *pageViews) Reset() { - *v = (*v)[:0] -} - -var v pageViews - -// HandleWebsocketConnection handles the online viewers per example(gist source) -func HandleWebsocketConnection(c websocket.Connection) { - - c.On("watch", func(pageSource string) { - v.Add(pageSource) - // join the socket to a room linked with the page source - c.Join(pageSource) - - viewsCount := v.Get(pageSource).getCount() - if viewsCount == 0 { - viewsCount++ // count should be always > 0 here - } - c.To(pageSource).Emit("watch", viewsCount) - }) - - c.OnLeave(func(roomName string) { - if roomName != c.ID() { // if the roomName it's not the connection iself - // the roomName here is the source, this is the only room(except the connection's ID room) which we join the users to. - pageV := v.Get(roomName) - if pageV == nil { - return // for any case that this room is not a pageView source - } - // decrement -1 the specific counter for this page source. - pageV.decrement() - // 1. open 30 tabs. - // 2. close the browser. - // 3. re-open the browser - // 4. should be v.getCount() = 1 - // in order to achieve the previous flow we should decrement exactly when the user disconnects - // but emit the result a little after, on a goroutine - // getting all connections within this room and emit the online views one by one. - // note: - // we can also add a time.Sleep(2-3 seconds) inside the goroutine at the future if we don't need 'real-time' updates. - go func(currentConnID string) { - for _, conn := range c.Server().GetConnectionsByRoom(roomName) { - if conn.ID() != currentConnID { - conn.Emit("watch", pageV.getCount()) - } - - } - }(c.ID()) - } - - }) -} diff --git a/tutorial/online-visitors/static/assets/js/visitors.js b/tutorial/online-visitors/static/assets/js/visitors.js deleted file mode 100644 index bfc0a9a0..00000000 --- a/tutorial/online-visitors/static/assets/js/visitors.js +++ /dev/null @@ -1,21 +0,0 @@ -(function() { - var socket = new Ws("ws://localhost:8080/my_endpoint"); - - socket.OnConnect(function () { - socket.Emit("watch", PAGE_SOURCE); - }); - - - socket.On("watch", function (onlineViews) { - var text = "1 online view"; - if (onlineViews > 1) { - text = onlineViews + " online views"; - } - document.getElementById("online_views").innerHTML = text; - }); - - socket.OnDisconnect(function () { - document.getElementById("online_views").innerHTML = "you've been disconnected"; - }); - -})(); diff --git a/tutorial/vuejs-todo-mvc/src/web/main.go b/tutorial/vuejs-todo-mvc/src/web/main.go deleted file mode 100644 index 85ab0959..00000000 --- a/tutorial/vuejs-todo-mvc/src/web/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "github.com/iris-contrib/examples/tutorial/vuejs-todo-mvc/src/todo" - "github.com/iris-contrib/examples/tutorial/vuejs-todo-mvc/src/web/controllers" - - "github.com/kataras/iris" - "github.com/kataras/iris/sessions" - "github.com/kataras/iris/websocket" - - "github.com/kataras/iris/mvc" -) - -func main() { - app := iris.New() - - // serve our app in public, public folder - // contains the client-side vue.js application, - // no need for any server-side template here, - // actually if you're going to just use vue without any - // back-end services, you can just stop afer this line and start the server. - app.StaticWeb("/", "./public") - - // configure the http sessions. - sess := sessions.New(sessions.Config{ - Cookie: "iris_session", - }) - - // configure the websocket server. - ws := websocket.New(websocket.Config{}) - - // create a sub router and register the client-side library for the iris websockets, - // you could skip it but iris websockets supports socket.io-like API. - todosRouter := app.Party("/todos") - // http://localhost:8080/todos/iris-ws.js - // serve the javascript client library to communicate with - // the iris high level websocket event system. - todosRouter.Any("/iris-ws.js", websocket.ClientHandler()) - - // create our mvc application targeted to /todos relative sub path. - todosApp := mvc.New(todosRouter) - - // any dependencies bindings here... - todosApp.Register( - todo.NewMemoryService(), - sess.Start, - ws.Upgrade, - ) - - // controllers registration here... - todosApp.Handle(new(controllers.TodoController)) - - // start the web server at http://localhost:8080 - app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker) -} diff --git a/tutorial/vuejs-todo-mvc/src/web/public/js/lib/vue b/tutorial/vuejs-todo-mvc/src/web/public/js/lib/vue deleted file mode 100644 index 8da03f48..00000000 --- a/tutorial/vuejs-todo-mvc/src/web/public/js/lib/vue +++ /dev/null @@ -1,2 +0,0 @@ -vue.js is not here to reduce the disk space for the examples. -Instead https://vuejs.org/js/vue.js is used instead. \ No newline at end of file diff --git a/url-shortener/README.md b/url-shortener/README.md new file mode 100644 index 00000000..842caed1 --- /dev/null +++ b/url-shortener/README.md @@ -0,0 +1,3 @@ +## A URL Shortener Service using Go, Iris and Bolt + +Hackernoon Article: https://medium.com/hackernoon/a-url-shortener-service-using-go-iris-and-bolt-4182f0b00ae7 \ No newline at end of file diff --git a/tutorial/url-shortener/factory.go b/url-shortener/factory.go similarity index 95% rename from tutorial/url-shortener/factory.go rename to url-shortener/factory.go index 9df9ae95..d3e71952 100644 --- a/tutorial/url-shortener/factory.go +++ b/url-shortener/factory.go @@ -3,7 +3,7 @@ package main import ( "net/url" - "github.com/satori/go.uuid" + "github.com/google/uuid" ) // Generator the type to generate keys(short urls) @@ -11,7 +11,7 @@ type Generator func() string // DefaultGenerator is the defautl url generator var DefaultGenerator = func() string { - id, _ := uuid.NewV4() + id, _ := uuid.NewRandom() return id.String() } diff --git a/tutorial/url-shortener/main.go b/url-shortener/main.go similarity index 86% rename from tutorial/url-shortener/main.go rename to url-shortener/main.go index 1516627c..ac10db8d 100644 --- a/tutorial/url-shortener/main.go +++ b/url-shortener/main.go @@ -2,17 +2,17 @@ // // Article: https://medium.com/@kataras/a-url-shortener-service-using-go-iris-and-bolt-4182f0b00ae7 // -// $ go get github.com/coreos/bbolt -// $ go get github.com/satori/go.uuid -// $ cd $GOPATH/src/github.com/kataras/iris/_examples/tutorial/url-shortener -// $ go build +// $ go get go.etcd.io/bbolt/... +// $ go get github.com/google/uuid +// $ cd $GOPATH/src/github.com/kataras/iris/_examples/url-shortener +// $ go build -mod=mod // $ ./url-shortener package main import ( "html/template" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -24,7 +24,7 @@ func main() { // release the "db" connection when server goes off. iris.RegisterOnInterrupt(db.Close) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func newApp(db *DB) *iris.Application { @@ -40,20 +40,20 @@ func newApp(db *DB) *iris.Application { // // Look ./templates/index.html#L16 tmpl.AddFunc("IsPositive", func(n int) bool { - if n > 0 { - return true - } - return false + return n > 0 }) app.RegisterView(tmpl) // Serve static files (css) - app.StaticWeb("/static", "./resources") + app.HandleDir("/static", iris.Dir("./resources")) indexHandler := func(ctx iris.Context) { ctx.ViewData("URL_COUNT", db.Len()) - ctx.View("index.html") + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } app.Get("/", indexHandler) @@ -72,7 +72,7 @@ func newApp(db *DB) *iris.Application { return } - ctx.Redirect(value, iris.StatusTemporaryRedirect) + ctx.Redirect(value, iris.StatusBadGateway) } app.Get("/u/{shortkey}", func(ctx iris.Context) { execShortURL(ctx, ctx.Params().Get("shortkey")) @@ -99,7 +99,6 @@ func newApp(db *DB) *iris.Application { ctx.ViewData("FORM_RESULT", template.HTML("<pre><a target='_new' href='"+shortenURL+"'>"+shortenURL+" </a></pre>")) } - } } diff --git a/tutorial/url-shortener/main_test.go b/url-shortener/main_test.go similarity index 91% rename from tutorial/url-shortener/main_test.go rename to url-shortener/main_test.go index fa8002d5..1c6d38a1 100644 --- a/tutorial/url-shortener/main_test.go +++ b/url-shortener/main_test.go @@ -1,12 +1,11 @@ package main import ( - "io/ioutil" "os" "testing" "time" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) // TestURLShortener tests the simple tasks of our url shortener application. @@ -14,7 +13,7 @@ import ( // The rest possible checks is up to you, take it as as an exercise! func TestURLShortener(t *testing.T) { // temp db file - f, err := ioutil.TempFile("", "shortener") + f, err := os.CreateTemp("", "shortener") if err != nil { t.Fatalf("creating temp file for database failed: %v", err) } @@ -37,7 +36,7 @@ func TestURLShortener(t *testing.T) { // get e.GET("/u/" + keys[0]).Expect(). - Status(httptest.StatusTemporaryRedirect).Header("Location").Equal(originalURL) + Status(httptest.StatusBadGateway).Header("Location").Equal(originalURL) // save the same again, it should add a new key e.POST("/shorten"). @@ -73,5 +72,4 @@ func TestURLShortener(t *testing.T) { } time.Sleep(1 * time.Second) - } diff --git a/tutorial/url-shortener/resources/css/style.css b/url-shortener/resources/css/style.css similarity index 100% rename from tutorial/url-shortener/resources/css/style.css rename to url-shortener/resources/css/style.css diff --git a/tutorial/url-shortener/store.go b/url-shortener/store.go similarity index 97% rename from tutorial/url-shortener/store.go rename to url-shortener/store.go index 32238b09..7da5d11e 100644 --- a/tutorial/url-shortener/store.go +++ b/url-shortener/store.go @@ -3,7 +3,7 @@ package main import ( "bytes" - "github.com/coreos/bbolt" + bolt "go.etcd.io/bbolt" ) // Panic panics, change it if you don't want to panic on critical INITIALIZE-ONLY-ERRORS @@ -20,9 +20,7 @@ type Store interface { Close() // release the store or ignore } -var ( - tableURLs = []byte("urls") -) +var tableURLs = []byte("urls") // DB representation of a Store. // Only one table/bucket which contains the urls, so it's not a fully Database, @@ -44,7 +42,7 @@ func openDatabase(stumb string) *bolt.DB { } // create the buckets here - var tables = [...][]byte{ + tables := [...][]byte{ tableURLs, } @@ -160,7 +158,6 @@ func (d *DB) GetByValue(value string) (keys []string) { // Len returns all the "shorted" urls length func (d *DB) Len() (num int) { d.db.View(func(tx *bolt.Tx) error { - // Assume bucket exists and has keys b := tx.Bucket(tableURLs) if b == nil { diff --git a/tutorial/url-shortener/templates/index.html b/url-shortener/templates/index.html similarity index 100% rename from tutorial/url-shortener/templates/index.html rename to url-shortener/templates/index.html diff --git a/view/context-view-data/main.go b/view/context-view-data/main.go index 732a1a3c..01e3ed88 100644 --- a/view/context-view-data/main.go +++ b/view/context-view-data/main.go @@ -3,7 +3,7 @@ package main import ( "time" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) const ( @@ -29,7 +29,7 @@ func main() { }) app.Get("/", func(ctx iris.Context) { - ctx.ViewData("BodyMessage", "a sample text here... setted by the route handler") + ctx.ViewData("BodyMessage", "a sample text here... set by the route handler") if err := ctx.View("index.html"); err != nil { ctx.Application().Logger().Infof(err.Error()) } @@ -37,7 +37,7 @@ func main() { app.Get("/about", func(ctx iris.Context) { ctx.ViewData("Title", "My About Page") - ctx.ViewData("BodyMessage", "about text here... setted by the route handler") + ctx.ViewData("BodyMessage", "about text here... set by the route handler") // same file, just to keep things simple. if err := ctx.View("index.html"); err != nil { @@ -47,7 +47,7 @@ func main() { // http://localhost:8080 // http://localhost:8080/about - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } // Notes: ViewData("", myCustomStruct{}) will set this myCustomStruct value as a root binding data, diff --git a/view/context-view-data/templates/layouts/layout.html b/view/context-view-data/templates/layouts/layout.html index 37c5343f..b991f95d 100644 --- a/view/context-view-data/templates/layouts/layout.html +++ b/view/context-view-data/templates/layouts/layout.html @@ -5,6 +5,6 @@ </head> <body> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/context-view-engine/main.go b/view/context-view-engine/main.go new file mode 100644 index 00000000..22ee15ef --- /dev/null +++ b/view/context-view-engine/main.go @@ -0,0 +1,74 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + // Register a root view engine, as usual, + // will be used to render files through Context.View method + // when no Party or Handler-specific view engine is available. + app.RegisterView(iris.Blocks("./views/public", ".html")) + + // http://localhost:8080 + app.Get("/", index) + + // Register a view engine per group of routes. + adminGroup := app.Party("/admin") + adminGroup.RegisterView(iris.Blocks("./views/admin", ".html")) + + // http://localhost:8080/admin + adminGroup.Get("/", admin) + + // Register a view engine on-fly for the current chain of handlers. + views := iris.Blocks("./views/on-fly", ".html") + if err := views.Load(); err != nil { + app.Logger().Fatal(err) + } + + // http://localhost:8080/on-fly + app.Get("/on-fly", setViews(views), onFly) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Public Index Title", + } + + ctx.ViewLayout("main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func admin(ctx iris.Context) { + data := iris.Map{ + "Title": "Admin Panel", + } + + ctx.ViewLayout("main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func setViews(views iris.ViewEngine) iris.Handler { + return func(ctx iris.Context) { + ctx.ViewEngine(views) + ctx.Next() + } +} + +func onFly(ctx iris.Context) { + data := iris.Map{ + "Message": "View engine changed through 'setViews' custom middleware.", + } + + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/context-view-engine/views/admin/index.html b/view/context-view-engine/views/admin/index.html new file mode 100644 index 00000000..f537f535 --- /dev/null +++ b/view/context-view-engine/views/admin/index.html @@ -0,0 +1,3 @@ +{{ define "content" }} +<h1>Hello, Admin!</h1> +{{ end }} \ No newline at end of file diff --git a/view/context-view-engine/views/admin/layouts/main.html b/view/context-view-engine/views/admin/layouts/main.html new file mode 100644 index 00000000..b4b52356 --- /dev/null +++ b/view/context-view-engine/views/admin/layouts/main.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{ .Title }}</title> +</head> +<body> + {{ template "content" .}} + + + <h4>Copyright © 2022 Admin</h4> +</body> +</html> \ No newline at end of file diff --git a/view/context-view-engine/views/on-fly/index.html b/view/context-view-engine/views/on-fly/index.html new file mode 100644 index 00000000..4b3fd536 --- /dev/null +++ b/view/context-view-engine/views/on-fly/index.html @@ -0,0 +1,2 @@ +<h1>On-fly</h1> +<h3>{{.Message}}</h3> \ No newline at end of file diff --git a/view/context-view-engine/views/public/500.html b/view/context-view-engine/views/public/500.html new file mode 100644 index 00000000..37c58b58 --- /dev/null +++ b/view/context-view-engine/views/public/500.html @@ -0,0 +1,12 @@ +<!-- You can define more than one block. +The default one is "content" which should be the main template's body. +So, even if it's missing (see index.html), it's added automatically by the view engine. +When you need to define more than one block, you have to be more specific: +--> +{{ define "content" }} +<h1>Internal Server Error</h1> +{{ end }} + +{{ define "message" }} +<p style="color:red;">{{.Message}}</p> +{{ end }} \ No newline at end of file diff --git a/view/context-view-engine/views/public/index.html b/view/context-view-engine/views/public/index.html new file mode 100644 index 00000000..b11758cf --- /dev/null +++ b/view/context-view-engine/views/public/index.html @@ -0,0 +1 @@ +<h1>Index Body</h1> \ No newline at end of file diff --git a/view/context-view-engine/views/public/layouts/error.html b/view/context-view-engine/views/public/layouts/error.html new file mode 100644 index 00000000..48598789 --- /dev/null +++ b/view/context-view-engine/views/public/layouts/error.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{.Code}}</title> +</head> +<body> + {{ template "content" .}} + + {{block "message" .}}{{end}} +</body> +</html> \ No newline at end of file diff --git a/view/context-view-engine/views/public/layouts/main.html b/view/context-view-engine/views/public/layouts/main.html new file mode 100644 index 00000000..e2b112b3 --- /dev/null +++ b/view/context-view-engine/views/public/layouts/main.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{ if .Title }}{{ .Title }}{{ else }}Default Main Title{{ end }}</title> +</head> +<body> + {{ template "content" . }} + +<footer>{{ partial "partials/footer" . }}</footer> +</body> +</html> \ No newline at end of file diff --git a/view/context-view-engine/views/public/partials/footer.html b/view/context-view-engine/views/public/partials/footer.html new file mode 100644 index 00000000..61ee8461 --- /dev/null +++ b/view/context-view-engine/views/public/partials/footer.html @@ -0,0 +1 @@ +<h3>Footer Partial</h3> \ No newline at end of file diff --git a/view/embedding-templates-into-app-bindata/bindata.go b/view/embedding-templates-into-app-bindata/bindata.go new file mode 100644 index 00000000..2df28740 --- /dev/null +++ b/view/embedding-templates-into-app-bindata/bindata.go @@ -0,0 +1,406 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// templates/layouts/layout.html +// templates/layouts/mylayout.html +// templates/page1.html +// templates/partials/page1_partial1.html +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _layoutsLayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\xc1\xa9\xc3\x30\x0c\x06\xe0\xf3\x33\x78\x07\xbd\x01\x8c\xc9\x5d\x78\x82\x9e\x4a\x17\x70\x6a\x51\x19\x94\xa4\x38\xca\xc1\x84\xec\x5e\xec\xba\x27\x49\xf0\x89\xff\x47\xd6\x45\x82\x35\xc8\x14\x53\x9b\x9a\x55\x28\xdc\x62\xdd\x0e\x45\xff\xbd\xac\xb1\x06\xfd\x4f\xcc\x5b\xaa\xc1\x9a\x3f\xe4\x29\x3c\x38\xef\x90\x77\x50\x26\x78\xc9\x36\x47\x01\x19\xaf\x3c\x75\x34\x17\xf0\x7d\xf9\x77\x0e\xee\xb4\x26\x2a\x5d\x3f\x8f\x52\x68\x55\x50\x5a\xde\x12\x95\x80\xa9\x10\x38\xd7\xec\x79\x42\xcd\x24\x09\xae\xab\x05\x8f\x40\xf4\xa3\xeb\x27\x00\x00\xff\xff\x68\xca\x16\xc2\xb4\x00\x00\x00") + +func layoutsLayoutHtmlBytes() ([]byte, error) { + return bindataRead( + _layoutsLayoutHtml, + "layouts/layout.html", + ) +} + +func layoutsLayoutHtml() (*asset, error) { + bytes, err := layoutsLayoutHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layouts/layout.html", size: 180, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _layoutsMylayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8f\x4d\x6a\xc5\x30\x0c\x84\xd7\x35\xf8\x0e\xd3\x03\x18\x93\xbd\xf1\x09\xba\x2a\xbd\x80\x53\xab\xc8\xe0\x9f\xe2\x28\x0b\x13\x72\xf7\x47\x9c\xbc\x95\x46\x62\x46\x7c\xe3\x58\x4a\xf6\x5a\x39\xa6\x10\xaf\x29\x49\x32\xf9\x32\xf0\x15\x46\xdb\xc5\xd9\xfb\xa0\x95\x56\xce\xbe\x4d\x6b\x8b\xc3\x6b\xf5\xe1\x78\xf1\x3f\x9c\x36\xa4\x0d\xc2\x84\x3c\x33\xf8\x6b\x7d\xae\xb6\x0c\x8b\x50\xe3\x14\x4d\x98\x3a\x7a\xdb\x85\x36\xb4\x9a\x87\xb3\xbc\xcc\x27\x6b\x87\x9d\xe2\xd3\x18\x7c\x53\x8d\x74\xc7\x7f\xf7\xde\xa9\x0a\x84\xca\x7f\x0e\x42\x60\xea\x04\x63\x2e\xef\x71\x60\x24\xca\x11\xe7\x79\x81\x3d\x40\xce\x3e\x75\x5e\x01\x00\x00\xff\xff\x64\xea\xc5\x1d\xd7\x00\x00\x00") + +func layoutsMylayoutHtmlBytes() ([]byte, error) { + return bindataRead( + _layoutsMylayoutHtml, + "layouts/mylayout.html", + ) +} + +func layoutsMylayoutHtml() (*asset, error) { + bytes, err := layoutsMylayoutHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layouts/mylayout.html", size: 215, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _page1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x41\xaa\xc2\x30\x10\x00\xd0\xf5\x2f\xf4\x0e\xc3\xec\xbf\x25\x5b\x8d\x3d\x83\x37\x90\x69\x33\xa4\xa1\x63\x53\x26\x69\x40\x42\xee\x2e\xa2\xb8\x7c\xf0\xac\x0b\x05\x52\x7e\x0a\x5f\x71\xa2\x79\xf5\x1a\x8f\xcd\xfd\xcf\x51\xa2\x9e\x61\x12\x9a\xd7\x0b\xfc\x74\x30\x8e\x7d\xd7\x77\x7f\x76\x31\xe3\x8d\x3c\x83\x81\x5a\xc1\x2b\x73\x06\x0c\x1a\x12\x38\x2e\x2c\x71\x67\xc5\xd6\xec\xb0\x98\xcf\xaf\x15\x94\x37\xc7\x0a\xb8\x93\xe6\x40\x92\x86\x9d\x3c\x9b\xfb\x97\xe6\xb4\xe4\x87\x60\x6b\xef\x6e\x07\x17\xca\xd8\x77\xaf\x00\x00\x00\xff\xff\x47\x41\x4a\x5c\x9d\x00\x00\x00") + +func page1HtmlBytes() ([]byte, error) { + return bindataRead( + _page1Html, + "page1.html", + ) +} + +func page1Html() (*asset, error) { + bytes, err := page1HtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "page1.html", size: 157, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _partialsPage1_partial1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x49\xc9\x2c\x53\x28\x2e\xa9\xcc\x49\xb5\x55\x4a\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x28\xcf\xc8\x2c\x49\xb5\x56\x80\xf2\x8a\x52\x53\x94\xec\x78\xb9\x38\x6d\x32\x0c\xed\x02\x12\xd3\x53\x15\x0c\xd5\x8b\x15\x02\x12\x8b\x4a\x32\x13\x73\x14\x0c\x6d\xf4\x33\x0c\xed\x78\xb9\x6c\xf4\x53\x32\xcb\xec\x78\xb9\x00\x01\x00\x00\xff\xff\xa2\xa6\x60\xb6\x59\x00\x00\x00") + +func partialsPage1_partial1HtmlBytes() ([]byte, error) { + return bindataRead( + _partialsPage1_partial1Html, + "partials/page1_partial1.html", + ) +} + +func partialsPage1_partial1Html() (*asset, error) { + bytes, err := partialsPage1_partial1HtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "partials/page1_partial1.html", size: 89, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "layouts/layout.html": layoutsLayoutHtml, + "layouts/mylayout.html": layoutsMylayoutHtml, + "page1.html": page1Html, + "partials/page1_partial1.html": partialsPage1_partial1Html, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "layouts": {nil, map[string]*bintree{ + "layout.html": {layoutsLayoutHtml, map[string]*bintree{}}, + "mylayout.html": {layoutsMylayoutHtml, map[string]*bintree{}}, + }}, + "page1.html": {page1Html, map[string]*bintree{}}, + "partials": {nil, map[string]*bintree{ + "page1_partial1.html": {partialsPage1_partial1Html, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/view/embedding-templates-into-app-bindata/main.go b/view/embedding-templates-into-app-bindata/main.go new file mode 100644 index 00000000..fbecfdda --- /dev/null +++ b/view/embedding-templates-into-app-bindata/main.go @@ -0,0 +1,58 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + // $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest + // $ go-bindata -fs -prefix "templates" ./templates/... + // $ go run . + // html files are not used, you can delete the folder and run the example. + tmpl := iris.HTML(AssetFile(), ".html") + tmpl.Layout("layouts/layout.html") + tmpl.AddFunc("greet", func(s string) string { + return "Greetings " + s + "!" + }) + + app.RegisterView(tmpl) + + app.Get("/", func(ctx iris.Context) { + if err := ctx.View("page1.html"); err != nil { + ctx.StatusCode(iris.StatusInternalServerError) + ctx.Writef(err.Error()) + } + }) + + // remove the layout for a specific route + app.Get("/nolayout", func(ctx iris.Context) { + ctx.ViewLayout(iris.NoLayout) + if err := ctx.View("page1.html"); err != nil { + ctx.StatusCode(iris.StatusInternalServerError) + ctx.Writef(err.Error()) + } + }) + + // set a layout for a party, .Layout should be BEFORE any Get or other Handle party's method + my := app.Party("/my").Layout("layouts/mylayout.html") + { // both of these will use the layouts/mylayout.html as their layout. + my.Get("/", func(ctx iris.Context) { + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + my.Get("/other", func(ctx iris.Context) { + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + } + + // http://localhost:8080 + // http://localhost:8080/nolayout + // http://localhost:8080/my + // http://localhost:8080/my/other + app.Listen(":8080") +} diff --git a/view/embedding-templates-into-app/templates/layouts/layout.html b/view/embedding-templates-into-app-bindata/templates/layouts/layout.html similarity index 91% rename from view/embedding-templates-into-app/templates/layouts/layout.html rename to view/embedding-templates-into-app-bindata/templates/layouts/layout.html index 69b545ec..929a31cd 100644 --- a/view/embedding-templates-into-app/templates/layouts/layout.html +++ b/view/embedding-templates-into-app-bindata/templates/layouts/layout.html @@ -7,6 +7,6 @@ <h1>This is the global layout</h1> <br /> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/embedding-templates-into-app/templates/layouts/mylayout.html b/view/embedding-templates-into-app-bindata/templates/layouts/mylayout.html similarity index 92% rename from view/embedding-templates-into-app/templates/layouts/mylayout.html rename to view/embedding-templates-into-app-bindata/templates/layouts/mylayout.html index d22426fe..4cbced18 100644 --- a/view/embedding-templates-into-app/templates/layouts/mylayout.html +++ b/view/embedding-templates-into-app-bindata/templates/layouts/mylayout.html @@ -7,6 +7,6 @@ <h1>This is the layout for the /my/ and /my/other routes only</h1> <br /> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/embedding-templates-into-app/templates/page1.html b/view/embedding-templates-into-app-bindata/templates/page1.html similarity index 69% rename from view/embedding-templates-into-app/templates/page1.html rename to view/embedding-templates-into-app-bindata/templates/page1.html index 6f63f7b3..03659b45 100644 --- a/view/embedding-templates-into-app/templates/page1.html +++ b/view/embedding-templates-into-app-bindata/templates/page1.html @@ -2,6 +2,6 @@ <h1>Page 1 {{ greet "iris developer"}}</h1> - {{ render "partials/page1_partial1.html"}} + {{ render "partials/page1_partial1.html" . }} </div> diff --git a/view/embedding-templates-into-app/templates/partials/page1_partial1.html b/view/embedding-templates-into-app-bindata/templates/partials/page1_partial1.html similarity index 100% rename from view/embedding-templates-into-app/templates/partials/page1_partial1.html rename to view/embedding-templates-into-app-bindata/templates/partials/page1_partial1.html diff --git a/view/embedding-templates-into-app/bindata.go b/view/embedding-templates-into-app/bindata.go deleted file mode 100644 index 896c1807..00000000 --- a/view/embedding-templates-into-app/bindata.go +++ /dev/null @@ -1,310 +0,0 @@ -// Code generated by go-bindata. -// sources: -// templates/layouts/layout.html -// templates/layouts/mylayout.html -// templates/page1.html -// templates/partials/page1_partial1.html -// DO NOT EDIT! - -package main - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _templatesLayoutsLayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\xce\xc1\xa9\xc3\x30\x0c\x06\xe0\xf3\x33\x78\x07\xbd\x01\x8c\xc9\x5d\x78\x82\x9e\x4a\x17\x70\x6a\x51\x19\x94\xa4\x38\xca\xc1\x84\xec\x5e\xec\xba\x27\x49\xf0\x89\xff\x47\xd6\x45\x82\x35\xc8\x14\x53\x9b\x9a\x55\x28\xdc\x62\xdd\x0e\x45\xff\xbd\xac\xb1\x06\xfd\x4f\xcc\x5b\xaa\xc1\x9a\x3f\xe4\x29\x3c\x38\xef\x90\x77\x50\x26\x78\xc9\x36\x47\x01\x19\xaf\x3c\x75\x34\x17\xf0\x7d\xf9\x77\x0e\xee\xb4\x26\x2a\x5d\x3f\x8f\x52\x68\x55\x50\x5a\xde\x12\x95\x80\xa9\x10\x38\xd7\xec\x79\x42\xcd\x24\x09\xae\xab\x05\x8f\x40\xf4\xa3\xeb\x27\x00\x00\xff\xff\x68\xca\x16\xc2\xb4\x00\x00\x00") - -func templatesLayoutsLayoutHtmlBytes() ([]byte, error) { - return bindataRead( - _templatesLayoutsLayoutHtml, - "templates/layouts/layout.html", - ) -} - -func templatesLayoutsLayoutHtml() (*asset, error) { - bytes, err := templatesLayoutsLayoutHtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "templates/layouts/layout.html", size: 180, mode: os.FileMode(438), modTime: time.Unix(1499700235, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _templatesLayoutsMylayoutHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x34\x8f\x4d\x6a\xc5\x30\x0c\x84\xd7\x35\xf8\x0e\xd3\x03\x18\x93\xbd\xf1\x09\xba\x2a\xbd\x80\x53\xab\xc8\xe0\x9f\xe2\x28\x0b\x13\x72\xf7\x47\x9c\xbc\x95\x46\x62\x46\x7c\xe3\x58\x4a\xf6\x5a\x39\xa6\x10\xaf\x29\x49\x32\xf9\x32\xf0\x15\x46\xdb\xc5\xd9\xfb\xa0\x95\x56\xce\xbe\x4d\x6b\x8b\xc3\x6b\xf5\xe1\x78\xf1\x3f\x9c\x36\xa4\x0d\xc2\x84\x3c\x33\xf8\x6b\x7d\xae\xb6\x0c\x8b\x50\xe3\x14\x4d\x98\x3a\x7a\xdb\x85\x36\xb4\x9a\x87\xb3\xbc\xcc\x27\x6b\x87\x9d\xe2\xd3\x18\x7c\x53\x8d\x74\xc7\x7f\xf7\xde\xa9\x0a\x84\xca\x7f\x0e\x42\x60\xea\x04\x63\x2e\xef\x71\x60\x24\xca\x11\xe7\x79\x81\x3d\x40\xce\x3e\x75\x5e\x01\x00\x00\xff\xff\x64\xea\xc5\x1d\xd7\x00\x00\x00") - -func templatesLayoutsMylayoutHtmlBytes() ([]byte, error) { - return bindataRead( - _templatesLayoutsMylayoutHtml, - "templates/layouts/mylayout.html", - ) -} - -func templatesLayoutsMylayoutHtml() (*asset, error) { - bytes, err := templatesLayoutsMylayoutHtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "templates/layouts/mylayout.html", size: 215, mode: os.FileMode(438), modTime: time.Unix(1499700235, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _templatesPage1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\xca\x41\xaa\xc2\x30\x10\x00\xd0\xf5\x2f\xf4\x0e\xc3\xec\xbf\x25\x5b\x8d\x3d\x83\x37\x90\x69\x33\xa4\xa1\x63\x53\x26\x69\x40\x42\xee\x2e\xa2\xb8\x7c\xf0\xac\x0b\x05\x52\x7e\x0a\x5f\x71\xa2\x79\xf5\x1a\x8f\xcd\xfd\xcf\x51\xa2\x9e\x61\x12\x9a\xd7\x0b\xfc\x74\x30\x8e\x7d\xd7\x77\x7f\x76\x31\xe3\x8d\x3c\x83\x81\x5a\xc1\x2b\x73\x06\x0c\x1a\x12\x38\x2e\x2c\x71\x67\xc5\xd6\xec\xb0\x98\xcf\xaf\x15\x94\x37\xc7\x0a\xb8\x93\xe6\x40\x92\x86\x9d\x3c\x9b\xfb\x97\xe6\xb4\xe4\x87\x60\x6b\xef\x6e\x07\x17\xca\xd8\x77\xaf\x00\x00\x00\xff\xff\x47\x41\x4a\x5c\x9d\x00\x00\x00") - -func templatesPage1HtmlBytes() ([]byte, error) { - return bindataRead( - _templatesPage1Html, - "templates/page1.html", - ) -} - -func templatesPage1Html() (*asset, error) { - bytes, err := templatesPage1HtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "templates/page1.html", size: 157, mode: os.FileMode(438), modTime: time.Unix(1499700235, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -var _templatesPartialsPage1_partial1Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x49\xc9\x2c\x53\x28\x2e\xa9\xcc\x49\xb5\x55\x4a\x4a\x4c\xce\x4e\x2f\xca\x2f\xcd\x4b\xd1\x4d\xce\xcf\xc9\x2f\xb2\x52\x28\xcf\xc8\x2c\x49\xb5\x56\x80\xf2\x8a\x52\x53\x94\xec\x78\xb9\x38\x6d\x32\x0c\xed\x02\x12\xd3\x53\x15\x0c\xd5\x8b\x15\x02\x12\x8b\x4a\x32\x13\x73\x14\x0c\x6d\xf4\x33\x0c\xed\x78\xb9\x6c\xf4\x53\x32\xcb\xec\x78\xb9\x00\x01\x00\x00\xff\xff\xa2\xa6\x60\xb6\x59\x00\x00\x00") - -func templatesPartialsPage1_partial1HtmlBytes() ([]byte, error) { - return bindataRead( - _templatesPartialsPage1_partial1Html, - "templates/partials/page1_partial1.html", - ) -} - -func templatesPartialsPage1_partial1Html() (*asset, error) { - bytes, err := templatesPartialsPage1_partial1HtmlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "templates/partials/page1_partial1.html", size: 89, mode: os.FileMode(438), modTime: time.Unix(1499700235, 0)} - a := &asset{bytes: bytes, info: info} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - cannonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[cannonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "templates/layouts/layout.html": templatesLayoutsLayoutHtml, - "templates/layouts/mylayout.html": templatesLayoutsMylayoutHtml, - "templates/page1.html": templatesPage1Html, - "templates/partials/page1_partial1.html": templatesPartialsPage1_partial1Html, -} - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"} -// AssetDir("data/img") would return []string{"a.png", "b.png"} -// AssetDir("foo.txt") and AssetDir("notexist") would return an error -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - cannonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(cannonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "templates": {nil, map[string]*bintree{ - "layouts": {nil, map[string]*bintree{ - "layout.html": {templatesLayoutsLayoutHtml, map[string]*bintree{}}, - "mylayout.html": {templatesLayoutsMylayoutHtml, map[string]*bintree{}}, - }}, - "page1.html": {templatesPage1Html, map[string]*bintree{}}, - "partials": {nil, map[string]*bintree{ - "page1_partial1.html": {templatesPartialsPage1_partial1Html, map[string]*bintree{}}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) - if err != nil { - return err - } - return nil -} - -// RestoreAssets restores an asset under the given directory recursively -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - cannonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) -} diff --git a/view/embedding-templates-into-app/embedded/templates/layouts/layout.html b/view/embedding-templates-into-app/embedded/templates/layouts/layout.html new file mode 100644 index 00000000..929a31cd --- /dev/null +++ b/view/embedding-templates-into-app/embedded/templates/layouts/layout.html @@ -0,0 +1,12 @@ +<html> +<head> +<title>Layout</title> + +</head> +<body> + <h1>This is the global layout</h1> + <br /> + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/view/embedding-templates-into-app/embedded/templates/layouts/mylayout.html b/view/embedding-templates-into-app/embedded/templates/layouts/mylayout.html new file mode 100644 index 00000000..4cbced18 --- /dev/null +++ b/view/embedding-templates-into-app/embedded/templates/layouts/mylayout.html @@ -0,0 +1,12 @@ +<html> +<head> +<title>my Layout</title> + +</head> +<body> + <h1>This is the layout for the /my/ and /my/other routes only</h1> + <br /> + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/view/embedding-templates-into-app/embedded/templates/page1.html b/view/embedding-templates-into-app/embedded/templates/page1.html new file mode 100644 index 00000000..03659b45 --- /dev/null +++ b/view/embedding-templates-into-app/embedded/templates/page1.html @@ -0,0 +1,7 @@ +<div style="background-color: black; color: blue"> + + <h1>Page 1 {{ greet "iris developer"}}</h1> + + {{ render "partials/page1_partial1.html" . }} + +</div> diff --git a/view/embedding-templates-into-app/embedded/templates/partials/page1_partial1.html b/view/embedding-templates-into-app/embedded/templates/partials/page1_partial1.html new file mode 100644 index 00000000..66ba9266 --- /dev/null +++ b/view/embedding-templates-into-app/embedded/templates/partials/page1_partial1.html @@ -0,0 +1,3 @@ +<div style="background-color: white; color: red"> + <h1>Page 1's Partial 1</h1> +</div> diff --git a/view/embedding-templates-into-app/main.go b/view/embedding-templates-into-app/main.go index 69372f95..b6f5d2ca 100644 --- a/view/embedding-templates-into-app/main.go +++ b/view/embedding-templates-into-app/main.go @@ -1,31 +1,30 @@ package main import ( - "github.com/kataras/iris" + "embed" + + "github.com/kataras/iris/v12" ) +//go:embed embedded/* +var embeddedFS embed.FS + func main() { app := iris.New() - tmpl := iris.HTML("./templates", ".html") + tmpl := iris.HTML(embeddedFS, ".html").RootDir("embedded/templates") + tmpl.Layout("layouts/layout.html") tmpl.AddFunc("greet", func(s string) string { return "Greetings " + s + "!" }) - // $ go get -u github.com/shuLhan/go-bindata/... - // $ go-bindata ./templates/... - // $ go build - // $ ./embedding-templates-into-app - // html files are not used, you can delete the folder and run the example. - tmpl.Binary(Asset, AssetNames) // <-- IMPORTANT - app.RegisterView(tmpl) app.Get("/", func(ctx iris.Context) { if err := ctx.View("page1.html"); err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.Writef(err.Error()) + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -33,8 +32,8 @@ func main() { app.Get("/nolayout", func(ctx iris.Context) { ctx.ViewLayout(iris.NoLayout) if err := ctx.View("page1.html"); err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.Writef(err.Error()) + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -42,10 +41,16 @@ func main() { my := app.Party("/my").Layout("layouts/mylayout.html") { // both of these will use the layouts/mylayout.html as their layout. my.Get("/", func(ctx iris.Context) { - ctx.View("page1.html") + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) my.Get("/other", func(ctx iris.Context) { - ctx.View("page1.html") + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) } @@ -53,10 +58,5 @@ func main() { // http://localhost:8080/nolayout // http://localhost:8080/my // http://localhost:8080/my/other - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } - -// Note for new Gophers: -// `go build` is used instead of `go run main.go` as the example comments says -// otherwise you will get compile errors, this is a Go thing; -// because you have multiple files in the `package main`. diff --git a/view/fallback/main.go b/view/fallback/main.go new file mode 100644 index 00000000..067744b7 --- /dev/null +++ b/view/fallback/main.go @@ -0,0 +1,45 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.HTML("./view", ".html")) + + // Use the FallbackView helper Register a fallback view + // filename per-party when the provided was not found. + app.FallbackView(iris.FallbackView("fallback.html")) + + // Use the FallbackViewLayout helper to register a fallback view layout. + app.FallbackView(iris.FallbackViewLayout("layout.html")) + + // Register a custom fallback function per-party to handle everything. + // You can register more than one. If fails (returns a not nil error of ErrViewNotExists) + // then it proceeds to the next registered fallback. + app.FallbackView(iris.FallbackViewFunc(func(ctx iris.Context, err iris.ErrViewNotExist) error { + // err.Name is the previous template name. + // err.IsLayout reports whether the failure came from the layout template. + // err.Data is the template data provided to the previous View call. + // [...custom logic e.g. ctx.View("fallback.html", err.Data)] + return err + })) + + app.Get("/", index) + + app.Listen(":8080") +} + +// Register fallback view(s) in a middleware. +// func fallbackInsideAMiddleware(ctx iris.Context) { +// ctx.FallbackView(...) +// To remove all previous registered fallbacks, pass nil. +// ctx.FallbackView(nil) +// ctx.Next() +// } + +func index(ctx iris.Context) { + if err := ctx.View("blabla.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/fallback/view/fallback.html b/view/fallback/view/fallback.html new file mode 100644 index 00000000..c10ca04c --- /dev/null +++ b/view/fallback/view/fallback.html @@ -0,0 +1 @@ +<h1>Fallback view</h1> \ No newline at end of file diff --git a/http_responsewriter/herotemplate/README.md b/view/herotemplate/README.md similarity index 100% rename from http_responsewriter/herotemplate/README.md rename to view/herotemplate/README.md diff --git a/http_responsewriter/herotemplate/app.go b/view/herotemplate/app.go similarity index 54% rename from http_responsewriter/herotemplate/app.go rename to view/herotemplate/app.go index 92ac22dc..62f7a53a 100644 --- a/http_responsewriter/herotemplate/app.go +++ b/view/herotemplate/app.go @@ -3,9 +3,9 @@ package main import ( "bytes" - "github.com/iris-contrib/examples/http_responsewriter/herotemplate/template" + "github.com/kataras/iris/v12/_examples/view/herotemplate/template" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // $ go get -u github.com/shiyanhui/hero/hero @@ -14,14 +14,13 @@ import ( // Read more at https://github.com/shiyanhui/hero/hero func main() { - app := iris.New() app.Get("/users", func(ctx iris.Context) { - ctx.Gzip(true) + ctx.CompressWriter(true) ctx.ContentType("text/html") - var userList = []string{ + userList := []string{ "Alice", "Bob", "Tom", @@ -36,20 +35,18 @@ func main() { // template.UserList(userList, buffer) // ctx.Write(buffer.Bytes()) - // using an io.Writer for automatic buffer management (i.e. hero built-in buffer pool), - // iris context implements the io.Writer by its ResponseWriter - // which is an enhanced version of the standard http.ResponseWriter - // but still 100% compatible, GzipResponseWriter too: - // _, err := template.UserListToWriter(userList, ctx.GzipResponseWriter()) + // iris context implements the io.Writer: + // _, err := template.UserListToWriter(userList, ctx) + // OR: buffer := new(bytes.Buffer) template.UserList(userList, buffer) _, err := ctx.Write(buffer.Bytes()) if err != nil { - ctx.StatusCode(iris.StatusInternalServerError) - ctx.WriteString(err.Error()) + ctx.StopWithError(iris.StatusInternalServerError, err) + return } }) - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/http_responsewriter/herotemplate/template/index.html b/view/herotemplate/template/index.html similarity index 100% rename from http_responsewriter/herotemplate/template/index.html rename to view/herotemplate/template/index.html diff --git a/http_responsewriter/herotemplate/template/index.html.go b/view/herotemplate/template/index.html.go similarity index 100% rename from http_responsewriter/herotemplate/template/index.html.go rename to view/herotemplate/template/index.html.go diff --git a/http_responsewriter/herotemplate/template/user.html b/view/herotemplate/template/user.html similarity index 100% rename from http_responsewriter/herotemplate/template/user.html rename to view/herotemplate/template/user.html diff --git a/http_responsewriter/herotemplate/template/user.html.go b/view/herotemplate/template/user.html.go similarity index 100% rename from http_responsewriter/herotemplate/template/user.html.go rename to view/herotemplate/template/user.html.go diff --git a/http_responsewriter/herotemplate/template/userlist.html b/view/herotemplate/template/userlist.html similarity index 100% rename from http_responsewriter/herotemplate/template/userlist.html rename to view/herotemplate/template/userlist.html diff --git a/http_responsewriter/herotemplate/template/userlist.html.go b/view/herotemplate/template/userlist.html.go similarity index 99% rename from http_responsewriter/herotemplate/template/userlist.html.go rename to view/herotemplate/template/userlist.html.go index ebf6fcf1..d8d62324 100644 --- a/http_responsewriter/herotemplate/template/userlist.html.go +++ b/view/herotemplate/template/userlist.html.go @@ -37,5 +37,4 @@ func UserList(userList []string, buffer *bytes.Buffer) { </body> </html> `) - } diff --git a/http_responsewriter/herotemplate/template/userlistwriter.html b/view/herotemplate/template/userlistwriter.html similarity index 100% rename from http_responsewriter/herotemplate/template/userlistwriter.html rename to view/herotemplate/template/userlistwriter.html diff --git a/http_responsewriter/herotemplate/template/userlistwriter.html.go b/view/herotemplate/template/userlistwriter.html.go similarity index 99% rename from http_responsewriter/herotemplate/template/userlistwriter.html.go rename to view/herotemplate/template/userlistwriter.html.go index 114bffa9..f6df2ed5 100644 --- a/http_responsewriter/herotemplate/template/userlistwriter.html.go +++ b/view/herotemplate/template/userlistwriter.html.go @@ -40,5 +40,4 @@ func UserListToWriter(userList []string, w io.Writer) (int, error) { </html> `) return w.Write(_buffer.Bytes()) - } diff --git a/view/layout/ace/main.go b/view/layout/ace/main.go new file mode 100644 index 00000000..e3d05eef --- /dev/null +++ b/view/layout/ace/main.go @@ -0,0 +1,29 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + // By default Ace minifies the template before render, + // using the SetIndent method, we make it to match + // the rest of the template results. + app.RegisterView(iris.Ace("./views", ".ace").SetIndent(" ")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + ctx.ViewLayout("layouts/main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/ace/views/index.ace b/view/layout/ace/views/index.ace new file mode 100644 index 00000000..38b81f08 --- /dev/null +++ b/view/layout/ace/views/index.ace @@ -0,0 +1,2 @@ +h1 Index Body +h3 Message: {{.Message}} \ No newline at end of file diff --git a/view/layout/ace/views/layouts/main.ace b/view/layout/ace/views/layouts/main.ace new file mode 100644 index 00000000..d17414b3 --- /dev/null +++ b/view/layout/ace/views/layouts/main.ace @@ -0,0 +1,8 @@ += doctype html +html + head + title {{.Title}} + body + {{ yield . }} + footer + = include partials/footer.ace . \ No newline at end of file diff --git a/view/layout/ace/views/partials/footer.ace b/view/layout/ace/views/partials/footer.ace new file mode 100644 index 00000000..aefe45fd --- /dev/null +++ b/view/layout/ace/views/partials/footer.ace @@ -0,0 +1,2 @@ +h3 Footer Partial +h4 {{.FooterText}} \ No newline at end of file diff --git a/view/layout/blocks/main.go b/view/layout/blocks/main.go new file mode 100644 index 00000000..f65155fb --- /dev/null +++ b/view/layout/blocks/main.go @@ -0,0 +1,30 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.Blocks("./views", ".html")) + // Note, in Blocks engine, layouts + // are used by their base names, the + // blocks.LayoutDir(layoutDir) defaults to "./layouts". + // .Blocks(...).Layout("main") for default layout for all views, it can be modified through ctx.ViewLayout though. + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + ctx.ViewLayout("main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/blocks/views/index.html b/view/layout/blocks/views/index.html new file mode 100644 index 00000000..f35b8eac --- /dev/null +++ b/view/layout/blocks/views/index.html @@ -0,0 +1,2 @@ +<h1>Index Body</h1> +<h3>Message: {{.Message}}</h3> \ No newline at end of file diff --git a/view/layout/blocks/views/layouts/main.html b/view/layout/blocks/views/layouts/main.html new file mode 100644 index 00000000..e8bd6089 --- /dev/null +++ b/view/layout/blocks/views/layouts/main.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<head> + <title>{{.Title}}</title> +</head> +<body> +{{ template "content" . }} +<footer> +{{ partial "partials/footer" . }} +</footer> +</body> +</html> \ No newline at end of file diff --git a/view/layout/blocks/views/partials/footer.html b/view/layout/blocks/views/partials/footer.html new file mode 100644 index 00000000..6ea1a8a2 --- /dev/null +++ b/view/layout/blocks/views/partials/footer.html @@ -0,0 +1,2 @@ +<h3>Footer Partial</h3> +<h4>{{.FooterText}}</h4> \ No newline at end of file diff --git a/view/layout/django/main.go b/view/layout/django/main.go new file mode 100644 index 00000000..ad6cc034 --- /dev/null +++ b/view/layout/django/main.go @@ -0,0 +1,28 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.Django("./views", ".html")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + // On Django this is ignored: ctx.ViewLayout("layouts/main") + // Layouts are only rendered from inside the index page itself + // using the "extends" keyword. + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/django/views/index.html b/view/layout/django/views/index.html new file mode 100644 index 00000000..e960e91d --- /dev/null +++ b/view/layout/django/views/index.html @@ -0,0 +1,6 @@ +{% extends "layouts/main.html" %} + +{% block content %} +<h1>Index Body</h1> +<h3>Message: {{Message}}</h3> +{% endblock %} \ No newline at end of file diff --git a/view/layout/django/views/layouts/main.html b/view/layout/django/views/layouts/main.html new file mode 100644 index 00000000..043e7c22 --- /dev/null +++ b/view/layout/django/views/layouts/main.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<head> + <title>{{Title}}</title> +</head> +<body> + {% block content %} {% endblock %} + +<footer>{% include "../partials/footer.html" %}</footer> +</body> +</html> \ No newline at end of file diff --git a/view/layout/django/views/partials/footer.html b/view/layout/django/views/partials/footer.html new file mode 100644 index 00000000..c078f0d6 --- /dev/null +++ b/view/layout/django/views/partials/footer.html @@ -0,0 +1,2 @@ +<h3>Footer Partial</h3> +<h4>{{FooterText}}</h4> \ No newline at end of file diff --git a/view/layout/handlebars/main.go b/view/layout/handlebars/main.go new file mode 100644 index 00000000..7b62c7b8 --- /dev/null +++ b/view/layout/handlebars/main.go @@ -0,0 +1,27 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.RegisterView(iris.Handlebars("./views", ".html")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + ctx.ViewLayout("layouts/main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/handlebars/views/index.html b/view/layout/handlebars/views/index.html new file mode 100644 index 00000000..b6b44104 --- /dev/null +++ b/view/layout/handlebars/views/index.html @@ -0,0 +1,2 @@ +<h1>Index Body</h1> +<h3>Message: {{Message}} </h3> \ No newline at end of file diff --git a/view/layout/handlebars/views/layouts/main.html b/view/layout/handlebars/views/layouts/main.html new file mode 100644 index 00000000..1dd581b8 --- /dev/null +++ b/view/layout/handlebars/views/layouts/main.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<head> + <title>{{Title}}</title> +</head> +<body> + {{ yield . }} + +<footer>{{ render "partials/footer.html" .}}</footer> +</body> +</html> \ No newline at end of file diff --git a/view/layout/handlebars/views/partials/footer.html b/view/layout/handlebars/views/partials/footer.html new file mode 100644 index 00000000..c078f0d6 --- /dev/null +++ b/view/layout/handlebars/views/partials/footer.html @@ -0,0 +1,2 @@ +<h3>Footer Partial</h3> +<h4>{{FooterText}}</h4> \ No newline at end of file diff --git a/view/layout/html/main.go b/view/layout/html/main.go new file mode 100644 index 00000000..494f1c76 --- /dev/null +++ b/view/layout/html/main.go @@ -0,0 +1,27 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.RegisterView(iris.HTML("./views", ".html")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + ctx.ViewLayout("layouts/main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/html/views/index.html b/view/layout/html/views/index.html new file mode 100644 index 00000000..f35b8eac --- /dev/null +++ b/view/layout/html/views/index.html @@ -0,0 +1,2 @@ +<h1>Index Body</h1> +<h3>Message: {{.Message}}</h3> \ No newline at end of file diff --git a/view/layout/html/views/layouts/main.html b/view/layout/html/views/layouts/main.html new file mode 100644 index 00000000..898f7f60 --- /dev/null +++ b/view/layout/html/views/layouts/main.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<head> + <title>{{.Title}}</title> +</head> +<body> +{{ yield . }} +<footer> +{{ render "partials/footer.html" . }} +</footer> +</body> +</html> \ No newline at end of file diff --git a/view/layout/html/views/partials/footer.html b/view/layout/html/views/partials/footer.html new file mode 100644 index 00000000..6ea1a8a2 --- /dev/null +++ b/view/layout/html/views/partials/footer.html @@ -0,0 +1,2 @@ +<h3>Footer Partial</h3> +<h4>{{.FooterText}}</h4> \ No newline at end of file diff --git a/view/layout/jet/main.go b/view/layout/jet/main.go new file mode 100644 index 00000000..075266b3 --- /dev/null +++ b/view/layout/jet/main.go @@ -0,0 +1,29 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + app.RegisterView(iris.Jet("./views", ".jet")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + // On Jet this is ignored: ctx.ViewLayout("layouts/main") + // Layouts are only rendered from inside the index page itself + // using the "extends" keyword. + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/jet/views/index.jet b/view/layout/jet/views/index.jet new file mode 100644 index 00000000..5ecb4b58 --- /dev/null +++ b/view/layout/jet/views/index.jet @@ -0,0 +1,5 @@ +{{ extends "../layouts/main.jet" }} +{{ block documentBody() }} +<h1>Index Body</h1> +<h3>Message: {{.Message}}</h3> +{{ end }} \ No newline at end of file diff --git a/view/layout/jet/views/layouts/main.jet b/view/layout/jet/views/layouts/main.jet new file mode 100644 index 00000000..39a625cd --- /dev/null +++ b/view/layout/jet/views/layouts/main.jet @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> + <title>{{.Title}}</title> +</head> +<body> + {{ yield . documentBody() }} +<footer>{{ include "../partials/footer.jet" . }}</footer> +</body> +</html> \ No newline at end of file diff --git a/view/layout/jet/views/partials/footer.jet b/view/layout/jet/views/partials/footer.jet new file mode 100644 index 00000000..6ea1a8a2 --- /dev/null +++ b/view/layout/jet/views/partials/footer.jet @@ -0,0 +1,2 @@ +<h3>Footer Partial</h3> +<h4>{{.FooterText}}</h4> \ No newline at end of file diff --git a/view/layout/pug/main.go b/view/layout/pug/main.go new file mode 100644 index 00000000..4432545f --- /dev/null +++ b/view/layout/pug/main.go @@ -0,0 +1,28 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.Pug("./views", ".pug")) + + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + "FooterText": "Footer contents", + "Message": "Main contents", + } + + // On Pug this is ignored: ctx.ViewLayout("layouts/main") + // Layouts are only rendered from inside the index page itself + // using the "extends" keyword. + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/layout/pug/views/index.pug b/view/layout/pug/views/index.pug new file mode 100644 index 00000000..26ddcbc5 --- /dev/null +++ b/view/layout/pug/views/index.pug @@ -0,0 +1,5 @@ +extends layouts/main.pug + +block content + h1 Index Body + h3 Message: {{.Message}} \ No newline at end of file diff --git a/view/layout/pug/views/layouts/main.pug b/view/layout/pug/views/layouts/main.pug new file mode 100644 index 00000000..c9c46c2d --- /dev/null +++ b/view/layout/pug/views/layouts/main.pug @@ -0,0 +1,8 @@ +doctype html +html + head + title {{.Title}} + body + block content + footer + include ../partials/footer.pug \ No newline at end of file diff --git a/view/layout/pug/views/partials/footer.pug b/view/layout/pug/views/partials/footer.pug new file mode 100644 index 00000000..aefe45fd --- /dev/null +++ b/view/layout/pug/views/partials/footer.pug @@ -0,0 +1,2 @@ +h3 Footer Partial +h4 {{.FooterText}} \ No newline at end of file diff --git a/view/overview/main.go b/view/overview/main.go index 38756d93..bd50af31 100644 --- a/view/overview/main.go +++ b/view/overview/main.go @@ -1,44 +1,107 @@ package main -import "github.com/kataras/iris" +import ( + "html/template" + "time" + + "github.com/kataras/iris/v12" +) + +// ViewFunctions presents some builtin functions +// for html view engines. See `View.Funcs` or `view/html.Funcs` and etc. +var Functions = template.FuncMap{ + "Now": time.Now, +} func main() { app := iris.New() - // - standard html | iris.HTML(...) - // - django | iris.Django(...) - // - pug(jade) | iris.Pug(...) - // - handlebars | iris.Handlebars(...) - // - amber | iris.Amber(...) // with default template funcs: // // - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }} - // - {{ render "header.html" }} - // - {{ render_r "header.html" }} // partial relative path to current page - // - {{ yield }} - // - {{ current }} - app.RegisterView(iris.HTML("./templates", ".html")) + // - {{ render "header.html" . }} + // - {{ render_r "header.html" . }} // partial relative path to current page + // - {{ yield . }} + // - {{ current . }} + app.RegisterView(iris.HTML("./templates", ".html"). + Funcs(Functions). // Optionally register some more builtin functions. + Reload(false)) // Set Reload to true on development. + app.Get("/", func(ctx iris.Context) { + // enable compression based on Accept-Encoding (e.g. "gzip"), + // alternatively: app.Use(iris.Compression). + ctx.CompressWriter(true) + // the .Name inside the ./templates/hi.html. + ctx.ViewData("Name", "iris") + // render the template with the file name relative to the './templates'. + // file extension is OPTIONAL. + if err := ctx.View("hi.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) - ctx.ViewData("Name", "iris") // the .Name inside the ./templates/hi.html - ctx.Gzip(true) // enable gzip for big files - ctx.View("hi.html") // render the template with the file name relative to the './templates' + app.Get("/example_map", func(ctx iris.Context) { + examplePage := iris.Map{ + "Name": "Example Name", + "Age": 42, + "Items": []string{"Example slice entry 1", "entry 2", "entry 3"}, + "Map": iris.Map{"map key": "map value", "other key": "other value"}, + "Nested": iris.Map{"Title": "Iris E-Book", "Pages": 620}, + } + if err := ctx.View("example.html", examplePage); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) - // http://localhost:8080/ - app.Run(iris.Addr(":8080")) -} + app.Get("/example_struct", func(ctx iris.Context) { + type book struct { + Title string + Pages int + } -/* -Note: + var examplePage = struct { + Name string + Age int + Items []string + Map map[string]interface{} + Nested book + }{ + "Example Name", + 42, + []string{"Example slice entry 1", "entry 2", "entry 3"}, + iris.Map{"map key": "map value", "other key": "other value"}, + book{ + "Iris E-Book", + 620, + }, + } -In case you're wondering, the code behind the view engines derives from the "github.com/kataras/iris/view" package, -access to the engines' variables can be granded by "github.com/kataras/iris" package too. + if err := ctx.View("example.html", examplePage); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Get("/functions", func(ctx iris.Context) { + var functionsPage = struct { + // A function. + Now func() time.Time + // A struct field which contains methods. + Ctx iris.Context + }{ + Now: time.Now, + Ctx: ctx, + } + + if err := ctx.View("functions.html", functionsPage); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) - iris.HTML(...) is a shortcut of view.HTML(...) - iris.Django(...) >> >> view.Django(...) - iris.Pug(...) >> >> view.Pug(...) - iris.Handlebars(...) >> >> view.Handlebars(...) - iris.Amber(...) >> >> view.Amber(...) -*/ + // http://localhost:8080/ + app.Listen(":8080") +} diff --git a/view/overview/templates/example.html b/view/overview/templates/example.html new file mode 100644 index 00000000..eccd19ff --- /dev/null +++ b/view/overview/templates/example.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>HTML Template Example</title> +</head> +<body> + <h2>Name: {{.Name}}</h2> + <h3>Age: {{.Age}}</h3> + + <h4>Slice</h4> + {{range $idx, $item := .Items}} + {{ $idx }} - {{ $item }} <br/> + {{end}} + + <h4>Map</h4> + {{range $key, $value := .Map}} + {{ $key }} - {{ $value }} <br/> + {{end}} + + <h4>Nested</h4> + + <strong>Title:</strong>{{ .Nested.Title}} + + <hr/> + + <strong>Read more at: <a href="https://pkg.go.dev/html/template" target="_new"> + https://pkg.go.dev/html/template</a> + </strong> +</body> +</html> \ No newline at end of file diff --git a/view/overview/templates/functions.html b/view/overview/templates/functions.html new file mode 100644 index 00000000..bfbf3709 --- /dev/null +++ b/view/overview/templates/functions.html @@ -0,0 +1,3 @@ +<h1>Function: {{ Now }}</h1> +<h1>Field: {{ .Ctx.Request.URL.Path }} </h1> +<h1>Field Struct's Function (Method): {{ .Ctx.FullRequestURI }} </h1> diff --git a/view/parse-template/django/main.go b/view/parse-template/django/main.go new file mode 100644 index 00000000..8fe6c08a --- /dev/null +++ b/view/parse-template/django/main.go @@ -0,0 +1,30 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + e := iris.Django(nil, ".html") // You can still use a file system though. + e.AddFunc("greet", func(name string) string { + return "Hello, " + name + "!" + }) + err := e.ParseTemplate("program.html", []byte(`<h1>{{greet(Name)}}</h1>`)) + if err != nil { + panic(err) + } + e.Reload(true) + + app := iris.New() + app.RegisterView(e) + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("program.html", iris.Map{ + "Name": "Gerasimos", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/parse-template/handlebars/main.go b/view/parse-template/handlebars/main.go new file mode 100644 index 00000000..1a6adb09 --- /dev/null +++ b/view/parse-template/handlebars/main.go @@ -0,0 +1,28 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + e := iris.Handlebars(nil, ".html") // You can still use a file system though. + e.ParseTemplate("program.html", `<h1>{{greet Name}}</h1>`, iris.Map{ + "greet": func(name string) string { + return "Hello, " + name + "!" + }, + }) + e.Reload(true) + + app := iris.New() + app.RegisterView(e) + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("program.html", iris.Map{ + "Name": "Gerasimos", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/parse-template/jet/main.go b/view/parse-template/jet/main.go new file mode 100644 index 00000000..9b07b32b --- /dev/null +++ b/view/parse-template/jet/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "reflect" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/view" +) + +func main() { + e := iris.Jet(nil, ".jet") // You can still use a file system though. + e.AddFunc("greet", func(args view.JetArguments) reflect.Value { + msg := "Hello, " + args.Get(0).String() + "!" + return reflect.ValueOf(msg) + }) + err := e.ParseTemplate("program.jet", `<h1>{{greet(.Name)}}</h1>`) + if err != nil { + panic(err) + } + e.Reload(true) + + app := iris.New() + app.RegisterView(e) + app.Get("/", index) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("program.jet", iris.Map{ + "Name": "Gerasimos", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/parse-template/main.go b/view/parse-template/main.go new file mode 100644 index 00000000..8c9bd88e --- /dev/null +++ b/view/parse-template/main.go @@ -0,0 +1,45 @@ +// Package main shows how to parse a template through custom byte slice content. +// The following works with HTML, Pug and Ace template parsers. +// To learn how you can manually parse a template from a text for the rest +// template parsers navigate through the example's subdirectories. +package main + +import "github.com/kataras/iris/v12" + +func main() { + // To not load any templates from files or embedded data, + // pass nil or empty string on the first argument: + // e := iris.HTML(nil, ".html") + + e := iris.HTML("./views", ".html") + // e := iris.Pug("./views",".pug") + // e := iris.Ace("./views",".ace") + e.ParseTemplate("program.html", []byte(`<h1>{{greet .Name}}</h1>`), iris.Map{ + "greet": func(name string) string { + return "Hello, " + name + "!" + }, + }) + e.Reload(true) + + app := iris.New() + app.RegisterView(e) + + app.Get("/", index) + app.Get("/layout", layout) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("program.html", iris.Map{ + "Name": "Gerasimos", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func layout(ctx iris.Context) { + ctx.ViewLayout("layouts/main.html") + index(ctx) +} diff --git a/view/parse-template/views/layouts/main.html b/view/parse-template/views/layouts/main.html new file mode 100644 index 00000000..588c57bb --- /dev/null +++ b/view/parse-template/views/layouts/main.html @@ -0,0 +1,11 @@ +<html> +<head> +<title>My Layout</title> + +</head> +<body> + <h1>[layout] Body content is below...</h1> + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/http_responsewriter/quicktemplate/README.md b/view/quicktemplate/README.md similarity index 100% rename from http_responsewriter/quicktemplate/README.md rename to view/quicktemplate/README.md diff --git a/view/quicktemplate/controllers/execute_template.go b/view/quicktemplate/controllers/execute_template.go new file mode 100644 index 00000000..6baf71a4 --- /dev/null +++ b/view/quicktemplate/controllers/execute_template.go @@ -0,0 +1,14 @@ +package controllers + +import ( + "github.com/kataras/iris/v12/_examples/view/quicktemplate/templates" + + "github.com/kataras/iris/v12" +) + +// ExecuteTemplate renders a "tmpl" partial template to the `Context.ResponseWriter`. +func ExecuteTemplate(ctx iris.Context, tmpl templates.Partial) { + ctx.CompressWriter(true) + ctx.ContentType("text/html") + templates.WriteTemplate(ctx, tmpl) +} diff --git a/http_responsewriter/quicktemplate/controllers/hello.go b/view/quicktemplate/controllers/hello.go similarity index 88% rename from http_responsewriter/quicktemplate/controllers/hello.go rename to view/quicktemplate/controllers/hello.go index bb6a6982..009742a4 100644 --- a/http_responsewriter/quicktemplate/controllers/hello.go +++ b/view/quicktemplate/controllers/hello.go @@ -1,9 +1,9 @@ package controllers import ( - "github.com/iris-contrib/examples/http_responsewriter/quicktemplate/templates" + "github.com/kataras/iris/v12/_examples/view/quicktemplate/templates" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // Hello renders our ../templates/hello.qtpl file using the compiled ../templates/hello.qtpl.go file. diff --git a/http_responsewriter/quicktemplate/controllers/index.go b/view/quicktemplate/controllers/index.go similarity index 70% rename from http_responsewriter/quicktemplate/controllers/index.go rename to view/quicktemplate/controllers/index.go index 633d07f4..56cf6717 100644 --- a/http_responsewriter/quicktemplate/controllers/index.go +++ b/view/quicktemplate/controllers/index.go @@ -1,9 +1,9 @@ package controllers import ( - "github.com/iris-contrib/examples/http_responsewriter/quicktemplate/templates" + "github.com/kataras/iris/v12/_examples/view/quicktemplate/templates" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) // Index renders our ../templates/index.qtpl file using the compiled ../templates/index.qtpl.go file. diff --git a/http_responsewriter/quicktemplate/main.go b/view/quicktemplate/main.go similarity index 58% rename from http_responsewriter/quicktemplate/main.go rename to view/quicktemplate/main.go index 85b30e03..7a63ab0d 100644 --- a/http_responsewriter/quicktemplate/main.go +++ b/view/quicktemplate/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/iris-contrib/examples/http_responsewriter/quicktemplate/controllers" + "github.com/kataras/iris/v12/_examples/view/quicktemplate/controllers" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func newApp() *iris.Application { @@ -18,5 +18,5 @@ func main() { app := newApp() // http://localhost:8080 // http://localhost:8080/yourname - app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) + app.Listen(":8080") } diff --git a/http_responsewriter/quicktemplate/main_test.go b/view/quicktemplate/main_test.go similarity index 75% rename from http_responsewriter/quicktemplate/main_test.go rename to view/quicktemplate/main_test.go index db5a88fd..147db84b 100644 --- a/http_responsewriter/quicktemplate/main_test.go +++ b/view/quicktemplate/main_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/kataras/iris/httptest" + "github.com/kataras/iris/v12/httptest" ) func TestResponseWriterQuicktemplate(t *testing.T) { @@ -42,6 +42,6 @@ func TestResponseWriterQuicktemplate(t *testing.T) { e := httptest.New(t, app) - e.GET("/").Expect().Status(httptest.StatusOK).Body().Equal(expectedIndexRawBody) - e.GET("/" + name).Expect().Status(httptest.StatusOK).Body().Equal(expectedHelloRawBody) + e.GET("/").Expect().Status(httptest.StatusOK).Body().IsEqual(expectedIndexRawBody) + e.GET("/" + name).Expect().Status(httptest.StatusOK).Body().IsEqual(expectedHelloRawBody) } diff --git a/view/quicktemplate/models/.gitkeep b/view/quicktemplate/models/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/http_responsewriter/quicktemplate/templates/base.qtpl b/view/quicktemplate/templates/base.qtpl similarity index 100% rename from http_responsewriter/quicktemplate/templates/base.qtpl rename to view/quicktemplate/templates/base.qtpl diff --git a/http_responsewriter/quicktemplate/templates/base.qtpl.go b/view/quicktemplate/templates/base.qtpl.go similarity index 100% rename from http_responsewriter/quicktemplate/templates/base.qtpl.go rename to view/quicktemplate/templates/base.qtpl.go diff --git a/http_responsewriter/quicktemplate/templates/hello.qtpl b/view/quicktemplate/templates/hello.qtpl similarity index 100% rename from http_responsewriter/quicktemplate/templates/hello.qtpl rename to view/quicktemplate/templates/hello.qtpl diff --git a/http_responsewriter/quicktemplate/templates/hello.qtpl.go b/view/quicktemplate/templates/hello.qtpl.go similarity index 100% rename from http_responsewriter/quicktemplate/templates/hello.qtpl.go rename to view/quicktemplate/templates/hello.qtpl.go diff --git a/http_responsewriter/quicktemplate/templates/index.qtpl b/view/quicktemplate/templates/index.qtpl similarity index 100% rename from http_responsewriter/quicktemplate/templates/index.qtpl rename to view/quicktemplate/templates/index.qtpl diff --git a/http_responsewriter/quicktemplate/templates/index.qtpl.go b/view/quicktemplate/templates/index.qtpl.go similarity index 100% rename from http_responsewriter/quicktemplate/templates/index.qtpl.go rename to view/quicktemplate/templates/index.qtpl.go diff --git a/view/templ/go.mod b/view/templ/go.mod new file mode 100644 index 00000000..42d779dc --- /dev/null +++ b/view/templ/go.mod @@ -0,0 +1,53 @@ +module github.com/kataras/iris/v12/_examples/view/templ + +go 1.22 + +require ( + github.com/a-h/templ v0.2.663 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/view/templ/go.sum b/view/templ/go.sum new file mode 100644 index 00000000..26da2eea --- /dev/null +++ b/view/templ/go.sum @@ -0,0 +1,180 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/a-h/templ v0.2.663 h1:aa0WMm27InkYHGjimcM7us6hJ6BLhg98ZbfaiDPyjHE= +github.com/a-h/templ v0.2.663/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/view/templ/hello.templ b/view/templ/hello.templ new file mode 100644 index 00000000..e9203a95 --- /dev/null +++ b/view/templ/hello.templ @@ -0,0 +1,5 @@ +package main + +templ hello(name string) { + <div>Hello, <strong>{ name }</strong></div> +} \ No newline at end of file diff --git a/view/templ/hello_templ.go b/view/templ/hello_templ.go new file mode 100644 index 00000000..f1472a90 --- /dev/null +++ b/view/templ/hello_templ.go @@ -0,0 +1,53 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: 0.2.476 +package main + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +func hello(name string) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var2 := `Hello, ` + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<strong>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string = name + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</strong></div>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} diff --git a/view/templ/main.go b/view/templ/main.go new file mode 100644 index 00000000..42113a93 --- /dev/null +++ b/view/templ/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +// $ go install github.com/a-h/templ/cmd/templ@latest +// $ templ generate +// $ go run . +func main() { + component := hello("Makis") + + app := iris.New() + app.Get("/", iris.Component(component)) + + app.Listen(":8080") +} diff --git a/view/template_ace_0/main.go b/view/template_ace_0/main.go new file mode 100644 index 00000000..3e8637a0 --- /dev/null +++ b/view/template_ace_0/main.go @@ -0,0 +1,37 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + + // Read about its markup syntax at: https://github.com/yosssi/ace + tmpl := iris.Ace("./views", ".ace") + // tmpl.Layout("layouts/main.ace") -> global layout for all pages. + + app.RegisterView(tmpl) + + app.Get("/", func(ctx iris.Context) { + if err := ctx.View("index", iris.Map{ + "Title": "Title of The Page", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Get("/layout", func(ctx iris.Context) { + ctx.ViewLayout("layouts/main") // layout for that response. + if err := ctx.View("index", iris.Map{ // file extension is optional. + "Title": "Title of the main Page", + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + // otherGroup := app.Party("/other").Layout("layouts/other.ace") -> layout for that party. + // otherGroup.Get("/", func(ctx iris.Context) { ctx.View("index.ace", [...]) }) + + app.Listen(":8080") +} diff --git a/view/template_ace_0/views/index.ace b/view/template_ace_0/views/index.ace new file mode 100644 index 00000000..144910f0 --- /dev/null +++ b/view/template_ace_0/views/index.ace @@ -0,0 +1,7 @@ += include partials/header.ace . + +h2 {{.Title}} + +h3 Body + += include partials/footer.ace . \ No newline at end of file diff --git a/view/template_ace_0/views/layouts/main.ace b/view/template_ace_0/views/layouts/main.ace new file mode 100644 index 00000000..7e6e5ff3 --- /dev/null +++ b/view/template_ace_0/views/layouts/main.ace @@ -0,0 +1,7 @@ += doctype html +html + head + title Main Page + body + h1 Layout + {{ yield . }} \ No newline at end of file diff --git a/view/template_ace_0/views/partials/footer.ace b/view/template_ace_0/views/partials/footer.ace new file mode 100644 index 00000000..99261685 --- /dev/null +++ b/view/template_ace_0/views/partials/footer.ace @@ -0,0 +1 @@ +h1 Partial Footer \ No newline at end of file diff --git a/view/template_ace_0/views/partials/header.ace b/view/template_ace_0/views/partials/header.ace new file mode 100644 index 00000000..dca23ac2 --- /dev/null +++ b/view/template_ace_0/views/partials/header.ace @@ -0,0 +1 @@ +h1 Partial Header \ No newline at end of file diff --git a/view/template_blocks_0/main.go b/view/template_blocks_0/main.go new file mode 100644 index 00000000..8171ffb3 --- /dev/null +++ b/view/template_blocks_0/main.go @@ -0,0 +1,41 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + // Read about its syntax at: https://github.com/kataras/blocks + app.RegisterView(iris.Blocks("./views", ".html").Reload(true)) + + app.Get("/", index) + app.Get("/500", internalServerError) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + } + + ctx.ViewLayout("main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func internalServerError(ctx iris.Context) { + ctx.StatusCode(iris.StatusInternalServerError) + + data := iris.Map{ + "Code": iris.StatusInternalServerError, + "Message": "Internal Server Error", + } + + ctx.ViewLayout("error") + if err := ctx.View("500", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/template_blocks_0/views/500.html b/view/template_blocks_0/views/500.html new file mode 100644 index 00000000..bbdd7463 --- /dev/null +++ b/view/template_blocks_0/views/500.html @@ -0,0 +1,7 @@ +{{ define "content" }} +<h1>Internal Server Error</h1> +{{ end }} + +{{ define "message" }} +<p style="color:red;">{{.Message}}</p> +{{ end }} \ No newline at end of file diff --git a/view/template_blocks_0/views/index.html b/view/template_blocks_0/views/index.html new file mode 100644 index 00000000..b11758cf --- /dev/null +++ b/view/template_blocks_0/views/index.html @@ -0,0 +1 @@ +<h1>Index Body</h1> \ No newline at end of file diff --git a/view/template_blocks_0/views/layouts/error.html b/view/template_blocks_0/views/layouts/error.html new file mode 100644 index 00000000..c61972f0 --- /dev/null +++ b/view/template_blocks_0/views/layouts/error.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{.Code}}</title> +</head> +<body> + {{ template "content" . }} + + {{ block "message" . }}Default Error Message{{ end }} +</body> +</html> \ No newline at end of file diff --git a/view/template_blocks_0/views/layouts/main.html b/view/template_blocks_0/views/layouts/main.html new file mode 100644 index 00000000..e2b112b3 --- /dev/null +++ b/view/template_blocks_0/views/layouts/main.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>{{ if .Title }}{{ .Title }}{{ else }}Default Main Title{{ end }}</title> +</head> +<body> + {{ template "content" . }} + +<footer>{{ partial "partials/footer" . }}</footer> +</body> +</html> \ No newline at end of file diff --git a/view/template_blocks_0/views/partials/footer.html b/view/template_blocks_0/views/partials/footer.html new file mode 100644 index 00000000..61ee8461 --- /dev/null +++ b/view/template_blocks_0/views/partials/footer.html @@ -0,0 +1 @@ +<h3>Footer Partial</h3> \ No newline at end of file diff --git a/view/template_blocks_1_embedded/bindata.go b/view/template_blocks_1_embedded/bindata.go new file mode 100644 index 00000000..1d3155a2 --- /dev/null +++ b/view/template_blocks_1_embedded/bindata.go @@ -0,0 +1,429 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// ../template_blocks_0/views/500.html +// ../template_blocks_0/views/index.html +// ../template_blocks_0/views/layouts/error.html +// ../template_blocks_0/views/layouts/main.html +// ../template_blocks_0/views/partials/footer.html +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var __500Html = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x8f\xb1\x4e\xf3\x30\x14\x85\xf7\x48\x79\x87\xfb\x67\xe9\x8f\xd4\xa4\xea\x5a\x42\x37\x06\x06\xa6\x22\x21\x46\xc7\x3e\xad\x2d\x9c\x7b\x23\xdb\x49\x89\xa2\xbc\x3b\x6a\x5a\x04\x2c\xac\xf7\x7e\xe7\x3b\x3a\xf5\xbf\xb2\xa4\x37\xe9\x49\x2b\x26\x83\xa3\x63\x50\x2b\x01\x94\xac\x62\x12\x06\x35\x5e\xf4\x7b\x95\x67\x2f\x16\x17\x40\xf5\x3e\x2d\x77\x17\xa9\xd0\xc2\x09\x9c\x0a\x3a\x5b\xa7\x2d\x45\x2b\xbd\x37\xd4\x5c\xd2\xa0\x56\x39\xa6\x84\xb6\xf3\x2a\x61\x15\xa9\x11\x33\x56\x79\x76\x90\x35\x61\x00\x93\x3b\x92\x4b\xab\x48\xad\x8b\xd1\xf1\x89\xfe\x47\x80\x1c\x1b\x7c\x54\x36\xb5\xfe\x6e\x7d\x7d\x2b\x63\x60\x48\xf5\x49\x5a\x95\x9c\x56\xde\x8f\xd4\x8c\x4b\xc3\xe0\x70\x26\xf0\xc9\x31\xaa\x3c\x7b\xb5\x60\x1a\xa5\x27\x06\x0c\x25\xf9\x63\xce\x7a\xe1\xac\x1a\x70\xe1\x9a\x1b\x13\x3b\x68\x77\x74\x7a\x97\x67\x65\xb9\xcf\xb3\x69\xfa\x52\x7c\x0f\x9d\xe7\x3c\xab\xed\x76\xff\xc4\x09\x81\x95\xa7\x03\xc2\x80\x40\x8f\x21\x48\xa8\x37\x76\x7b\xcd\x81\xcd\x82\xfe\x92\xb4\x88\x51\x9d\x70\x93\x74\x14\xd3\xe8\xf1\x50\x68\xf1\x12\x76\x01\xe6\xbe\xd8\x4f\x53\xf5\x7c\xa5\xe6\xb9\xde\x74\x3f\x65\x9f\x01\x00\x00\xff\xff\xb3\xfa\x91\xbd\xaa\x01\x00\x00") + +func _500HtmlBytes() ([]byte, error) { + return bindataRead( + __500Html, + "500.html", + ) +} + +func _500Html() (*asset, error) { + bytes, err := _500HtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "500.html", size: 426, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _indexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb4\xf3\xcc\x4b\x49\xad\x50\x70\xca\x4f\xa9\xb4\xd1\xcf\x30\xb4\x03\x04\x00\x00\xff\xff\xcc\x4b\x98\x69\x13\x00\x00\x00") + +func indexHtmlBytes() ([]byte, error) { + return bindataRead( + _indexHtml, + "index.html", + ) +} + +func indexHtml() (*asset, error) { + bytes, err := indexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "index.html", size: 19, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _layoutsErrorHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xbf\x4e\xf3\x40\x10\xc4\x7b\x4b\x7e\x87\xfd\xb6\xfe\x6c\x43\x47\x71\xe7\x26\x40\x0b\x45\x28\x28\x37\x77\xa3\xf8\xc4\xfd\x89\xe2\x55\x22\x74\xf2\xbb\xa3\x18\x83\x44\xb5\xda\x99\x9f\x66\x57\x63\xfe\x3d\xbe\xec\xf6\xef\xaf\x4f\x34\x69\x8a\x63\xdb\x98\xdb\xa4\x28\xf9\x68\x19\x99\x57\x05\xe2\xc7\xb6\x21\x22\x32\x09\x2a\xe4\x26\x39\xcf\x50\xcb\x6f\xfb\xe7\xee\x81\xff\x78\x59\x12\x2c\x5f\x02\xae\xa7\x72\x56\x26\x57\xb2\x22\xab\xe5\x6b\xf0\x3a\x59\x8f\x4b\x70\xe8\xd6\xe5\x3f\x85\x1c\x34\x48\xec\x66\x27\x11\xf6\xbe\xbf\xfb\xcd\xd2\xa0\x11\x63\xad\xfd\xae\x78\x2c\x8b\x19\xbe\x85\xb6\x31\xc3\xf6\x8e\x39\x14\xff\xb9\xe1\xb5\x92\x22\x9d\xa2\x28\x88\xb7\x8b\x4c\xfd\xb2\xb4\xcd\x0f\x70\x88\xc5\x7d\x10\x27\xcc\xb3\x1c\xb1\x9a\xb5\x22\xfb\x1b\x63\x86\x2d\xcb\x0c\x6b\x0b\x5f\x01\x00\x00\xff\xff\xbe\xb7\x11\x67\x15\x01\x00\x00") + +func layoutsErrorHtmlBytes() ([]byte, error) { + return bindataRead( + _layoutsErrorHtml, + "layouts/error.html", + ) +} + +func layoutsErrorHtml() (*asset, error) { + bytes, err := layoutsErrorHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layouts/error.html", size: 277, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _layoutsMainHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x54\x90\xb1\x4e\xf4\x30\x10\x84\xfb\x48\x79\x87\xf9\x5d\xff\x49\xa0\xa3\xb0\xd3\x70\xd0\x21\x28\x42\x41\xb9\x24\x1b\x62\xc9\x71\xa2\x64\xb9\x13\xb2\xfc\xee\xc8\x39\x0b\xe9\x2a\xcf\xfa\xb3\x66\xc6\xab\xff\x9d\x5e\x1f\xbb\x8f\xb7\x27\x4c\x32\xbb\xb6\x2c\x74\x3a\xe1\xc8\x7f\x19\xc5\x5e\x1d\x37\x4c\x43\x5b\x16\x00\xa0\x67\x16\x42\x3f\xd1\xb6\xb3\x18\xf5\xde\x3d\x57\x0f\xea\x86\x79\x9a\xd9\xa8\xb3\xe5\xcb\xba\x6c\xa2\xd0\x2f\x5e\xd8\x8b\x51\x17\x3b\xc8\x64\x06\x3e\xdb\x9e\xab\x63\xf8\x0f\xeb\xad\x58\x72\xd5\xde\x93\x63\x73\x5f\xdf\xfd\x79\x89\x15\xc7\x6d\x08\xb0\x23\xea\x2e\x0d\x88\x31\x84\x1b\xcd\x6e\x4f\xea\xc4\x23\x7d\x3b\xc1\x0b\x59\x8f\x03\x27\xe6\x07\xc4\xa8\x9b\xab\x4f\x59\xe8\x26\xff\x42\x7f\x2e\xc3\x4f\x4e\x09\x01\xc2\xf3\xea\x48\x18\x2a\x17\x55\xa8\x11\x63\x59\x94\x85\x1e\x97\x45\x78\x4b\x25\x56\xda\x52\x4f\xa8\x2c\xf6\xe6\xca\x14\xea\x14\x92\x1f\xa6\x94\xec\xae\x9b\x63\x9d\xbf\x01\x00\x00\xff\xff\x44\x95\x63\x98\x5e\x01\x00\x00") + +func layoutsMainHtmlBytes() ([]byte, error) { + return bindataRead( + _layoutsMainHtml, + "layouts/main.html", + ) +} + +func layoutsMainHtml() (*asset, error) { + bytes, err := layoutsMainHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layouts/main.html", size: 350, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _partialsFooterHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\xc9\x30\xb6\x73\xcb\xcf\x2f\x49\x2d\x52\x08\x48\x2c\x2a\xc9\x4c\xcc\xb1\xd1\xcf\x30\xb6\x03\x04\x00\x00\xff\xff\x08\xe6\xe9\xf8\x17\x00\x00\x00") + +func partialsFooterHtmlBytes() ([]byte, error) { + return bindataRead( + _partialsFooterHtml, + "partials/footer.html", + ) +} + +func partialsFooterHtml() (*asset, error) { + bytes, err := partialsFooterHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "partials/footer.html", size: 23, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "500.html": _500Html, + "index.html": indexHtml, + "layouts/error.html": layoutsErrorHtml, + "layouts/main.html": layoutsMainHtml, + "partials/footer.html": partialsFooterHtml, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "500.html": {_500Html, map[string]*bintree{}}, + "index.html": {indexHtml, map[string]*bintree{}}, + "layouts": {nil, map[string]*bintree{ + "error.html": {layoutsErrorHtml, map[string]*bintree{}}, + "main.html": {layoutsMainHtml, map[string]*bintree{}}, + }}, + "partials": {nil, map[string]*bintree{ + "footer.html": {partialsFooterHtml, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) +} diff --git a/view/template_blocks_1_embedded/main.go b/view/template_blocks_1_embedded/main.go new file mode 100644 index 00000000..f036cc81 --- /dev/null +++ b/view/template_blocks_1_embedded/main.go @@ -0,0 +1,50 @@ +package main + +import "github.com/kataras/iris/v12" + +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// +// $ go-bindata -fs -prefix "../template_blocks_0/views" ../template_blocks_0/views/... +// $ go run . +// +// # OR: go-bindata -fs -prefix "views" ./views/... if the views dir is rel to the executable. +// # OR: go-bindata -fs -prefix "../template_blocks_0" ../template_blocks_0/views/... +// # with iris.Blocks(AssetFile()).RootDir("/views") +// +// System files are not used, you can optionally delete the folder and run the example now. +func main() { + app := iris.New() + app.RegisterView(iris.Blocks(AssetFile(), ".html")) + + app.Get("/", index) + app.Get("/500", internalServerError) + + app.Listen(":8080") +} + +func index(ctx iris.Context) { + data := iris.Map{ + "Title": "Page Title", + } + + ctx.ViewLayout("main") + if err := ctx.View("index", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +func internalServerError(ctx iris.Context) { + ctx.StatusCode(iris.StatusInternalServerError) + + data := iris.Map{ + "Code": iris.StatusInternalServerError, + "Message": "Internal Server Error", + } + + ctx.ViewLayout("error") + if err := ctx.View("500", data); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/template_blocks_2/main.go b/view/template_blocks_2/main.go new file mode 100644 index 00000000..d494961f --- /dev/null +++ b/view/template_blocks_2/main.go @@ -0,0 +1,38 @@ +package main + +import "github.com/kataras/iris/v12" + +// Based on https://github.com/kataras/iris/issues/2214. +func main() { + app := initApp() + app.Listen(":8080") +} + +func initApp() *iris.Application { + app := iris.New() + app.Logger().SetLevel("debug") + + tmpl := iris.Blocks("./src/public/html", ".html") + tmpl.Layout("main") + app.RegisterView(tmpl) + + app.Get("/list", func(ctx iris.Context) { + ctx.View("files/list") + }) + + app.Get("/menu", func(ctx iris.Context) { + ctx.View("menu/menu") + }) + + app.Get("/list2", func(ctx iris.Context) { + ctx.ViewLayout("secondary") + ctx.View("files/list") + }) + + app.Get("/menu2", func(ctx iris.Context) { + ctx.ViewLayout("secondary") + ctx.View("menu/menu") + }) + + return app +} diff --git a/view/template_blocks_2/src/public/html/files/list.html b/view/template_blocks_2/src/public/html/files/list.html new file mode 100644 index 00000000..b2bf68b9 --- /dev/null +++ b/view/template_blocks_2/src/public/html/files/list.html @@ -0,0 +1,7 @@ +{{ define "title"}} + <title>222</title> +{{ end }} + +{{ define "content" }} +<h1>List Content</h1> +{{ end }} \ No newline at end of file diff --git a/view/template_blocks_2/src/public/html/layouts/main.html b/view/template_blocks_2/src/public/html/layouts/main.html new file mode 100644 index 00000000..22501f28 --- /dev/null +++ b/view/template_blocks_2/src/public/html/layouts/main.html @@ -0,0 +1,8 @@ +<html> +<head> + {{ block "title" .}}<title>Main Default Title</title>{{end}} +</head> +<body> + {{ block "content" .}}<h1>Main Default Content</h1>{{end}} +</body> +</html> \ No newline at end of file diff --git a/view/template_blocks_2/src/public/html/layouts/secondary.html b/view/template_blocks_2/src/public/html/layouts/secondary.html new file mode 100644 index 00000000..0bfda42d --- /dev/null +++ b/view/template_blocks_2/src/public/html/layouts/secondary.html @@ -0,0 +1,9 @@ +<html> +<head> + {{ block "title" .}}<title>Secondary Default Title</title>{{end}} +</head> +<body> + <h1>Secondary Layout</h1> + {{ block "content" .}}<h1>Secondary Default Content</h1>{{end}} +</body> +</html> \ No newline at end of file diff --git a/view/template_blocks_2/src/public/html/menu/menu.html b/view/template_blocks_2/src/public/html/menu/menu.html new file mode 100644 index 00000000..a9880027 --- /dev/null +++ b/view/template_blocks_2/src/public/html/menu/menu.html @@ -0,0 +1,3 @@ +{{ define "title" }} <title>111</title>{{ end }} + +{{ define "content" }}<h1>Menu Content</h1>{{ end }} \ No newline at end of file diff --git a/view/template_django_0/main.go b/view/template_django_0/main.go new file mode 100644 index 00000000..91104bbe --- /dev/null +++ b/view/template_django_0/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "time" + + "github.com/kataras/iris/v12" + // optionally, register filters like `timesince`. + _ "github.com/iris-contrib/pongo2-addons/v4" +) + +var startTime = time.Now() + +func main() { + app := iris.New() + + tmpl := iris.Django("./templates", ".html") + tmpl.Reload(true) // reload templates on each request (development mode) + tmpl.AddFunc("greet", func(s string) string { // {{greet(name)}} + return "Greetings " + s + "!" + }) + + // tmpl.RegisterFilter("myFilter", myFilter) // {{"simple input for filter"|myFilter}} + app.RegisterView(tmpl) + + app.Get("/", hi) + + // http://localhost:8080 + app.Listen(":8080") +} + +func hi(ctx iris.Context) { + // ctx.ViewData("title", "Hi Page") + // ctx.ViewData("name", "iris") + // ctx.ViewData("serverStartTime", startTime) + // or if you set all view data in the same handler you can use the + // iris.Map/pongo2.Context/map[string]interface{}, look below: + + if err := ctx.View("hi.html", iris.Map{ + "title": "Hi Page", + "name": "iris", + "serverStartTime": startTime, + }); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/template_django_0/templates/hi.html b/view/template_django_0/templates/hi.html new file mode 100644 index 00000000..945782e4 --- /dev/null +++ b/view/template_django_0/templates/hi.html @@ -0,0 +1,12 @@ +<html> +<head> +<title>{{title}}</title> +</head> +<body> + <h1>Hi {{name|capfirst}} </h1> + + <h2>{{greet(name)}}</h2> + + <h3>Server started about {{serverStartTime|timesince}}. Refresh the page to see different result</h3> +</body> +</html> diff --git a/view/template_django_1/main.go b/view/template_django_1/main.go new file mode 100644 index 00000000..cb816352 --- /dev/null +++ b/view/template_django_1/main.go @@ -0,0 +1,64 @@ +package main + +import "github.com/kataras/iris/v12" + +func main() { + app := iris.New() + app.RegisterView(iris.Django("./views", ".html").Reload(true)) + + mypathRoute := app.Get("/mypath", writePathHandler) + mypathRoute.Name = "my-page1" + + mypath2Route := app.Get("/mypath2/{paramfirst}/{paramsecond}", writePathHandler) + mypath2Route.Name = "my-page2" + + mypath3Route := app.Get("/mypath3/{paramfirst}/statichere/{paramsecond}", writePathHandler) + mypath3Route.Name = "my-page3" + + mypath4Route := app.Get("/mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}", writePathHandler) + // same as: app.Get("/mypath4/:paramfirst/statichere/:paramsecond/:otherparam/*something", writePathHandler) + mypath4Route.Name = "my-page4" + + // same with Handle/Func + mypath5Route := app.Handle("GET", "/mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{something:path}", writePathHandler) + mypath5Route.Name = "my-page5" + + mypath6Route := app.Get("/mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic}", writePathHandler) + mypath6Route.Name = "my-page6" + + app.Get("/", func(ctx iris.Context) { + // for /mypath6... + paramsAsArray := []string{"theParam1", "theParam2", "paramThirdAfterStatic"} + ctx.ViewData("ParamsAsArray", paramsAsArray) + if err := ctx.View("page.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Get("/redirect/{namedRoute}", func(ctx iris.Context) { + routeName := ctx.Params().Get("namedRoute") + r := app.GetRoute(routeName) + if r == nil { + ctx.StatusCode(404) + ctx.Writef("Route with name %s not found", routeName) + return + } + + println("The path of " + routeName + "is: " + r.Path) + // if routeName == "my-page1" + // prints: The path of of my-page1 is: /mypath + // if it's a path which takes named parameters + // then use "r.ResolvePath(paramValuesHere)" + ctx.Redirect(r.Path) + // http://localhost:8080/redirect/my-page1 will redirect to -> http://localhost:8080/mypath + }) + + // http://localhost:8080 + // http://localhost:8080/redirect/my-page1 + app.Listen(":8080") +} + +func writePathHandler(ctx iris.Context) { + ctx.Writef("Hello from %s.", ctx.Path()) +} diff --git a/view/template_django_1/views/page.html b/view/template_django_1/views/page.html new file mode 100644 index 00000000..6ea673ca --- /dev/null +++ b/view/template_django_1/views/page.html @@ -0,0 +1,55 @@ +<html> + +<head> + <title>urlpath function - django</title> + <style> + a { + color: #0f7afc; + border-bottom-color: rgba(15, 122, 252, 0.2); + text-decoration: none + } + + a:hover { + color: #cf0000; + border-bottom-color: rgba(208, 64, 0, 0.2); + text-decoration: none + } + + a:visited { + color: #800080; + border-bottom-color: rgba(128, 0, 128, 0.2); + text-decoration: none + } + </style> +</head> + +<body> + + <a href="{{urlpath('my-page1')}}">/mypath</a> + <br /> + <br /> + + <a href="{{urlpath('my-page2','theParam1','theParam2')}}">/mypath2/{paramfirst}/{paramsecond}</a> + <br /> + <br /> + + <a href="{{urlpath('my-page3','theParam1','theParam2AfterStatic')}}">/mypath3/{paramfirst}/statichere/{paramsecond}</a> + <br /> + <br /> + + <a href="{{urlpath('my-page4','theParam1','theparam2AfterStatic','otherParam','matchAnything')}}"> + /mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}</a> + <br /> + <br /> + + <a href="{{urlpath('my-page5','theParam1','theParam2Afterstatichere','otherParam','matchAnythingAfterStatic')}}"> + /mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{anything:path}</a> + <br /> + <br /> + + <a href="{{urlpath('my-page6', ParamsAsArray)}}"> + /mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic} + </a> +</body> + +</html> \ No newline at end of file diff --git a/view/template_handlebars_0/main.go b/view/template_handlebars_0/main.go new file mode 100644 index 00000000..dac5417d --- /dev/null +++ b/view/template_handlebars_0/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/mvc" +) + +func main() { + app := iris.New() + app.Logger().SetLevel("debug") + + // Init the handlebars engine + e := iris.Handlebars("./templates", ".html").Reload(true) + // Register a helper. + e.AddFunc("fullName", func(person map[string]string) string { + return person["firstName"] + " " + person["lastName"] + }) + + app.RegisterView(e) + + app.Get("/", func(ctx iris.Context) { + viewData := iris.Map{ + "author": map[string]string{"firstName": "Jean", "lastName": "Valjean"}, + "body": "Life is difficult", + "comments": []iris.Map{{ + "author": map[string]string{"firstName": "Marcel", "lastName": "Beliveau"}, + "body": "LOL!", + }}, + } + + if err := ctx.View("example.html", viewData); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + exampleRouter := app.Party("/example") + /* See context-view-data example: Set data through one or more middleware */ + exampleRouter.Use(func(ctx iris.Context) { + ctx.ViewData("author", map[string]string{"firstName": "Jean", "lastName": "Valjean"}) + ctx.ViewData("body", "Life is difficult") + ctx.ViewData("comments", []iris.Map{{ + "author": map[string]string{"firstName": "Marcel", "lastName": "Beliveau"}, + "body": "LOL!", + }}) + + // OR: + // ctx.ViewData("", iris.Map{ + // "author": map[string]string{"firstName": "Jean", "lastName": "Valjean"}, + // "body": "Life is difficult", + // "comments": []iris.Map{{ + // "author": map[string]string{"firstName": "Marcel", "lastName": "Beliveau"}, + // "body": "LOL!", + // }}, + // }) + + ctx.Next() + }) + + mvc.New(exampleRouter).Handle(new(controller)) + + // Read more about its syntax at: + // https://github.com/mailgun/raymond and + // https://handlebarsjs.com/guide + + // http://localhost:8080 + // http://localhost:8080/example + app.Listen(":8080") +} + +type controller struct{} + +func (c *controller) Get() mvc.Result { + return mvc.View{ + Name: "example", + Code: 200, + } +} diff --git a/view/template_handlebars_0/templates/example.html b/view/template_handlebars_0/templates/example.html new file mode 100644 index 00000000..353de651 --- /dev/null +++ b/view/template_handlebars_0/templates/example.html @@ -0,0 +1,27 @@ +<div class="post"> + <h1>By {{fullName author}}</h1> + <div class="body">{{body}}</div> + + <h1>Comments</h1> + + {{#each comments}} + <h2>By {{fullName author}}</h2> + <div class="body">{{body}}</div> + {{/each}} + + + <!-- <h1>Struct example</h1> + {{#with myStruct}} + {{ this }} + OR + {{ FieldMame }} + {{/with}} --> + + <hr /> + + <strong>Read more at: <a href="https://github.com/mailgun/raymond" target="_new"> + https://github.com/mailgun/raymond</a> and <a href="https://handlebarsjs.com/guide" target="_new"> + https://handlebarsjs.com/guide + </a> + </strong> +</div> \ No newline at end of file diff --git a/view/template_html_0/main.go b/view/template_html_0/main.go index efc997f0..687adfb7 100644 --- a/view/template_html_0/main.go +++ b/view/template_html_0/main.go @@ -1,27 +1,21 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { app := iris.New() // defaults to these - // - standard html | iris.HTML(...) - // - django | iris.Django(...) - // - pug(jade) | iris.Pug(...) - // - handlebars | iris.Handlebars(...) - // - amber | iris.Amber(...) - tmpl := iris.HTML("./templates", ".html") tmpl.Reload(true) // reload templates on each request (development mode) // default template funcs are: // // - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }} - // - {{ render "header.html" }} - // - {{ render_r "header.html" }} // partial relative path to current page - // - {{ yield }} - // - {{ current }} + // - {{ render "header.html" . }} + // - {{ render_r "header.html" . }} // partial relative path to current page + // - {{ yield . }} + // - {{ current . }} tmpl.AddFunc("greet", func(s string) string { return "Greetings " + s + "!" }) @@ -30,25 +24,15 @@ func main() { app.Get("/", hi) // http://localhost:8080 - app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8")) // defaults to that but you can change it. + app.Listen(":8080", iris.WithCharset("utf-8")) // defaults to that but you can change it. } func hi(ctx iris.Context) { ctx.ViewData("Title", "Hi Page") ctx.ViewData("Name", "iris") // {{.Name}} will render: iris // ctx.ViewData("", myCcustomStruct{}) - ctx.View("hi.html") + if err := ctx.View("hi.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } - -/* -Note: - -In case you're wondering, the code behind the view engines derives from the "github.com/kataras/iris/view" package, -access to the engines' variables can be granded by "github.com/kataras/iris" package too. - - iris.HTML(...) is a shortcut of view.HTML(...) - iris.Django(...) >> >> view.Django(...) - iris.Pug(...) >> >> view.Pug(...) - iris.Handlebars(...) >> >> view.Handlebars(...) - iris.Amber(...) >> >> view.Amber(...) -*/ diff --git a/view/template_html_1/main.go b/view/template_html_1/main.go index 81bf5b5f..26d2e9a5 100644 --- a/view/template_html_1/main.go +++ b/view/template_html_1/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) type mypage struct { @@ -16,14 +16,17 @@ func main() { // TIP: append .Reload(true) to reload the templates on each request. app.Get("/", func(ctx iris.Context) { - ctx.Gzip(true) + ctx.CompressWriter(true) ctx.ViewData("", mypage{"My Page title", "Hello world!"}) - ctx.View("mypage.html") + if err := ctx.View("mypage.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } // Note that: you can pass "layout" : "otherLayout.html" to bypass the config's Layout property // or view.NoLayout to disable layout on this render action. // third is an optional parameter }) // http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/view/template_html_1/templates/layout.html b/view/template_html_1/templates/layout.html index 3f6b65a6..588c57bb 100644 --- a/view/template_html_1/templates/layout.html +++ b/view/template_html_1/templates/layout.html @@ -6,6 +6,6 @@ <body> <h1>[layout] Body content is below...</h1> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/template_html_2/README.md b/view/template_html_2/README.md index da4c76a1..5e978ff3 100644 --- a/view/template_html_2/README.md +++ b/view/template_html_2/README.md @@ -1,3 +1,3 @@ ## Info -This folder examines the {{render "dir/templatefilename"}} functionality to manually render any template inside any template +This folder examines the {{render "dir/templatefilename" .}} functionality to manually render any template inside any template diff --git a/view/template_html_2/main.go b/view/template_html_2/main.go index 9418bd16..6e864223 100644 --- a/view/template_html_2/main.go +++ b/view/template_html_2/main.go @@ -1,7 +1,7 @@ package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -35,10 +35,16 @@ func main() { my := app.Party("/my").Layout("layouts/mylayout.html") { // both of these will use the layouts/mylayout.html as their layout. my.Get("/", func(ctx iris.Context) { - ctx.View("page1.html") + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) my.Get("/other", func(ctx iris.Context) { - ctx.View("page1.html") + if err := ctx.View("page1.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) } @@ -46,5 +52,5 @@ func main() { // http://localhost:8080/nolayout // http://localhost:8080/my // http://localhost:8080/my/other - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/view/template_html_2/templates/layouts/layout.html b/view/template_html_2/templates/layouts/layout.html index 69b545ec..929a31cd 100644 --- a/view/template_html_2/templates/layouts/layout.html +++ b/view/template_html_2/templates/layouts/layout.html @@ -7,6 +7,6 @@ <h1>This is the global layout</h1> <br /> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/template_html_2/templates/layouts/mylayout.html b/view/template_html_2/templates/layouts/mylayout.html index d22426fe..4cbced18 100644 --- a/view/template_html_2/templates/layouts/mylayout.html +++ b/view/template_html_2/templates/layouts/mylayout.html @@ -7,6 +7,6 @@ <h1>This is the layout for the /my/ and /my/other routes only</h1> <br /> <!-- Render the current template here --> - {{ yield }} + {{ yield . }} </body> </html> diff --git a/view/template_html_2/templates/page1.html b/view/template_html_2/templates/page1.html index 6f63f7b3..03659b45 100644 --- a/view/template_html_2/templates/page1.html +++ b/view/template_html_2/templates/page1.html @@ -2,6 +2,6 @@ <h1>Page 1 {{ greet "iris developer"}}</h1> - {{ render "partials/page1_partial1.html"}} + {{ render "partials/page1_partial1.html" . }} </div> diff --git a/view/template_html_3/main.go b/view/template_html_3/main.go index 82b192f3..91cc7e75 100644 --- a/view/template_html_3/main.go +++ b/view/template_html_3/main.go @@ -1,8 +1,9 @@ -// Package main an example on how to naming your routes & use the custom 'url path' HTML Template Engine, same for other template engines. +// Package main an example on how to naming your routes & use the custom +// 'url path' HTML Template Engine, same for other template engines. package main import ( - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) func main() { @@ -34,7 +35,8 @@ func main() { paramsAsArray := []string{"theParam1", "theParam2", "paramThirdAfterStatic"} ctx.ViewData("ParamsAsArray", paramsAsArray) if err := ctx.View("page.html"); err != nil { - panic(err) + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -58,8 +60,7 @@ func main() { // http://localhost:8080 // http://localhost:8080/redirect/my-page1 - app.Run(iris.Addr(":8080")) - + app.Listen(":8080") } func writePathHandler(ctx iris.Context) { diff --git a/view/template_html_3/templates/page.html b/view/template_html_3/templates/page.html index 7e568511..379f7714 100644 --- a/view/template_html_3/templates/page.html +++ b/view/template_html_3/templates/page.html @@ -1,25 +1,55 @@ -<a href="{{urlpath "my-page1"}}">/mypath</a> -<br /> -<br /> - -<a href="{{urlpath "my-page2" "theParam1" "theParam2"}}">/mypath2/{paramfirst}/{paramsecond}</a> -<br /> -<br /> - -<a href="{{urlpath "my-page3" "theParam1" "theParam2AfterStatic"}}">/mypath3/{paramfirst}/statichere/{paramsecond}</a> -<br /> -<br /> - -<a href="{{urlpath "my-page4" "theParam1" "theparam2AfterStatic" "otherParam" "matchAnything"}}"> - /mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}</a> -<br /> -<br /> - -<a href="{{urlpath "my-page5" "theParam1" "theParam2Afterstatichere" "otherParam" "matchAnythingAfterStatic"}}"> - /mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{anything:path}</a> -<br /> -<br /> - -<a href={{urlpath "my-page6" .ParamsAsArray }}> - /mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic} -</a> +<html> + +<head> + <title>template_html_3</title> + <style> + a { + color: #0f7afc; + border-bottom-color: rgba(15, 122, 252, 0.2); + text-decoration: none + } + + a:hover { + color: #cf0000; + border-bottom-color: rgba(208, 64, 0, 0.2); + text-decoration: none + } + + a:visited { + color: #800080; + border-bottom-color: rgba(128, 0, 128, 0.2); + text-decoration: none + } + </style> +</head> + +<body> + + <a href="{{urlpath "my-page1"}}">/mypath</a> + <br /> + <br /> + + <a href="{{urlpath "my-page2" "theParam1" "theParam2"}}">/mypath2/{paramfirst}/{paramsecond}</a> + <br /> + <br /> + + <a href="{{urlpath "my-page3" "theParam1" "theParam2AfterStatic"}}">/mypath3/{paramfirst}/statichere/{paramsecond}</a> + <br /> + <br /> + + <a href="{{urlpath "my-page4" "theParam1" "theparam2AfterStatic" "otherParam" "matchAnything"}}"> + /mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}</a> + <br /> + <br /> + + <a href="{{urlpath "my-page5" "theParam1" "theParam2Afterstatichere" "otherParam" "matchAnythingAfterStatic"}}"> + /mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{anything:path}</a> + <br /> + <br /> + + <a href={{urlpath "my-page6" .ParamsAsArray }}> + /mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic} + </a> +</body> + +</html> \ No newline at end of file diff --git a/view/template_html_4/main.go b/view/template_html_4/main.go index 4484adf8..6a0ea14e 100644 --- a/view/template_html_4/main.go +++ b/view/template_html_4/main.go @@ -2,8 +2,8 @@ package main import ( - "github.com/kataras/iris" - "github.com/kataras/iris/core/router" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/core/router" ) const ( @@ -27,7 +27,7 @@ func main() { // wildcard subdomain, will catch username1.... username2.... username3... username4.... username5... // that our below links are providing via page.html's first argument which is the subdomain. - subdomain := app.Party("*.") + subdomain := app.WildcardSubdomain() mypathRoute := subdomain.Get("/mypath", emptyHandler) mypathRoute.Name = "my-page1" @@ -52,7 +52,8 @@ func main() { paramsAsArray := []string{"username5", "theParam1", "theParam2", "paramThirdAfterStatic"} ctx.ViewData("ParamsAsArray", paramsAsArray) if err := ctx.View("page.html"); err != nil { - panic(err) + ctx.HTML("<h3>%s</h3>", err.Error()) + return } }) @@ -63,7 +64,7 @@ func main() { app.Get("/mypath7/{paramfirst}/{paramsecond}/static/{paramthird}", emptyHandler).Name = "my-page7" // http://127.0.0.1:8080 - app.Run(iris.Addr(host)) + app.Listen(host) } func emptyHandler(ctx iris.Context) { diff --git a/view/template_html_5/main.go b/view/template_html_5/main.go new file mode 100644 index 00000000..3727c07d --- /dev/null +++ b/view/template_html_5/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + + app.RegisterView(iris.HTML("./views", ".html").Layout("layout.html")) + // TIP: append .Reload(true) to reload the templates on each request. + + app.Get("/home", func(ctx iris.Context) { + ctx.ViewData("title", "Home page") + if err := ctx.View("home.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + + // Note that: you can pass "layout" : "otherLayout.html" to bypass the config's Layout property + // or view.NoLayout to disable layout on this render action. + // third is an optional parameter + }) + + app.Get("/about", func(ctx iris.Context) { + if err := ctx.View("about.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Get("/user/index", func(ctx iris.Context) { + if err := ctx.View("user/index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + // http://localhost:8080 + app.Listen(":8080") +} diff --git a/view/template_html_5/views/about.html b/view/template_html_5/views/about.html new file mode 100644 index 00000000..a2642992 --- /dev/null +++ b/view/template_html_5/views/about.html @@ -0,0 +1,15 @@ +{{ define "about-head"}} + <title>about page</title> + <style type="text/css"> + body { + background: #666; + } + </style> +{{ end }} + +{{ define "about-body"}} + extend body content in layout. +{{ end }} +<div> + Hello about page +</div> \ No newline at end of file diff --git a/view/template_html_5/views/home.html b/view/template_html_5/views/home.html new file mode 100644 index 00000000..36599009 --- /dev/null +++ b/view/template_html_5/views/home.html @@ -0,0 +1,11 @@ +{{ define "home-head"}} + <title>{{.title}}</title> + <style type="text/css"> + body { + background: #999; + } + </style> +{{ end }} +<div> + Hello home page +</div> \ No newline at end of file diff --git a/view/template_html_5/views/layout.html b/view/template_html_5/views/layout.html new file mode 100644 index 00000000..6fbb4c89 --- /dev/null +++ b/view/template_html_5/views/layout.html @@ -0,0 +1,11 @@ +<html> +<head> +{{ part "head"}} +</head> +<body> + <h1>[layout] Body content is below...</h1> + {{ part "body" . }} + <!-- Render the current template here --> + {{ yield . }} +</body> +</html> diff --git a/view/template_html_5/views/user/index.html b/view/template_html_5/views/user/index.html new file mode 100644 index 00000000..6c73fb2e --- /dev/null +++ b/view/template_html_5/views/user/index.html @@ -0,0 +1,10 @@ +{{ define "user/index-head"}} +<style type="text/css"> + body { + background: red; + } +</style> +{{ end }} +<div> + Hello user index page +</div> \ No newline at end of file diff --git a/view/template_jet_0/README.md b/view/template_jet_0/README.md new file mode 100644 index 00000000..627e5b3e --- /dev/null +++ b/view/template_jet_0/README.md @@ -0,0 +1,10 @@ +# Jet Engine Example + +This example is a fork of <https://github.com/CloudyKit/jet/tree/master/examples/todos> to work with Iris, so you can notice the differences side by side. + +Read more at: https://github.com/CloudyKit/jet/blob/master/docs/syntax.md + +> The Iris Jet View Engine fixes some bugs that the underline [jet template parser](https://github.com/CloudyKit/jet) currently has. + + +Continue by learning how you can [serve embedded templates](../template_jet_1_embedded). \ No newline at end of file diff --git a/view/template_jet_0/main.go b/view/template_jet_0/main.go new file mode 100644 index 00000000..272b9a1e --- /dev/null +++ b/view/template_jet_0/main.go @@ -0,0 +1,152 @@ +// Package main shows how to use jet template parser with ease using the Iris built-in Jet view engine. +// This example is customized fork of https://github.com/CloudyKit/jet/tree/master/examples/todos, so you can +// notice the differences side by side. +package main + +import ( + "bytes" + "encoding/base64" + "fmt" + "os" + "reflect" + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/view" +) + +type tTODO struct { + Text string + Done bool +} + +type doneTODOs struct { + list map[string]*tTODO + keys []string + len int + i int +} + +func (dt *doneTODOs) New(todos map[string]*tTODO) *doneTODOs { + dt.len = len(todos) + for k := range todos { + dt.keys = append(dt.keys, k) + } + dt.list = todos + return dt +} + +// Range satisfies the jet.Ranger interface and only returns TODOs that are done, +// even when the list contains TODOs that are not done. +func (dt *doneTODOs) Range() (reflect.Value, reflect.Value, bool) { + for dt.i < dt.len { + key := dt.keys[dt.i] + dt.i++ + if dt.list[key].Done { + return reflect.ValueOf(key), reflect.ValueOf(dt.list[key]), false + } + } + return reflect.Value{}, reflect.Value{}, true +} + +// Note: jet version 4 requires this. +func (dt *doneTODOs) ProvidesIndex() bool { return true } + +func (dt *doneTODOs) Render(r *view.JetRuntime) { + r.Write([]byte("custom renderer")) +} + +// Render implements jet.Renderer interface +func (t *tTODO) Render(r *view.JetRuntime) { + done := "yes" + if !t.Done { + done = "no" + } + r.Write([]byte(fmt.Sprintf("TODO: %s (done: %s)", t.Text, done))) +} + +func main() { + // + // Type aliases: + // view.JetRuntimeVars = jet.VarMap + // view.JetRuntime = jet.Runtime + // view.JetArguments = jet.Arguments + // + // Iris also gives you the ability to put runtime variables + // from middlewares as well, by: + // view.AddJetRuntimeVars(ctx, vars) + // or tmpl.AddRuntimeVars(ctx, vars) + app := iris.New() + tmpl := iris.Jet("./views", ".jet") // <-- + tmpl.Reload(true) // remove in production. + tmpl.AddFunc("base64", func(a view.JetArguments) reflect.Value { + a.RequireNumOfArguments("base64", 1, 1) + + buffer := bytes.NewBuffer(nil) + fmt.Fprint(buffer, a.Get(0)) + + return reflect.ValueOf(base64.URLEncoding.EncodeToString(buffer.Bytes())) + }) + app.RegisterView(tmpl) // <-- + + todos := map[string]*tTODO{ + "example-todo-1": {Text: "Add an show todo page to the example project", Done: true}, + "example-todo-2": {Text: "Add an add todo page to the example project"}, + "example-todo-3": {Text: "Add an update todo page to the example project"}, + "example-todo-4": {Text: "Add an delete todo page to the example project", Done: true}, + } + + app.Get("/", func(ctx iris.Context) { + err := ctx.View("todos/index.jet", todos) // <-- + // Note that the `ctx.View` already logs the error if logger level is allowing it and returns the error. + if err != nil { + ctx.StopWithText(iris.StatusInternalServerError, "Templates not rendered!") + } + }) + + app.Get("/todo", func(ctx iris.Context) { + id := ctx.URLParam("id") + todo, ok := todos[id] + if !ok { + ctx.Redirect("/") + return + } + + ctx.ViewData("title", "Show TODO") + if err := ctx.View("todos/show.jet", todo); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + app.Get("/all-done", func(ctx iris.Context) { + // vars := make(view.JetRuntimeVars) + // vars.Set("showingAllDone", true) + // vars.Set("title", "Todos - All Done") + // view.AddJetRuntimeVars(ctx, vars) + // ctx.View("todos/index.jet", (&doneTODOs{}).New(todos)) + // + // OR + ctx.ViewData("showingAllDone", true) + ctx.ViewData("title", "Todos - All Done") + + // Use ctx.ViewData("_jet", jetData) + // if using as middleware and you want + // to pre-set the value or even change it later on from another next middleware. + // ctx.ViewData("_jet", (&doneTODOs{}).New(todos)) + // and ctx.View("todos/index.jet") + // OR + if err := ctx.View("todos/index.jet", (&doneTODOs{}).New(todos)); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + port := os.Getenv("PORT") + if len(port) == 0 { + port = ":8080" + } else if !strings.HasPrefix(":", port) { + port = ":" + port + } + + app.Listen(port) +} diff --git a/view/template_jet_0/views/layouts/application.jet b/view/template_jet_0/views/layouts/application.jet new file mode 100644 index 00000000..d8945a34 --- /dev/null +++ b/view/template_jet_0/views/layouts/application.jet @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title>{{ isset(title) ? title : "Default" }}</title> + </head> + <body> + {{block documentBody()}}{{end}} + </body> +</html> diff --git a/view/template_jet_0/views/todos/index.jet b/view/template_jet_0/views/todos/index.jet new file mode 100644 index 00000000..5b700e28 --- /dev/null +++ b/view/template_jet_0/views/todos/index.jet @@ -0,0 +1,30 @@ +{{extends "../layouts/application.jet"}} + +{{block button(label, href="javascript:void(0)")}} + <a href="{{ href }}">{{ label }}</a> +{{end}} + +{{block ul()}} + <ul> + {{yield content}} + </ul> +{{end}} + +{{block documentBody()}} + <h1>List of TODOs</h1> + + {{if isset(showingAllDone) && showingAllDone}} + <p>Showing only TODOs that are done</p> + {{else}} + <p><a href="/all-done">Show only TODOs that are done</a></p> + {{end}} + + {{yield ul() content}} + {{range id, value := .}} + <li {{if value.Done}}style="color:red;text-decoration: line-through;"{{end}}> + <a href="/todo?id={{ id }}">{{ value.Text }}</a> + {{yield button(label="UP", href="/update/?id="+base64(id))}} - {{yield button(href="/delete/?id="+id, label="DL")}} + </li> + {{end}} + {{end}} +{{end}} diff --git a/view/template_jet_0/views/todos/show.jet b/view/template_jet_0/views/todos/show.jet new file mode 100644 index 00000000..cc37722e --- /dev/null +++ b/view/template_jet_0/views/todos/show.jet @@ -0,0 +1,9 @@ +{{extends "../layouts/application.jet"}} + +{{block documentBody()}} + <h1>Show TODO</h1> + <p>This uses a custom renderer by implementing the Renderer interface. + <p> + {{.}} + </p> +{{end}} diff --git a/view/template_jet_1_embedded/bindata.go b/view/template_jet_1_embedded/bindata.go new file mode 100644 index 00000000..b80211e4 --- /dev/null +++ b/view/template_jet_1_embedded/bindata.go @@ -0,0 +1,406 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// views/includes/_partial.jet +// views/includes/blocks.jet +// views/index.jet +// views/layouts/application.jet +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _includes_partialJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb2\x29\xb0\xf3\xcc\x4b\xce\x29\x4d\x49\x4d\x51\x28\x48\x2c\x2a\xc9\x4c\xcc\xb1\xd1\x2f\xb0\xe3\xe5\x02\x04\x00\x00\xff\xff\x90\x62\x4f\xfb\x19\x00\x00\x00") + +func includes_partialJetBytes() ([]byte, error) { + return bindataRead( + _includes_partialJet, + "includes/_partial.jet", + ) +} + +func includes_partialJet() (*asset, error) { + bytes, err := includes_partialJetBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "includes/_partial.jet", size: 25, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _includesBlocksJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xaa\xae\x4e\xca\xc9\x4f\xce\x56\xc8\x4d\xcd\x2b\xd5\xd0\xac\xad\xe5\xe5\x52\x50\xb0\x29\xb0\x0b\xc9\x48\x05\x0b\x29\x40\x64\xcb\x13\x8b\x15\x32\xf3\xca\xf2\xb3\x53\x53\xf4\x6c\xf4\x0b\xec\x78\xb9\xaa\xab\x53\xf3\x52\x40\xca\x01\x01\x00\x00\xff\xff\xa0\xd9\xd9\x5d\x41\x00\x00\x00") + +func includesBlocksJetBytes() ([]byte, error) { + return bindataRead( + _includesBlocksJet, + "includes/blocks.jet", + ) +} + +func includesBlocksJet() (*asset, error) { + bytes, err := includesBlocksJetBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "includes/blocks.jet", size: 65, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _indexJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x64\x90\xb1\x6a\xf3\x30\x14\x85\xf7\x1f\xfe\x77\x38\xf5\xd2\x74\xa9\xc9\x5a\x8c\x87\x42\x86\x2e\x5d\xfa\x00\x45\xb6\x6e\xb0\x1a\x59\x57\xf8\x5e\xd7\x36\x22\xef\x5e\x2c\x9b\x10\xda\xed\x48\xe7\x3b\xe8\x43\x29\xd1\xac\x14\xac\xa0\xf0\x66\xe1\x51\xa5\x34\x31\x7a\xd7\x1a\x75\x1c\x9e\xbf\x48\x8b\xeb\xf5\xff\xbf\x94\x5c\x1f\x79\x50\x14\x2e\xb4\x7e\xb4\x24\x65\xe3\xb9\xbd\xc8\x8d\x58\x99\x7c\x05\xcb\xed\xd8\x53\xd0\x57\xb6\xcb\xe1\x69\xed\x80\xaa\x3b\xd6\xa7\xbe\x21\x6b\xc9\x82\x66\xd3\x47\x4f\x55\xd9\x1d\xeb\x75\x08\x54\xc1\x7c\xd7\x6b\x00\x52\x5a\x1c\x79\x8b\x9e\xc2\x78\x5b\x97\x5b\xbf\xe6\x94\x76\x83\x3b\x95\xcf\x68\x06\x75\xc6\xdf\xc9\x64\xf0\x8c\x87\x9d\x79\x3b\x9f\x66\x27\x2a\x87\xc2\x32\xc9\x3b\x6b\x3e\x66\x7e\x7f\x03\xa8\x62\xfd\xd1\xf1\x24\xe8\x78\xfa\x33\xc4\xc4\xc3\x45\x5e\xf0\x7b\x8e\xc9\x08\x02\x2b\x76\xde\xa2\xa1\xd6\x8c\x42\x70\x9a\xe1\xf0\xa8\xa0\x4c\x57\x65\xac\x37\x31\x0a\x76\xfb\xd4\x3d\xfc\x04\x00\x00\xff\xff\x28\x5a\x9d\x42\x85\x01\x00\x00") + +func indexJetBytes() ([]byte, error) { + return bindataRead( + _indexJet, + "index.jet", + ) +} + +func indexJet() (*asset, error) { + bytes, err := indexJetBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "index.jet", size: 389, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _layoutsApplicationJet = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x3c\x8e\xbd\xae\xc2\x30\x0c\x85\xf7\x4a\x7d\x07\xdf\x4c\x97\x01\x75\x65\x70\x3b\x00\x65\x85\xa1\x0c\x8c\x69\x6d\x11\x44\x7e\x10\x18\x89\x2a\xca\xbb\x23\xda\xc0\x64\xcb\x3e\xdf\xa7\x83\x7f\xdb\xfd\xa6\x3b\x1d\x5a\x30\xe2\x6c\x53\x16\xf8\x99\x60\xb5\x3f\xd7\x8a\xbd\x6a\xca\x02\x00\x0d\x6b\x9a\x36\x00\x74\x2c\x1a\x06\xa3\xef\x0f\x96\x5a\x1d\xbb\xdd\x72\xa5\xbe\x3f\xb9\x88\xe5\xa6\x75\x3d\x13\x31\x01\xbf\xb4\xbb\x59\xc6\x6a\xbe\x4f\xaa\xea\xe7\xc2\x3e\xd0\x98\xc9\x18\x7b\x1b\x86\x2b\x50\x18\x9e\x8e\xbd\xac\x03\x8d\xff\x8b\x94\x62\x64\x4f\x29\xcd\x64\xce\x63\x95\xab\xbe\x03\x00\x00\xff\xff\xee\xc2\x94\xa4\xbc\x00\x00\x00") + +func layoutsApplicationJetBytes() ([]byte, error) { + return bindataRead( + _layoutsApplicationJet, + "layouts/application.jet", + ) +} + +func layoutsApplicationJet() (*asset, error) { + bytes, err := layoutsApplicationJetBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layouts/application.jet", size: 188, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "includes/_partial.jet": includes_partialJet, + "includes/blocks.jet": includesBlocksJet, + "index.jet": indexJet, + "layouts/application.jet": layoutsApplicationJet, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "includes": {nil, map[string]*bintree{ + "_partial.jet": {includes_partialJet, map[string]*bintree{}}, + "blocks.jet": {includesBlocksJet, map[string]*bintree{}}, + }}, + "index.jet": {indexJet, map[string]*bintree{}}, + "layouts": {nil, map[string]*bintree{ + "application.jet": {layoutsApplicationJet, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) +} diff --git a/view/template_jet_1_embedded/main.go b/view/template_jet_1_embedded/main.go new file mode 100644 index 00000000..b6595078 --- /dev/null +++ b/view/template_jet_1_embedded/main.go @@ -0,0 +1,37 @@ +// Package main shows how to use jet templates embedded in your application with ease using the Iris built-in Jet view engine. +// This example is a customized fork of https://github.com/CloudyKit/jet/tree/master/examples/asset_packaging, so you can +// notice the differences side by side. For example, you don't have to use any external package inside your application, +// Iris manually builds the template loader for binary data when Asset and AssetNames are available via tools like the go-bindata. +package main + +import ( + "os" + + "github.com/kataras/iris/v12" +) + +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// +// $ go-bindata -fs -prefix "views" ./views/... +// $ go run . +// +// System files are not used, you can optionally delete the folder and run the example now. +func main() { + app := iris.New() + tmpl := iris.Jet(AssetFile(), ".jet") + app.RegisterView(tmpl) + + app.Get("/", func(ctx iris.Context) { + if err := ctx.View("index.jet"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + addr := ":8080" + if port := os.Getenv("PORT"); port != "" { + addr = ":" + port + } + + app.Listen(addr) +} diff --git a/view/template_jet_1_embedded/views/includes/_partial.jet b/view/template_jet_1_embedded/views/includes/_partial.jet new file mode 100644 index 00000000..3ebaa7af --- /dev/null +++ b/view/template_jet_1_embedded/views/includes/_partial.jet @@ -0,0 +1 @@ +<p>Included partial</p> diff --git a/view/template_jet_1_embedded/views/includes/blocks.jet b/view/template_jet_1_embedded/views/includes/blocks.jet new file mode 100644 index 00000000..14c074ea --- /dev/null +++ b/view/template_jet_1_embedded/views/includes/blocks.jet @@ -0,0 +1,3 @@ +{{block menu()}} + <p>The menu block was invoked.</p> +{{end}} diff --git a/view/template_jet_1_embedded/views/index.jet b/view/template_jet_1_embedded/views/index.jet new file mode 100644 index 00000000..670f11a7 --- /dev/null +++ b/view/template_jet_1_embedded/views/index.jet @@ -0,0 +1,16 @@ +{{extends "layouts/application.jet"}} +{{import "includes/blocks.jet"}} + +{{block documentBody()}} + <h1>Embedded example</h1> + + <nav> + {{yield menu()}} + </nav> + + {{include "includes/_partial.jet"}} + + {{if !includeIfExists("doesNotExist.jet")}} + <p>Shows how !includeIfExists works: doesNotExist.jet was not included because it doesn't exist.</p> + {{end}} +{{end}} diff --git a/view/template_jet_1_embedded/views/layouts/application.jet b/view/template_jet_1_embedded/views/layouts/application.jet new file mode 100644 index 00000000..16117b71 --- /dev/null +++ b/view/template_jet_1_embedded/views/layouts/application.jet @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <title>Embedded example</title> + </head> + <body> + {{block documentBody()}}{{end}} + </body> +</html> diff --git a/view/template_jet_2/main.go b/view/template_jet_2/main.go new file mode 100644 index 00000000..d40bf4e5 --- /dev/null +++ b/view/template_jet_2/main.go @@ -0,0 +1,71 @@ +// Package main an example on how to naming your routes & use the custom 'url path' Jet Template Engine. +package main + +import ( + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + app.RegisterView(iris.Jet("./views", ".jet").Reload(true)) + + mypathRoute := app.Get("/mypath", writePathHandler) + mypathRoute.Name = "my-page1" + + mypath2Route := app.Get("/mypath2/{paramfirst}/{paramsecond}", writePathHandler) + mypath2Route.Name = "my-page2" + + mypath3Route := app.Get("/mypath3/{paramfirst}/statichere/{paramsecond}", writePathHandler) + mypath3Route.Name = "my-page3" + + mypath4Route := app.Get("/mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}", writePathHandler) + // same as: app.Get("/mypath4/:paramfirst/statichere/:paramsecond/:otherparam/*something", writePathHandler) + mypath4Route.Name = "my-page4" + + // same with Handle/Func + mypath5Route := app.Handle("GET", "/mypath5/{paramfirst:int}/statichere/{paramsecond}/{otherparam}/anything/{something:path}", writePathHandlerPage5) + mypath5Route.Name = "my-page5" + + mypath6Route := app.Get("/mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic}", writePathHandler) + mypath6Route.Name = "my-page6" + + app.Get("/", func(ctx iris.Context) { + // for /mypath6... + paramsAsArray := []string{"theParam1", "theParam2", "paramThirdAfterStatic"} + ctx.ViewData("ParamsAsArray", paramsAsArray) + if err := ctx.View("page.jet"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Get("/redirect/{namedRoute}", func(ctx iris.Context) { + routeName := ctx.Params().Get("namedRoute") + r := app.GetRoute(routeName) + if r == nil { + ctx.StatusCode(iris.StatusNotFound) + ctx.Writef("Route with name %s not found", routeName) + return + } + + println("The path of " + routeName + "is: " + r.Path) + // if routeName == "my-page1" + // prints: The path of of my-page1 is: /mypath + // if it's a path which takes named parameters + // then use "r.ResolvePath(paramValuesHere)" + ctx.Redirect(r.Path) + // http://localhost:8080/redirect/my-page1 will redirect to -> http://localhost:8080/mypath + }) + + // http://localhost:8080 + // http://localhost:8080/redirect/my-page1 + app.Listen(":8080") +} + +func writePathHandler(ctx iris.Context) { + ctx.Writef("Hello from %s.", ctx.Path()) +} + +func writePathHandlerPage5(ctx iris.Context) { + ctx.Writef("Hello from %s.\nparamfirst(int)=%d", ctx.Path(), ctx.Params().GetIntDefault("paramfirst", 0)) +} diff --git a/view/template_jet_2/views/page.jet b/view/template_jet_2/views/page.jet new file mode 100644 index 00000000..c7268d9d --- /dev/null +++ b/view/template_jet_2/views/page.jet @@ -0,0 +1,24 @@ +<a href="{{urlpath("my-page1")}}">/mypath</a> +<br /> +<br/> +<a href="{{urlpath("my-page2","theParam1","theParam2")}}">/mypath2/{paramfirst}/{paramsecond}</a> +<br /> +<br /> + +<a href="{{urlpath("my-page3", "theParam1", "theParam2AfterStatic")}}">/mypath3/{paramfirst}/statichere/{paramsecond}</a> +<br /> +<br /> + +<a href="{{urlpath("my-page4", "theParam1", "theparam2AfterStatic", "otherParam", "matchAnything")}}"> + /mypath4/{paramfirst}/statichere/{paramsecond}/{otherparam}/{something:path}</a> +<br /> +<br /> + +<a href="{{urlpath("my-page5", "42", "theParam2Afterstatichere", "otherParam", "matchAnythingAfterStatic")}}"> + /mypath5/{paramfirst}/statichere/{paramsecond}/{otherparam}/anything/{anything:path}</a> +<br /> +<br /> + +<a href={{urlpath("my-page6", .ParamsAsArray)}}> + /mypath6/{paramfirst}/{paramsecond}/statichere/{paramThirdAfterStatic} +</a> diff --git a/view/template_jet_3/main.go b/view/template_jet_3/main.go new file mode 100644 index 00000000..8d7cc864 --- /dev/null +++ b/view/template_jet_3/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "reflect" + "strings" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/view" +) + +func main() { + tmpl := iris.Jet("./views", ".jet") + tmpl.Reload(true) + + val := reflect.ValueOf(ViewBuiler{}) + fns := val.Type() + for i := 0; i < fns.NumMethod(); i++ { + method := fns.Method(i) + tmpl.AddFunc(strings.ToLower(method.Name), val.Method(i).Interface()) + } + + app := iris.New() + app.RegisterView(tmpl) + + app.Get("/", func(ctx iris.Context) { + if err := ctx.View("index.jet"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + }) + + app.Listen(":8080") +} + +type ViewBuiler struct { +} + +func (ViewBuiler) Asset(a view.JetArguments) reflect.Value { + path := a.Get(0).String() + // fmt.Println(os.Getenv("APP_URL")) + return reflect.ValueOf(path) +} + +func (ViewBuiler) Style(a view.JetArguments) reflect.Value { + path := a.Get(0).String() + s := fmt.Sprintf(`<link href="%v" rel="stylesheet">`, path) + return reflect.ValueOf(s) +} + +func (ViewBuiler) Script(a view.JetArguments) reflect.Value { + path := a.Get(0).String() + s := fmt.Sprintf(`<script src="%v"></script>`, path) + return reflect.ValueOf(s) +} diff --git a/view/template_jet_3/views/index.jet b/view/template_jet_3/views/index.jet new file mode 100644 index 00000000..6022ed37 --- /dev/null +++ b/view/template_jet_3/views/index.jet @@ -0,0 +1,16 @@ +{{ asset("./myasset.mp3")}} +<br/> +{{ style("my-stle.css") | raw}} +<br/> +{{ script("my-script.js") | raw}} + +<!-- view page source: can't add a link as chrome blocks loading local source, instead +do that: --> + +<code> + ./myasset.mp3 + <br/> + <link href="my-stle.css" rel="stylesheet"> + <br/> + <script src="my-script.js"></script> +</code> \ No newline at end of file diff --git a/view/template_pug_0/main.go b/view/template_pug_0/main.go index 1d5f35e6..548f2ac1 100644 --- a/view/template_pug_0/main.go +++ b/view/template_pug_0/main.go @@ -1,29 +1,45 @@ +// Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions package main -import "github.com/kataras/iris" +import "github.com/kataras/iris/v12" + +type Person struct { + Name string + Age int + Emails []string + Jobs []*Job +} + +type Job struct { + Employer string + Role string +} func main() { app := iris.New() tmpl := iris.Pug("./templates", ".pug") - tmpl.Reload(true) // reload templates on each request (development mode) - tmpl.AddFunc("greet", func(s string) string { // add your template func here. - return "Greetings " + s + "!" - }) - app.RegisterView(tmpl) app.Get("/", index) // http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func index(ctx iris.Context) { - ctx.ViewData("pageTitle", "My Index Page") - ctx.ViewData("youAreUsingJade", true) - // Q: why need extension .pug? - // A: Because you can register more than one view engine per Iris application. - ctx.View("index.pug") - + job1 := Job{Employer: "Monash B", Role: "Honorary"} + job2 := Job{Employer: "Box Hill", Role: "Head of HE"} + + person := Person{ + Name: "jan", + Age: 50, + Emails: []string{"jan@newmarch.name", "jan.newmarch@gmail.com"}, + Jobs: []*Job{&job1, &job2}, + } + + if err := ctx.View("index.pug", person); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } } diff --git a/view/template_pug_0/templates/index.pug b/view/template_pug_0/templates/index.pug index e0f39238..c6b21de2 100644 --- a/view/template_pug_0/templates/index.pug +++ b/view/template_pug_0/templates/index.pug @@ -1,25 +1,20 @@ -mixin withGo - | Generating Go html/template output. - doctype html html(lang="en") - head - title= .pageTitle - script(type='text/javascript'). - if (foo) { - bar(1 + 5) - } - body - h1 Jade - template engine - #container.col - if .youAreUsingJade - p {{ greet "iris user" }} <!-- execute template funcs --> - p You are amazing! - else - p Get on it! - p. - Jade is #[a(terse)] and simple - templating language with a - #[strong focus] on performance - and powerful features. - + withGo \ No newline at end of file + head + meta(charset="utf-8") + title Title + body + p ads + ul + li The name is {{.Name}}. + li The age is {{.Age}}. + + each _,_ in .Emails + div An email is {{.}} + + | {{ with .Jobs }} + each _,_ in . + div + An employer is {{.Employer}} + and the role is {{.Role}} + | {{ end }} \ No newline at end of file diff --git a/view/template_pug_1/main.go b/view/template_pug_1/main.go index 7c266507..fac8bb86 100644 --- a/view/template_pug_1/main.go +++ b/view/template_pug_1/main.go @@ -1,42 +1,31 @@ -// Package main shows an example of pug actions based on https://github.com/Joker/jade/tree/master/example/actions package main -import "github.com/kataras/iris" +import ( + "html/template" -type Person struct { - Name string - Age int - Emails []string - Jobs []*Job -} - -type Job struct { - Employer string - Role string -} + "github.com/kataras/iris/v12" +) func main() { app := iris.New() tmpl := iris.Pug("./templates", ".pug") + tmpl.Reload(true) // reload templates on each request (development mode) + tmpl.AddFunc("bold", func(s string) (template.HTML, error) { // add your template func here. + return template.HTML("<b>" + s + "</b>"), nil + }) + app.RegisterView(tmpl) app.Get("/", index) // http://localhost:8080 - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } func index(ctx iris.Context) { - job1 := Job{Employer: "Monash B", Role: "Honorary"} - job2 := Job{Employer: "Box Hill", Role: "Head of HE"} - - person := Person{ - Name: "jan", - Age: 50, - Emails: []string{"jan@newmarch.name", "jan.newmarch@gmail.com"}, - Jobs: []*Job{&job1, &job2}, + if err := ctx.View("index.pug"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return } - - ctx.View("index.pug", person) } diff --git a/view/template_pug_2/templates/footer.pug b/view/template_pug_1/templates/footer.pug similarity index 100% rename from view/template_pug_2/templates/footer.pug rename to view/template_pug_1/templates/footer.pug diff --git a/view/template_pug_2/templates/header.pug b/view/template_pug_1/templates/header.pug similarity index 100% rename from view/template_pug_2/templates/header.pug rename to view/template_pug_1/templates/header.pug diff --git a/view/template_pug_1/templates/index.pug b/view/template_pug_1/templates/index.pug index c6b21de2..ee11d9b4 100644 --- a/view/template_pug_1/templates/index.pug +++ b/view/template_pug_1/templates/index.pug @@ -1,20 +1,7 @@ doctype html -html(lang="en") - head - meta(charset="utf-8") - title Title - body - p ads - ul - li The name is {{.Name}}. - li The age is {{.Age}}. - - each _,_ in .Emails - div An email is {{.}} - - | {{ with .Jobs }} - each _,_ in . - div - An employer is {{.Employer}} - and the role is {{.Role}} - | {{ end }} \ No newline at end of file +html + include header.pug + body + h1 My Site + p {{ bold "Welcome to my super lame site."}} + include footer.pug \ No newline at end of file diff --git a/view/template_pug_2/main.go b/view/template_pug_2/main.go deleted file mode 100644 index 02e9571e..00000000 --- a/view/template_pug_2/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "html/template" - - "github.com/kataras/iris" -) - -func main() { - app := iris.New() - - tmpl := iris.Pug("./templates", ".pug") - tmpl.Reload(true) // reload templates on each request (development mode) - tmpl.AddFunc("bold", func(s string) (template.HTML, error) { // add your template func here. - return template.HTML("<b>" + s + "</b>"), nil - }) - - app.RegisterView(tmpl) - - app.Get("/", index) - - // http://localhost:8080 - app.Run(iris.Addr(":8080")) -} - -func index(ctx iris.Context) { - ctx.View("index.pug") -} diff --git a/view/template_pug_2/templates/index.pug b/view/template_pug_2/templates/index.pug deleted file mode 100644 index a006f865..00000000 --- a/view/template_pug_2/templates/index.pug +++ /dev/null @@ -1,7 +0,0 @@ -doctype html -html - include templates/header.pug - body - h1 My Site - p {{ bold "Welcome to my super lame site."}} - include templates/footer.pug \ No newline at end of file diff --git a/view/template_pug_2_embedded/bindata.go b/view/template_pug_2_embedded/bindata.go new file mode 100644 index 00000000..99d59246 --- /dev/null +++ b/view/template_pug_2_embedded/bindata.go @@ -0,0 +1,356 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + +// Package main generated by go-bindata.// sources: +// templates/index.pug +// templates/layout.pug +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _indexPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xad\x28\x49\xcd\x4b\x29\x56\xc8\x49\xac\xcc\x2f\x2d\xd1\x2b\x28\x4d\xe7\xe5\xe2\xe5\x4a\xca\xc9\x4f\xce\x56\x28\xc9\x2c\xc9\x49\xe5\xe5\x52\x80\x30\x14\x1c\x8b\x4a\x32\x93\x73\x52\x15\x42\x20\xc2\x30\x55\xc9\xf9\x79\x25\xa9\x79\x25\x20\x75\x19\x86\x0a\xbe\x95\x30\x75\x80\x00\x00\x00\xff\xff\xa6\xfd\x18\x8c\x5a\x00\x00\x00") + +func indexPugBytes() ([]byte, error) { + return bindataRead( + _indexPug, + "index.pug", + ) +} + +func indexPug() (*asset, error) { + bytes, err := indexPugBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "index.pug", size: 90, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _layoutPug = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4a\xc9\x4f\x2e\xa9\x2c\x48\x55\xc8\x28\xc9\xcd\xe1\xe5\x82\x90\x0a\x0a\x19\xa9\x89\x29\x20\x5a\x41\x21\x29\x27\x3f\x39\x5b\xa1\x24\xb3\x24\x27\x15\x22\xa0\x00\xe1\x28\xb8\xa4\xa6\x25\x96\xe6\x94\x20\xa4\x92\xf2\x53\x2a\x91\xf5\x24\xe7\xe7\x95\xa4\xe6\x95\x00\x02\x00\x00\xff\xff\x5f\xa5\x93\xf9\x61\x00\x00\x00") + +func layoutPugBytes() ([]byte, error) { + return bindataRead( + _layoutPug, + "layout.pug", + ) +} + +func layoutPug() (*asset, error) { + bytes, err := layoutPugBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "layout.pug", size: 97, mode: os.FileMode(438), modTime: time.Unix(1599156854, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "index.pug": indexPug, + "layout.pug": layoutPug, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "index.pug": {indexPug, map[string]*bintree{}}, + "layout.pug": {layoutPug, map[string]*bintree{}}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = os.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) +} diff --git a/view/template_pug_2_embedded/main.go b/view/template_pug_2_embedded/main.go new file mode 100644 index 00000000..c04d08ba --- /dev/null +++ b/view/template_pug_2_embedded/main.go @@ -0,0 +1,29 @@ +package main + +import "github.com/kataras/iris/v12" + +// $ go install github.com/go-bindata/go-bindata/v3/go-bindata@latest +// +// $ go-bindata -fs -prefix "templates" ./templates/... +// $ go run . +// +// System files are not used, you can optionally delete the folder and run the example now. +func main() { + app := iris.New() + + tmpl := iris.Pug(AssetFile(), ".pug") + + app.RegisterView(tmpl) + + app.Get("/", index) + + // http://localhost:8080 + app.Listen(":8080") +} + +func index(ctx iris.Context) { + if err := ctx.View("index.pug"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} diff --git a/view/template_pug_3/templates/index.pug b/view/template_pug_2_embedded/templates/index.pug similarity index 69% rename from view/template_pug_3/templates/index.pug rename to view/template_pug_2_embedded/templates/index.pug index 257f4a7c..f061806c 100644 --- a/view/template_pug_3/templates/index.pug +++ b/view/template_pug_2_embedded/templates/index.pug @@ -1,4 +1,4 @@ -extends templates/layout.pug +extends layout.pug block title title Article Title diff --git a/view/template_pug_3/templates/layout.pug b/view/template_pug_2_embedded/templates/layout.pug similarity index 100% rename from view/template_pug_3/templates/layout.pug rename to view/template_pug_2_embedded/templates/layout.pug diff --git a/view/template_pug_3/main.go b/view/template_pug_3/main.go deleted file mode 100644 index ff82bbf4..00000000 --- a/view/template_pug_3/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import "github.com/kataras/iris" - -func main() { - app := iris.New() - - tmpl := iris.Pug("./templates", ".pug") - - app.RegisterView(tmpl) - - app.Get("/", index) - - // http://localhost:8080 - app.Run(iris.Addr(":8080")) -} - -func index(ctx iris.Context) { - ctx.View("index.pug") -} diff --git a/view/write-to/main.go b/view/write-to/main.go index 19adbe72..438c101f 100644 --- a/view/write-to/main.go +++ b/view/write-to/main.go @@ -3,7 +3,7 @@ package main import ( "os" - "github.com/kataras/iris" + "github.com/kataras/iris/v12" ) type mailData struct { @@ -34,10 +34,9 @@ func main() { RefTitle: "Iris web framework", RefLink: "https://iris-go.com", }) - if err != nil { app.Logger().Errorf("error from app.View: %v", err) } - app.Run(iris.Addr(":8080")) + app.Listen(":8080") } diff --git a/webassembly/client/go-wasm-runtime.js b/webassembly/client/go-wasm-runtime.js new file mode 100644 index 00000000..ecb09650 --- /dev/null +++ b/webassembly/client/go-wasm-runtime.js @@ -0,0 +1,412 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +(() => { + // Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API). + const isNodeJS = typeof process !== "undefined"; + if (isNodeJS) { + global.require = require; + global.fs = require("fs"); + + const nodeCrypto = require("crypto"); + global.crypto = { + getRandomValues(b) { + nodeCrypto.randomFillSync(b); + }, + }; + + global.performance = { + now() { + const [sec, nsec] = process.hrtime(); + return sec * 1000 + nsec / 1000000; + }, + }; + + const util = require("util"); + global.TextEncoder = util.TextEncoder; + global.TextDecoder = util.TextDecoder; + } else { + window.global = window; + + let outputBuf = ""; + global.fs = { + constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_NONBLOCK: -1, O_SYNC: -1 }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf("\n"); + if (nl != -1) { + console.log(outputBuf.substr(0, nl)); + outputBuf = outputBuf.substr(nl + 1); + } + return buf.length; + }, + openSync(path, flags, mode) { + const err = new Error("not implemented"); + err.code = "ENOSYS"; + throw err; + }, + }; + } + + const encoder = new TextEncoder("utf-8"); + const decoder = new TextDecoder("utf-8"); + + global.Go = class { + constructor() { + this.argv = ["js"]; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn("exit code:", code); + } + }; + this._callbackTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const mem = () => { + // The buffer may change when requesting more memory. + return new DataView(this._inst.exports.mem.buffer); + } + + const setInt64 = (addr, v) => { + mem().setUint32(addr + 0, v, true); + mem().setUint32(addr + 4, Math.floor(v / 4294967296), true); + } + + const getInt64 = (addr) => { + const low = mem().getUint32(addr + 0, true); + const high = mem().getInt32(addr + 4, true); + return low + high * 4294967296; + } + + const loadValue = (addr) => { + const f = mem().getFloat64(addr, true); + if (!isNaN(f)) { + return f; + } + + const id = mem().getUint32(addr, true); + return this._values[id]; + } + + const storeValue = (addr, v) => { + if (typeof v === "number") { + if (isNaN(v)) { + mem().setUint32(addr + 4, 0x7FF80000, true); // NaN + mem().setUint32(addr, 0, true); + return; + } + mem().setFloat64(addr, v, true); + return; + } + + mem().setUint32(addr + 4, 0x7FF80000, true); // NaN + + switch (v) { + case undefined: + mem().setUint32(addr, 1, true); + return; + case null: + mem().setUint32(addr, 2, true); + return; + case true: + mem().setUint32(addr, 3, true); + return; + case false: + mem().setUint32(addr, 4, true); + return; + } + + if (typeof v === "string") { + let ref = this._stringRefs.get(v); + if (ref === undefined) { + ref = this._values.length; + this._values.push(v); + this._stringRefs.set(v, ref); + } + mem().setUint32(addr, ref, true); + return; + } + + if (typeof v === "symbol") { + let ref = this._symbolRefs.get(v); + if (ref === undefined) { + ref = this._values.length; + this._values.push(v); + this._symbolRefs.set(v, ref); + } + mem().setUint32(addr, ref, true); + return; + } + + let ref = v[this._refProp]; + if (ref === undefined) { + ref = this._values.length; + this._values.push(v); + v[this._refProp] = ref; + } + mem().setUint32(addr, ref, true); + } + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + } + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + } + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); + } + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + go: { + // func wasmExit(code int32) + "runtime.wasmExit": (sp) => { + this.exited = true; + this.exit(mem().getInt32(sp + 8, true)); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + "runtime.wasmWrite": (sp) => { + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = mem().getInt32(sp + 24, true); + fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); + }, + + // func nanotime() int64 + "runtime.nanotime": (sp) => { + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + "runtime.walltime": (sp) => { + const msec = (new Date).getTime(); + setInt64(sp + 8, msec / 1000); + mem().setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleCallback(delay int64) int32 + "runtime.scheduleCallback": (sp) => { + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._callbackTimeouts.set(id, setTimeout( + () => { this._resolveCallbackPromise(); }, + getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early + )); + mem().setInt32(sp + 16, id, true); + }, + + // func clearScheduledCallback(id int32) + "runtime.clearScheduledCallback": (sp) => { + const id = mem().getInt32(sp + 8, true); + clearTimeout(this._callbackTimeouts.get(id)); + this._callbackTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + "runtime.getRandomData": (sp) => { + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func stringVal(value string) ref + "syscall/js.stringVal": (sp) => { + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + "syscall/js.valueGet": (sp) => { + storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16))); + }, + + // func valueSet(v ref, p string, x ref) + "syscall/js.valueSet": (sp) => { + Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); + }, + + // func valueIndex(v ref, i int) ref + "syscall/js.valueIndex": (sp) => { + storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); + }, + + // valueSetIndex(v ref, i int, x ref) + "syscall/js.valueSetIndex": (sp) => { + Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + "syscall/js.valueCall": (sp) => { + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + storeValue(sp + 56, Reflect.apply(m, v, args)); + mem().setUint8(sp + 64, 1); + } catch (err) { + storeValue(sp + 56, err); + mem().setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + "syscall/js.valueInvoke": (sp) => { + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + storeValue(sp + 40, Reflect.apply(v, undefined, args)); + mem().setUint8(sp + 48, 1); + } catch (err) { + storeValue(sp + 40, err); + mem().setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + "syscall/js.valueNew": (sp) => { + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + storeValue(sp + 40, Reflect.construct(v, args)); + mem().setUint8(sp + 48, 1); + } catch (err) { + storeValue(sp + 40, err); + mem().setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + "syscall/js.valueLength": (sp) => { + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + "syscall/js.valuePrepareString": (sp) => { + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + "syscall/js.valueLoadString": (sp) => { + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + "syscall/js.valueInstanceOf": (sp) => { + mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16)); + }, + + "debug": (value) => { + console.log(value); + }, + } + }; + } + + async run(instance) { + this._inst = instance; + this._values = [ // TODO: garbage collection + NaN, + undefined, + null, + true, + false, + global, + this._inst.exports.mem, + () => { // resolveCallbackPromise + if (this.exited) { + throw new Error("bad callback: Go program has already exited"); + } + setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous + }, + ]; + this._stringRefs = new Map(); + this._symbolRefs = new Map(); + this._refProp = Symbol(); + this.exited = false; + + const mem = new DataView(this._inst.exports.mem.buffer) + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + let ptr = offset; + new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0")); + offset += str.length + (8 - (str.length % 8)); + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + + const keys = Object.keys(this.env).sort(); + argvPtrs.push(keys.length); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + + const argv = offset; + argvPtrs.forEach((ptr) => { + mem.setUint32(offset, ptr, true); + mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + while (true) { + const callbackPromise = new Promise((resolve) => { + this._resolveCallbackPromise = resolve; + }); + this._inst.exports.run(argc, argv); + if (this.exited) { + break; + } + await callbackPromise; + } + } + } + + if (isNodeJS) { + if (process.argv.length < 3) { + process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n"); + process.exit(1); + } + + const go = new Go(); + go.argv = process.argv.slice(2); + go.env = process.env; + go.exit = process.exit; + WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { + process.on("exit", () => { // Node.js exits if no callback is pending + if (!go.exited) { + console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!"); + process.exit(1); + } + }); + return go.run(result.instance); + }).catch((err) => { + console.error(err); + go.exited = true; + process.exit(1); + }); + } +})(); diff --git a/webassembly/client/hello.html b/webassembly/client/hello.html new file mode 100644 index 00000000..29caa55b --- /dev/null +++ b/webassembly/client/hello.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>Hello Webassembly + Iris (Go)</title> +</head> +<body> + <div id="hello"></div> + <script type="module" src="main.js"></script> +</body> +</html> \ No newline at end of file diff --git a/webassembly/client/hello_go116.go b/webassembly/client/hello_go116.go new file mode 100644 index 00000000..a44b432d --- /dev/null +++ b/webassembly/client/hello_go116.go @@ -0,0 +1,17 @@ +//go:build js +// +build js + +package main + +import ( + "fmt" + "syscall/js" + "time" +) + +func main() { + // GOARCH=wasm GOOS=js /home/$yourusername/go1.16/bin/go build -mod=mod -o hello.wasm hello_go116.go + js.Global().Get("console").Call("log", "Hello Webassembly!") + message := fmt.Sprintf("Hello, the current time is: %s", time.Now().String()) + js.Global().Get("document").Call("getElementById", "hello").Set("innerText", message) +} diff --git a/webassembly/client/main.js b/webassembly/client/main.js new file mode 100644 index 00000000..02fac56a --- /dev/null +++ b/webassembly/client/main.js @@ -0,0 +1,13 @@ +import './go-wasm-runtime.js'; + +if (!WebAssembly.instantiateStreaming) { // polyfill + WebAssembly.instantiateStreaming = async (resp, importObject) => { + const source = await (await resp).arrayBuffer(); + return await WebAssembly.instantiate(source, importObject); + }; +} + +const go = new Go(); +WebAssembly.instantiateStreaming(fetch("hello.wasm"), go.importObject).then((result) => { + return WebAssembly.instantiate(result.module, go.importObject); +}).then(instance => go.run(instance)); \ No newline at end of file diff --git a/webassembly/main.go b/webassembly/main.go index 63890a83..fdf8c0f6 100644 --- a/webassembly/main.go +++ b/webassembly/main.go @@ -1,5 +1,28 @@ package main -func main() {} +import ( + "github.com/kataras/iris/v12" +) -/* Go to https://github.com/kataras/iris/tree/master/_examples/webassemply/basic */ +/* +You need to build the hello.wasm first, download the go1.16 and execute the below command: +$ cd client && GOARCH=wasm GOOS=js /home/$yourname/go1.16/bin/go build -mod=mod -o hello.wasm hello_go116.go +*/ + +func main() { + app := iris.New() + + // we could serve your assets like this the sake of the example, + // never include the .go files there in production. + app.HandleDir("/", iris.Dir("./client")) + + app.Get("/", func(ctx iris.Context) { + // ctx.CompressWriter(true) + ctx.ServeFile("./client/hello.html") + }) + + // visit http://localhost:8080 + // you should get an html output like this: + // Hello, the current time is: 2018-07-09 05:54:12.564 +0000 UTC m=+0.003900161 + app.Listen(":8080") +} diff --git a/websocket/README.md b/websocket/README.md index 6d7f41cf..8847af29 100644 --- a/websocket/README.md +++ b/websocket/README.md @@ -2,134 +2,13 @@ [WebSocket](https://wikipedia.org/wiki/WebSocket) is a protocol that enables two-way persistent communication channels over TCP connections. It is used for applications such as chat, stock tickers, games, anywhere you want real-time functionality in a web application. -[View or download sample code](https://github.com/kataras/iris/tree/master/_examples/websocket). +Iris websocket library is now merged with the [neffos real-time framework](https://github.com/kataras/neffos) and Iris-specific helpers and type aliases live on the [iris/websocket](https://github.com/kataras/iris/tree/main/websocket) subpackage. Learn neffos from its [wiki](https://github.com/kataras/neffos#learning-neffos). -## When to use it +Helpers and type aliases improves your code speed when writing a websocket module. +For example, instead of importing both `kataras/iris/websocket` - in order to use its `websocket.Handler` - and `github.com/kataras/neffos` - to create a new websocket server `neffos.New` - you can use the `websocket.New` instead, another example is the `neffos.Conn` which can be declared as `websocket.Conn`. -Use WebSockets when you need to work directly with a socket connection. For example, you might need the best possible performance for a real-time game. +All neffos and its subpackage's types and package-level functions exist as type aliases on the `kataras/iris/websocket` package too, there are too many of those and there is no need to write each one of those here, some common types: -## How to use it - -* import the `"github.com/kataras/iris/websocket"` -* Configure the websocket package. -* Accept WebSocket requests. -* Send and receive messages. - -### Import the websocket package - -```go -import "github.com/kataras/iris/websocket" -``` - -### Configure the websocket package - -```go -import "github.com/kataras/iris/websocket" - -func main() { - ws := websocket.New(websocket.Config{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - }) -} -``` - -#### Complete configuration - -```go -// Config the websocket server configuration -// all of these are optional. -type Config struct { - // IDGenerator used to create (and later on, set) - // an ID for each incoming websocket connections (clients). - // The request is an argument which you can use to generate the ID (from headers for example). - // If empty then the ID is generated by DefaultIDGenerator: randomString(64) - IDGenerator func(ctx context.Context) string - // Error is the function that will be fired if any client couldn't upgrade the HTTP connection - // to a websocket connection, a handshake error. - Error func(w http.ResponseWriter, r *http.Request, status int, reason error) - // CheckOrigin a function that is called right before the handshake, - // if returns false then that client is not allowed to connect with the websocket server. - CheckOrigin func(r *http.Request) bool - // HandshakeTimeout specifies the duration for the handshake to complete. - HandshakeTimeout time.Duration - // WriteTimeout time allowed to write a message to the connection. - // 0 means no timeout. - // Default value is 0 - WriteTimeout time.Duration - // ReadTimeout time allowed to read a message from the connection. - // 0 means no timeout. - // Default value is 0 - ReadTimeout time.Duration - // PongTimeout allowed to read the next pong message from the connection. - // Default value is 60 * time.Second - PongTimeout time.Duration - // PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout. - // Default value is 60 *time.Second - PingPeriod time.Duration - // MaxMessageSize max message size allowed from connection. - // Default value is 1024 - MaxMessageSize int64 - // BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text - // compatible if you wanna use the Connection's EmitMessage to send a custom binary data to the client, like a native server-client communication. - // defaults to false - BinaryMessages bool - // ReadBufferSize is the buffer size for the underline reader - // Default value is 4096 - ReadBufferSize int - // WriteBufferSize is the buffer size for the underline writer - // Default value is 4096 - WriteBufferSize int - // EnableCompression specify if the server should attempt to negotiate per - // message compression (RFC 7692). Setting this value to true does not - // guarantee that compression will be supported. Currently only "no context - // takeover" modes are supported. - EnableCompression bool - - // Subprotocols specifies the server's supported protocols in order of - // preference. If this field is set, then the Upgrade method negotiates a - // subprotocol by selecting the first match in this list with a protocol - // requested by the client. - Subprotocols []string -} -``` - -### Accept WebSocket requests & send & receive messages - -```go -import ( - "github.com/kataras/iris" - "github.com/kataras/iris/websocket" -) - -func main() { - ws := websocket.New(websocket.Config{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - }) - - ws.OnConnection(handleConnection) - - app := iris.New() - // register the server on an endpoint. - // see the inline javascript code in the websockets.html, this endpoint is used to connect to the server. - app.Get("/echo", ws.Handler()) - - // serve the javascript built'n client-side library, - // see websockets.html script tags, this path is used. - app.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) - }) -} - -func handleConnection(c websocket.Connection) { - // Read events from browser - c.On("chat", func(msg string) { - // Print the message to the console, c.Context() is the iris's http context. - fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg) - // Write message back to the client message owner: - // c.Emit("chat", msg) - c.To(websocket.Broadcast).Emit("chat", msg) - }) -} -``` \ No newline at end of file +- `github.com/kataras/neffos/#Conn` -> `github.com/kataras/iris/websocket/#Conn` +- `github.com/kataras/neffos/gorilla/#DefaultUpgrader` -> `github.com/kataras/iris/websocket/#DefaultGorillaUpgrader` +- `github.com/kataras/neffos/stackexchange/redis/#NewStackExchange` -> `github.com/kataras/iris/websocket/#NewRedisStackExchange` diff --git a/websocket/basic/README.md b/websocket/basic/README.md new file mode 100644 index 00000000..334c0ef9 --- /dev/null +++ b/websocket/basic/README.md @@ -0,0 +1,64 @@ +# Basic Example + +At the end of this example you will be able to run a websocket server +and clients for all platforms (Go, Browser and Nodejs). + + + +Open as many clients as you want to try out and start typing. + +This example contains only the basics, however, the library supports rooms, native websocket messages, any data can be sent and received (i.e protobufs, json) and all kinds of broadcasting and connections collections. + +## How to run + +### Server + +Open a terminal window instance and execute: + +```sh +$ go mod tidy -compat=1.17 +$ go run server.go # start the websocket server. +``` + +### Client (Go) + +Start a new terminal instance and execute: + +```sh +$ cd ./go-client +$ go mod tidy -compat=1.17 +$ go run client.go # start the websocket client. +# start typing... +``` + +### Client (Browser) + +Navigate to <http://localhost:8080> and start typing. +The `./browser/index.html` should be served, it contains the client-side code. + +### Client (Browserify) + +Install [NPM](https://nodejs.org) first, then start a new terminal instance and execute: + +```sh +$ cd ./browserify +$ npm install +# build the modern browser-side client: +# embed the neffos.js node-module and app.js +# into a single ./browserify/bundle.js file +# which ./browserify/client.html imports. +$ npm run-script build +``` + +Navigate to <http://localhost:8080/browserify/client.html> and start typing. + +### Client (Nodejs) + +Install [NPM](https://nodejs.org) if you haven't already and then, start a new terminal instance and execute: + +```sh +$ cd nodejs-client +$ npm install +$ node client.js # start the websocket client. +# start typing. +``` diff --git a/websocket/basic/browser/index.html b/websocket/basic/browser/index.html new file mode 100644 index 00000000..e0b4e3e5 --- /dev/null +++ b/websocket/basic/browser/index.html @@ -0,0 +1,112 @@ +<!-- the message's input --> +<input id="input" type="text" /> + +<!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' --> +<button id="sendBtn" disabled>Send</button> + +<!-- the messages will be shown here --> +<pre id="output"></pre> +<!-- import the iris client-side library for browser from a CDN or locally. + However, `neffos.(min.)js` is a NPM package too so alternatively, + you can use it as dependency on your package.json and all nodejs-npm tooling become available: + see the "browserify" example for more--> +<script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> +<script> + // `neffos` global variable is available now. + var scheme = document.location.protocol == "https:" ? "wss" : "ws"; + var port = document.location.port ? ":" + document.location.port : ""; + var wsURL = scheme + "://" + document.location.hostname + port + "/echo"; + + const enableJWT = true; + if (enableJWT) { + // This is just a signature and a payload of an example content, + // please replace this with your logic. + // + // Add a random letter in front of the token to make it + // invalid and see that this client is not allowed to dial the websocket server. + const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU"; + wsURL += "?token=" + token; + } + + var outputTxt = document.getElementById("output"); + function addMessage(msg) { + outputTxt.innerHTML += msg + "\n"; + } + + function handleError(reason) { + console.log(reason); + window.alert("error: see the dev console"); + } + + function handleNamespaceConnectedConn(nsConn) { + nsConn.emit("Hello from browser client side!"); + + let inputTxt = document.getElementById("input"); + let sendBtn = document.getElementById("sendBtn"); + + sendBtn.disabled = false; + sendBtn.onclick = function () { + const input = inputTxt.value; + inputTxt.value = ""; + nsConn.emit("chat", input); + addMessage("Me: " + input); + }; + } + + const username = window.prompt("Your username?"); + + async function runExample() { + // You can omit the "default" and simply define only Events, the namespace will be an empty string"", + // however if you decide to make any changes on this example make sure the changes are reflecting inside the ../server.go file as well. + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: function (nsConn, msg) { + addMessage("connected to namespace: " + msg.Namespace); + handleNamespaceConnectedConn(nsConn) + }, + _OnNamespaceDisconnect: function (nsConn, msg) { + addMessage("disconnected from namespace: " + msg.Namespace); + }, + chat: function (nsConn, msg) { // "chat" event. + addMessage(msg.Body); + } + } + },{ + headers: { + "X-Username": username, + } + }); + + // You can either wait to conenct or just conn.connect("connect") + // and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead. + // const nsConn = await conn.connect("default"); + // nsConn.emit(...); handleNamespaceConnectedConn(nsConn); + conn.connect("default"); + + } catch (err) { + handleError(err); + } + } + + runExample(); + + // If "await" and "async" are available, use them instead^, all modern browsers support those, + // all of the javascript examples will be written using async/await method instead of promise then/catch callbacks. + // A usage example of promise then/catch follows: + // neffos.dial(wsURL, { + // default: { // "default" namespace. + // _OnNamespaceConnected: function (ns, msg) { + // addMessage("connected to namespace: " + msg.Namespace); + // }, + // _OnNamespaceDisconnect: function (ns, msg) { + // addMessage("disconnected from namespace: " + msg.Namespace); + // }, + // chat: function (ns, msg) { // "chat" event. + // addMessage(msg.Body); + // } + // } + // }).then(function (conn) { + // conn.connect("default").then(handleNamespaceConnectedConn).catch(handleError); + // }).catch(handleError); +</script> \ No newline at end of file diff --git a/websocket/basic/browserify/app.js b/websocket/basic/browserify/app.js new file mode 100644 index 00000000..8acfb9c9 --- /dev/null +++ b/websocket/basic/browserify/app.js @@ -0,0 +1,75 @@ +const neffos = require('neffos.js'); + +var scheme = document.location.protocol == "https:" ? "wss" : "ws"; +var port = document.location.port ? ":" + document.location.port : ""; + +var wsURL = scheme + "://" + document.location.hostname + port + "/echo"; + +const enableJWT = true; +if (enableJWT) { + // This is just a signature and a payload of an example content, + // please replace this with your logic. + // + // Add a random letter in front of the token to make it + // invalid and see that this client is not allowed to dial the websocket server. + const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU"; + wsURL += "?token=" + token; +} + +var outputTxt = document.getElementById("output"); + +function addMessage(msg) { + outputTxt.innerHTML += msg + "\n"; +} + +function handleError(reason) { + console.log(reason); + window.alert(reason); +} + +function handleNamespaceConnectedConn(nsConn) { + nsConn.emit("chat", "Hello from browser(ify) client-side!"); + + const inputTxt = document.getElementById("input"); + const sendBtn = document.getElementById("sendBtn"); + + sendBtn.disabled = false; + sendBtn.onclick = function () { + const input = inputTxt.value; + inputTxt.value = ""; + + nsConn.emit("chat", input); + addMessage("Me: " + input); + }; +} + +async function runExample() { + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: function (nsConn, msg) { + addMessage("connected to namespace: " + msg.Namespace); + handleNamespaceConnectedConn(nsConn); + }, + _OnNamespaceDisconnect: function (nsConn, msg) { + addMessage("disconnected from namespace: " + msg.Namespace); + }, + chat: function (nsConn, msg) { // "chat" event. + addMessage(msg.Body); + } + } + }); + + // You can either wait to conenct or just conn.connect("connect") + // and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead. + // const nsConn = await conn.connect("default"); + // handleNamespaceConnectedConn(nsConn); + // nsConn.emit(...); handleNamespaceConnectedConn(nsConn); + conn.connect("default"); + + } catch (err) { + handleError(err); + } +} + +runExample(); \ No newline at end of file diff --git a/websocket/basic/browserify/bundle.js b/websocket/basic/browserify/bundle.js new file mode 100644 index 00000000..ccf030ba --- /dev/null +++ b/websocket/basic/browserify/bundle.js @@ -0,0 +1 @@ +(function(){function d(s,e,n){function f(u,i){if(!e[u]){if(!s[u]){var t="function"==typeof require&&require;if(!i&&t)return t(u,!0);if(o)return o(u,!0);var r=new Error("Cannot find module '"+u+"'");throw r.code="MODULE_NOT_FOUND",r}var a=e[u]={exports:{}};s[u][0].call(a.exports,function(e){var d=s[u][1][e];return f(d||e)},a,a.exports,d,s,e,n)}return e[u].exports}for(var o="function"==typeof require&&require,u=0;u<n.length;u++)f(n[u]);return f}return d})()({1:[function(e){function n(e){t.innerHTML+=e+"\n"}function d(e){console.log(e),window.alert(e)}function i(e){e.emit("chat","Hello from browser(ify) client-side!");const d=document.getElementById("input"),i=document.getElementById("sendBtn");i.disabled=!1,i.onclick=function(){const i=d.value;d.value="",e.emit("chat",i),n("Me: "+i)}}async function f(){try{const e=await u.dial(a,{default:{_OnNamespaceConnected:function(e,d){n("connected to namespace: "+d.Namespace),i(e)},_OnNamespaceDisconnect:function(e,d){n("disconnected from namespace: "+d.Namespace)},chat:function(e,d){n(d.Body)}}});e.connect("default")}catch(e){d(e)}}const u=e("neffos.js");var o="https:"==document.location.protocol?"wss":"ws",s=document.location.port?":"+document.location.port:"",a=o+"://"+document.location.hostname+s+"/echo";{a+="?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjozMjEzMjF9.8waEX7-vPKACa-Soi1pQvW3Rl8QY-SUFcHKTLZI4mvU"}var t=document.getElementById("output");f()},{"neffos.js":5}],2:[function(e,n){var d=e("./lib/encoding.js");n.exports={TextEncoder:d.TextEncoder,TextDecoder:d.TextDecoder}},{"./lib/encoding.js":4}],3:[function(e,n){(function(e){'use strict';"undefined"!=typeof n&&n.exports&&(n.exports=e),e["encoding-indexes"]={big5:[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,17392,19506,17923,17830,17784,160359,19831,17843,162993,19682,163013,15253,18230,18244,19527,19520,148159,144919,160594,159371,159954,19543,172881,18255,17882,19589,162924,19719,19108,18081,158499,29221,154196,137827,146950,147297,26189,22267,null,32149,22813,166841,15860,38708,162799,23515,138590,23204,13861,171696,23249,23479,23804,26478,34195,170309,29793,29853,14453,138579,145054,155681,16108,153822,15093,31484,40855,147809,166157,143850,133770,143966,17162,33924,40854,37935,18736,34323,22678,38730,37400,31184,31282,26208,27177,34973,29772,31685,26498,31276,21071,36934,13542,29636,155065,29894,40903,22451,18735,21580,16689,145038,22552,31346,162661,35727,18094,159368,16769,155033,31662,140476,40904,140481,140489,140492,40905,34052,144827,16564,40906,17633,175615,25281,28782,40907,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,12736,12737,12738,12739,12740,131340,12741,131281,131277,12742,12743,131275,139240,12744,131274,12745,12746,12747,12748,131342,12749,12750,256,193,461,192,274,201,282,200,332,211,465,210,null,7870,null,7872,202,257,225,462,224,593,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,null,7871,null,7873,234,609,9178,9179,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,172969,135493,null,25866,null,null,20029,28381,40270,37343,null,null,161589,25745,20250,20264,20392,20822,20852,20892,20964,21153,21160,21307,21326,21457,21464,22242,22768,22788,22791,22834,22836,23398,23454,23455,23706,24198,24635,25993,26622,26628,26725,27982,28860,30005,32420,32428,32442,32455,32463,32479,32518,32567,33402,33487,33647,35270,35774,35810,36710,36711,36718,29713,31996,32205,26950,31433,21031,null,null,null,null,37260,30904,37214,32956,null,36107,33014,133607,null,null,32927,40647,19661,40393,40460,19518,171510,159758,40458,172339,13761,null,28314,33342,29977,null,18705,39532,39567,40857,31111,164972,138698,132560,142054,20004,20097,20096,20103,20159,20203,20279,13388,20413,15944,20483,20616,13437,13459,13477,20870,22789,20955,20988,20997,20105,21113,21136,21287,13767,21417,13649,21424,13651,21442,21539,13677,13682,13953,21651,21667,21684,21689,21712,21743,21784,21795,21800,13720,21823,13733,13759,21975,13765,163204,21797,null,134210,134421,151851,21904,142534,14828,131905,36422,150968,169189,16467,164030,30586,142392,14900,18389,164189,158194,151018,25821,134524,135092,134357,135412,25741,36478,134806,134155,135012,142505,164438,148691,null,134470,170573,164073,18420,151207,142530,39602,14951,169460,16365,13574,152263,169940,161992,142660,40302,38933,null,17369,155813,25780,21731,142668,142282,135287,14843,135279,157402,157462,162208,25834,151634,134211,36456,139681,166732,132913,null,18443,131497,16378,22643,142733,null,148936,132348,155799,134988,134550,21881,16571,17338,null,19124,141926,135325,33194,39157,134556,25465,14846,141173,36288,22177,25724,15939,null,173569,134665,142031,142537,null,135368,145858,14738,14854,164507,13688,155209,139463,22098,134961,142514,169760,13500,27709,151099,null,null,161140,142987,139784,173659,167117,134778,134196,157724,32659,135375,141315,141625,13819,152035,134796,135053,134826,16275,134960,134471,135503,134732,null,134827,134057,134472,135360,135485,16377,140950,25650,135085,144372,161337,142286,134526,134527,142417,142421,14872,134808,135367,134958,173618,158544,167122,167321,167114,38314,21708,33476,21945,null,171715,39974,39606,161630,142830,28992,33133,33004,23580,157042,33076,14231,21343,164029,37302,134906,134671,134775,134907,13789,151019,13833,134358,22191,141237,135369,134672,134776,135288,135496,164359,136277,134777,151120,142756,23124,135197,135198,135413,135414,22428,134673,161428,164557,135093,134779,151934,14083,135094,135552,152280,172733,149978,137274,147831,164476,22681,21096,13850,153405,31666,23400,18432,19244,40743,18919,39967,39821,154484,143677,22011,13810,22153,20008,22786,138177,194680,38737,131206,20059,20155,13630,23587,24401,24516,14586,25164,25909,27514,27701,27706,28780,29227,20012,29357,149737,32594,31035,31993,32595,156266,13505,null,156491,32770,32896,157202,158033,21341,34916,35265,161970,35744,36125,38021,38264,38271,38376,167439,38886,39029,39118,39134,39267,17e4,40060,40479,40644,27503,63751,20023,131207,38429,25143,38050,null,20539,28158,171123,40870,15817,34959,147790,28791,23797,19232,152013,13657,154928,24866,166450,36775,37366,29073,26393,29626,144001,172295,15499,137600,19216,30948,29698,20910,165647,16393,27235,172730,16931,34319,133743,31274,170311,166634,38741,28749,21284,139390,37876,30425,166371,40871,30685,20131,20464,20668,20015,20247,40872,21556,32139,22674,22736,138678,24210,24217,24514,141074,25995,144377,26905,27203,146531,27903,null,29184,148741,29580,16091,150035,23317,29881,35715,154788,153237,31379,31724,31939,32364,33528,34199,40873,34960,40874,36537,40875,36815,34143,39392,37409,40876,167353,136255,16497,17058,23066,null,null,null,39016,26475,17014,22333,null,34262,149883,33471,160013,19585,159092,23931,158485,159678,40877,40878,23446,40879,26343,32347,28247,31178,15752,17603,143958,141206,17306,17718,null,23765,146202,35577,23672,15634,144721,23928,40882,29015,17752,147692,138787,19575,14712,13386,131492,158785,35532,20404,131641,22975,33132,38998,170234,24379,134047,null,139713,166253,16642,18107,168057,16135,40883,172469,16632,14294,18167,158790,16764,165554,160767,17773,14548,152730,17761,17691,19849,19579,19830,17898,16328,150287,13921,17630,17597,16877,23870,23880,23894,15868,14351,23972,23993,14368,14392,24130,24253,24357,24451,14600,14612,14655,14669,24791,24893,23781,14729,25015,25017,25039,14776,25132,25232,25317,25368,14840,22193,14851,25570,25595,25607,25690,14923,25792,23829,22049,40863,14999,25990,15037,26111,26195,15090,26258,15138,26390,15170,26532,26624,15192,26698,26756,15218,15217,15227,26889,26947,29276,26980,27039,27013,15292,27094,15325,27237,27252,27249,27266,15340,27289,15346,27307,27317,27348,27382,27521,27585,27626,27765,27818,15563,27906,27910,27942,28033,15599,28068,28081,28181,28184,28201,28294,166336,28347,28386,28378,40831,28392,28393,28452,28468,15686,147265,28545,28606,15722,15733,29111,23705,15754,28716,15761,28752,28756,28783,28799,28809,131877,17345,13809,134872,147159,22462,159443,28990,153568,13902,27042,166889,23412,31305,153825,169177,31333,31357,154028,31419,31408,31426,31427,29137,156813,16842,31450,31453,31466,16879,21682,154625,31499,31573,31529,152334,154878,31650,31599,33692,154548,158847,31696,33825,31634,31672,154912,15789,154725,33938,31738,31750,31797,154817,31812,31875,149634,31910,26237,148856,31945,31943,31974,31860,31987,31989,31950,32359,17693,159300,32093,159446,29837,32137,32171,28981,32179,32210,147543,155689,32228,15635,32245,137209,32229,164717,32285,155937,155994,32366,32402,17195,37996,32295,32576,32577,32583,31030,156368,39393,32663,156497,32675,136801,131176,17756,145254,17667,164666,32762,156809,32773,32776,32797,32808,32815,172167,158915,32827,32828,32865,141076,18825,157222,146915,157416,26405,32935,166472,33031,33050,22704,141046,27775,156824,151480,25831,136330,33304,137310,27219,150117,150165,17530,33321,133901,158290,146814,20473,136445,34018,33634,158474,149927,144688,137075,146936,33450,26907,194964,16859,34123,33488,33562,134678,137140,14017,143741,144730,33403,33506,33560,147083,159139,158469,158615,144846,15807,33565,21996,33669,17675,159141,33708,33729,33747,13438,159444,27223,34138,13462,159298,143087,33880,154596,33905,15827,17636,27303,33866,146613,31064,33960,158614,159351,159299,34014,33807,33681,17568,33939,34020,154769,16960,154816,17731,34100,23282,159385,17703,34163,17686,26559,34326,165413,165435,34241,159880,34306,136578,159949,194994,17770,34344,13896,137378,21495,160666,34430,34673,172280,34798,142375,34737,34778,34831,22113,34412,26710,17935,34885,34886,161248,146873,161252,34910,34972,18011,34996,34997,25537,35013,30583,161551,35207,35210,35238,35241,35239,35260,166437,35303,162084,162493,35484,30611,37374,35472,162393,31465,162618,147343,18195,162616,29052,35596,35615,152624,152933,35647,35660,35661,35497,150138,35728,35739,35503,136927,17941,34895,35995,163156,163215,195028,14117,163155,36054,163224,163261,36114,36099,137488,36059,28764,36113,150729,16080,36215,36265,163842,135188,149898,15228,164284,160012,31463,36525,36534,36547,37588,36633,36653,164709,164882,36773,37635,172703,133712,36787,18730,166366,165181,146875,24312,143970,36857,172052,165564,165121,140069,14720,159447,36919,165180,162494,36961,165228,165387,37032,165651,37060,165606,37038,37117,37223,15088,37289,37316,31916,166195,138889,37390,27807,37441,37474,153017,37561,166598,146587,166668,153051,134449,37676,37739,166625,166891,28815,23235,166626,166629,18789,37444,166892,166969,166911,37747,37979,36540,38277,38310,37926,38304,28662,17081,140922,165592,135804,146990,18911,27676,38523,38550,16748,38563,159445,25050,38582,30965,166624,38589,21452,18849,158904,131700,156688,168111,168165,150225,137493,144138,38705,34370,38710,18959,17725,17797,150249,28789,23361,38683,38748,168405,38743,23370,168427,38751,37925,20688,143543,143548,38793,38815,38833,38846,38848,38866,38880,152684,38894,29724,169011,38911,38901,168989,162170,19153,38964,38963,38987,39014,15118,160117,15697,132656,147804,153350,39114,39095,39112,39111,19199,159015,136915,21936,39137,39142,39148,37752,39225,150057,19314,170071,170245,39413,39436,39483,39440,39512,153381,14020,168113,170965,39648,39650,170757,39668,19470,39700,39725,165376,20532,39732,158120,14531,143485,39760,39744,171326,23109,137315,39822,148043,39938,39935,39948,171624,40404,171959,172434,172459,172257,172323,172511,40318,40323,172340,40462,26760,40388,139611,172435,172576,137531,172595,40249,172217,172724,40592,40597,40606,40610,19764,40618,40623,148324,40641,15200,14821,15645,20274,14270,166955,40706,40712,19350,37924,159138,40727,40726,40761,22175,22154,40773,39352,168075,38898,33919,40802,40809,31452,40846,29206,19390,149877,149947,29047,150008,148296,150097,29598,166874,137466,31135,166270,167478,37737,37875,166468,37612,37761,37835,166252,148665,29207,16107,30578,31299,28880,148595,148472,29054,137199,28835,137406,144793,16071,137349,152623,137208,14114,136955,137273,14049,137076,137425,155467,14115,136896,22363,150053,136190,135848,136134,136374,34051,145062,34051,33877,149908,160101,146993,152924,147195,159826,17652,145134,170397,159526,26617,14131,15381,15847,22636,137506,26640,16471,145215,147681,147595,147727,158753,21707,22174,157361,22162,135135,134056,134669,37830,166675,37788,20216,20779,14361,148534,20156,132197,131967,20299,20362,153169,23144,131499,132043,14745,131850,132116,13365,20265,131776,167603,131701,35546,131596,20120,20685,20749,20386,20227,150030,147082,20290,20526,20588,20609,20428,20453,20568,20732,20825,20827,20829,20830,28278,144789,147001,147135,28018,137348,147081,20904,20931,132576,17629,132259,132242,132241,36218,166556,132878,21081,21156,133235,21217,37742,18042,29068,148364,134176,149932,135396,27089,134685,29817,16094,29849,29716,29782,29592,19342,150204,147597,21456,13700,29199,147657,21940,131909,21709,134086,22301,37469,38644,37734,22493,22413,22399,13886,22731,23193,166470,136954,137071,136976,23084,22968,37519,23166,23247,23058,153926,137715,137313,148117,14069,27909,29763,23073,155267,23169,166871,132115,37856,29836,135939,28933,18802,37896,166395,37821,14240,23582,23710,24158,24136,137622,137596,146158,24269,23375,137475,137476,14081,137376,14045,136958,14035,33066,166471,138682,144498,166312,24332,24334,137511,137131,23147,137019,23364,34324,161277,34912,24702,141408,140843,24539,16056,140719,140734,168072,159603,25024,131134,131142,140827,24985,24984,24693,142491,142599,149204,168269,25713,149093,142186,14889,142114,144464,170218,142968,25399,173147,25782,25393,25553,149987,142695,25252,142497,25659,25963,26994,15348,143502,144045,149897,144043,21773,144096,137433,169023,26318,144009,143795,15072,16784,152964,166690,152975,136956,152923,152613,30958,143619,137258,143924,13412,143887,143746,148169,26254,159012,26219,19347,26160,161904,138731,26211,144082,144097,26142,153714,14545,145466,145340,15257,145314,144382,29904,15254,26511,149034,26806,26654,15300,27326,14435,145365,148615,27187,27218,27337,27397,137490,25873,26776,27212,15319,27258,27479,147392,146586,37792,37618,166890,166603,37513,163870,166364,37991,28069,28427,149996,28007,147327,15759,28164,147516,23101,28170,22599,27940,30786,28987,148250,148086,28913,29264,29319,29332,149391,149285,20857,150180,132587,29818,147192,144991,150090,149783,155617,16134,16049,150239,166947,147253,24743,16115,29900,29756,37767,29751,17567,159210,17745,30083,16227,150745,150790,16216,30037,30323,173510,15129,29800,166604,149931,149902,15099,15821,150094,16127,149957,149747,37370,22322,37698,166627,137316,20703,152097,152039,30584,143922,30478,30479,30587,149143,145281,14942,149744,29752,29851,16063,150202,150215,16584,150166,156078,37639,152961,30750,30861,30856,30930,29648,31065,161601,153315,16654,31131,33942,31141,27181,147194,31290,31220,16750,136934,16690,37429,31217,134476,149900,131737,146874,137070,13719,21867,13680,13994,131540,134157,31458,23129,141045,154287,154268,23053,131675,30960,23082,154566,31486,16889,31837,31853,16913,154547,155324,155302,31949,150009,137136,31886,31868,31918,27314,32220,32263,32211,32590,156257,155996,162632,32151,155266,17002,158581,133398,26582,131150,144847,22468,156690,156664,149858,32733,31527,133164,154345,154947,31500,155150,39398,34373,39523,27164,144447,14818,150007,157101,39455,157088,33920,160039,158929,17642,33079,17410,32966,33033,33090,157620,39107,158274,33378,33381,158289,33875,159143,34320,160283,23174,16767,137280,23339,137377,23268,137432,34464,195004,146831,34861,160802,23042,34926,20293,34951,35007,35046,35173,35149,153219,35156,161669,161668,166901,166873,166812,166393,16045,33955,18165,18127,14322,35389,35356,169032,24397,37419,148100,26068,28969,28868,137285,40301,35999,36073,163292,22938,30659,23024,17262,14036,36394,36519,150537,36656,36682,17140,27736,28603,140065,18587,28537,28299,137178,39913,14005,149807,37051,37015,21873,18694,37307,37892,166475,16482,166652,37927,166941,166971,34021,35371,38297,38311,38295,38294,167220,29765,16066,149759,150082,148458,16103,143909,38543,167655,167526,167525,16076,149997,150136,147438,29714,29803,16124,38721,168112,26695,18973,168083,153567,38749,37736,166281,166950,166703,156606,37562,23313,35689,18748,29689,147995,38811,38769,39224,134950,24001,166853,150194,38943,169178,37622,169431,37349,17600,166736,150119,166756,39132,166469,16128,37418,18725,33812,39227,39245,162566,15869,39323,19311,39338,39516,166757,153800,27279,39457,23294,39471,170225,19344,170312,39356,19389,19351,37757,22642,135938,22562,149944,136424,30788,141087,146872,26821,15741,37976,14631,24912,141185,141675,24839,40015,40019,40059,39989,39952,39807,39887,171565,39839,172533,172286,40225,19630,147716,40472,19632,40204,172468,172269,172275,170287,40357,33981,159250,159711,158594,34300,17715,159140,159364,159216,33824,34286,159232,145367,155748,31202,144796,144960,18733,149982,15714,37851,37566,37704,131775,30905,37495,37965,20452,13376,36964,152925,30781,30804,30902,30795,137047,143817,149825,13978,20338,28634,28633,28702,28702,21524,147893,22459,22771,22410,40214,22487,28980,13487,147884,29163,158784,151447,23336,137141,166473,24844,23246,23051,17084,148616,14124,19323,166396,37819,37816,137430,134941,33906,158912,136211,148218,142374,148417,22932,146871,157505,32168,155995,155812,149945,149899,166394,37605,29666,16105,29876,166755,137375,16097,150195,27352,29683,29691,16086,150078,150164,137177,150118,132007,136228,149989,29768,149782,28837,149878,37508,29670,37727,132350,37681,166606,166422,37766,166887,153045,18741,166530,29035,149827,134399,22180,132634,134123,134328,21762,31172,137210,32254,136898,150096,137298,17710,37889,14090,166592,149933,22960,137407,137347,160900,23201,14050,146779,14e3,37471,23161,166529,137314,37748,15565,133812,19094,14730,20724,15721,15692,136092,29045,17147,164376,28175,168164,17643,27991,163407,28775,27823,15574,147437,146989,28162,28428,15727,132085,30033,14012,13512,18048,16090,18545,22980,37486,18750,36673,166940,158656,22546,22472,14038,136274,28926,148322,150129,143331,135856,140221,26809,26983,136088,144613,162804,145119,166531,145366,144378,150687,27162,145069,158903,33854,17631,17614,159014,159057,158850,159710,28439,160009,33597,137018,33773,158848,159827,137179,22921,23170,137139,23137,23153,137477,147964,14125,23023,137020,14023,29070,37776,26266,148133,23150,23083,148115,27179,147193,161590,148571,148170,28957,148057,166369,20400,159016,23746,148686,163405,148413,27148,148054,135940,28838,28979,148457,15781,27871,194597,150095,32357,23019,23855,15859,24412,150109,137183,32164,33830,21637,146170,144128,131604,22398,133333,132633,16357,139166,172726,28675,168283,23920,29583,31955,166489,168992,20424,32743,29389,29456,162548,29496,29497,153334,29505,29512,16041,162584,36972,29173,149746,29665,33270,16074,30476,16081,27810,22269,29721,29726,29727,16098,16112,16116,16122,29907,16142,16211,30018,30061,30066,30093,16252,30152,30172,16320,30285,16343,30324,16348,30330,151388,29064,22051,35200,22633,16413,30531,16441,26465,16453,13787,30616,16490,16495,23646,30654,30667,22770,30744,28857,30748,16552,30777,30791,30801,30822,33864,152885,31027,26627,31026,16643,16649,31121,31129,36795,31238,36796,16743,31377,16818,31420,33401,16836,31439,31451,16847,20001,31586,31596,31611,31762,31771,16992,17018,31867,31900,17036,31928,17044,31981,36755,28864,134351,32207,32212,32208,32253,32686,32692,29343,17303,32800,32805,31545,32814,32817,32852,15820,22452,28832,32951,33001,17389,33036,29482,33038,33042,30048,33044,17409,15161,33110,33113,33114,17427,22586,33148,33156,17445,33171,17453,33189,22511,33217,33252,33364,17551,33446,33398,33482,33496,33535,17584,33623,38505,27018,33797,28917,33892,24803,33928,17668,33982,34017,34040,34064,34104,34130,17723,34159,34160,34272,17783,34418,34450,34482,34543,38469,34699,17926,17943,34990,35071,35108,35143,35217,162151,35369,35384,35476,35508,35921,36052,36082,36124,18328,22623,36291,18413,20206,36410,21976,22356,36465,22005,36528,18487,36558,36578,36580,36589,36594,36791,36801,36810,36812,36915,39364,18605,39136,37395,18718,37416,37464,37483,37553,37550,37567,37603,37611,37619,37620,37629,37699,37764,37805,18757,18769,40639,37911,21249,37917,37933,37950,18794,37972,38009,38189,38306,18855,38388,38451,18917,26528,18980,38720,18997,38834,38850,22100,19172,24808,39097,19225,39153,22596,39182,39193,20916,39196,39223,39234,39261,39266,19312,39365,19357,39484,39695,31363,39785,39809,39901,39921,39924,19565,39968,14191,138178,40265,39994,40702,22096,40339,40381,40384,40444,38134,36790,40571,40620,40625,40637,40646,38108,40674,40689,40696,31432,40772,131220,131767,132e3,26906,38083,22956,132311,22592,38081,14265,132565,132629,132726,136890,22359,29043,133826,133837,134079,21610,194619,134091,21662,134139,134203,134227,134245,134268,24807,134285,22138,134325,134365,134381,134511,134578,134600,26965,39983,34725,134660,134670,134871,135056,134957,134771,23584,135100,24075,135260,135247,135286,26398,135291,135304,135318,13895,135359,135379,135471,135483,21348,33965,135907,136053,135990,35713,136567,136729,137155,137159,20088,28859,137261,137578,137773,137797,138282,138352,138412,138952,25283,138965,139029,29080,26709,139333,27113,14024,139900,140247,140282,141098,141425,141647,33533,141671,141715,142037,35237,142056,36768,142094,38840,142143,38983,39613,142412,null,142472,142519,154600,142600,142610,142775,142741,142914,143220,143308,143411,143462,144159,144350,24497,26184,26303,162425,144743,144883,29185,149946,30679,144922,145174,32391,131910,22709,26382,26904,146087,161367,155618,146961,147129,161278,139418,18640,19128,147737,166554,148206,148237,147515,148276,148374,150085,132554,20946,132625,22943,138920,15294,146687,148484,148694,22408,149108,14747,149295,165352,170441,14178,139715,35678,166734,39382,149522,149755,150037,29193,150208,134264,22885,151205,151430,132985,36570,151596,21135,22335,29041,152217,152601,147274,150183,21948,152646,152686,158546,37332,13427,152895,161330,152926,18200,152930,152934,153543,149823,153693,20582,13563,144332,24798,153859,18300,166216,154286,154505,154630,138640,22433,29009,28598,155906,162834,36950,156082,151450,35682,156674,156746,23899,158711,36662,156804,137500,35562,150006,156808,147439,156946,19392,157119,157365,141083,37989,153569,24981,23079,194765,20411,22201,148769,157436,20074,149812,38486,28047,158909,13848,35191,157593,157806,156689,157790,29151,157895,31554,168128,133649,157990,37124,158009,31301,40432,158202,39462,158253,13919,156777,131105,31107,158260,158555,23852,144665,33743,158621,18128,158884,30011,34917,159150,22710,14108,140685,159819,160205,15444,160384,160389,37505,139642,160395,37680,160486,149968,27705,38047,160848,134904,34855,35061,141606,164979,137137,28344,150058,137248,14756,14009,23568,31203,17727,26294,171181,170148,35139,161740,161880,22230,16607,136714,14753,145199,164072,136133,29101,33638,162269,168360,23143,19639,159919,166315,162301,162314,162571,163174,147834,31555,31102,163849,28597,172767,27139,164632,21410,159239,37823,26678,38749,164207,163875,158133,136173,143919,163912,23941,166960,163971,22293,38947,166217,23979,149896,26046,27093,21458,150181,147329,15377,26422,163984,164084,164142,139169,164175,164233,164271,164378,164614,164655,164746,13770,164968,165546,18682,25574,166230,30728,37461,166328,17394,166375,17375,166376,166726,166868,23032,166921,36619,167877,168172,31569,168208,168252,15863,168286,150218,36816,29327,22155,169191,169449,169392,169400,169778,170193,170313,170346,170435,170536,170766,171354,171419,32415,171768,171811,19620,38215,172691,29090,172799,19857,36882,173515,19868,134300,36798,21953,36794,140464,36793,150163,17673,32383,28502,27313,20202,13540,166700,161949,14138,36480,137205,163876,166764,166809,162366,157359,15851,161365,146615,153141,153942,20122,155265,156248,22207,134765,36366,23405,147080,150686,25566,25296,137206,137339,25904,22061,154698,21530,152337,15814,171416,19581,22050,22046,32585,155352,22901,146752,34672,19996,135146,134473,145082,33047,40286,36120,30267,40005,30286,30649,37701,21554,33096,33527,22053,33074,33816,32957,21994,31074,22083,21526,134813,13774,22021,22001,26353,164578,13869,30004,22e3,21946,21655,21874,134209,134294,24272,151880,134774,142434,134818,40619,32090,21982,135285,25245,38765,21652,36045,29174,37238,25596,25529,25598,21865,142147,40050,143027,20890,13535,134567,20903,21581,21790,21779,30310,36397,157834,30129,32950,34820,34694,35015,33206,33820,135361,17644,29444,149254,23440,33547,157843,22139,141044,163119,147875,163187,159440,160438,37232,135641,37384,146684,173737,134828,134905,29286,138402,18254,151490,163833,135147,16634,40029,25887,142752,18675,149472,171388,135148,134666,24674,161187,135149,null,155720,135559,29091,32398,40272,19994,19972,13687,23309,27826,21351,13996,14812,21373,13989,149016,22682,150382,33325,21579,22442,154261,133497,null,14930,140389,29556,171692,19721,39917,146686,171824,19547,151465,169374,171998,33884,146870,160434,157619,145184,25390,32037,147191,146988,14890,36872,21196,15988,13946,17897,132238,30272,23280,134838,30842,163630,22695,16575,22140,39819,23924,30292,173108,40581,19681,30201,14331,24857,143578,148466,null,22109,135849,22439,149859,171526,21044,159918,13741,27722,40316,31830,39737,22494,137068,23635,25811,169168,156469,160100,34477,134440,159010,150242,134513,null,20990,139023,23950,38659,138705,40577,36940,31519,39682,23761,31651,25192,25397,39679,31695,39722,31870,39726,31810,31878,39957,31740,39689,40727,39963,149822,40794,21875,23491,20477,40600,20466,21088,15878,21201,22375,20566,22967,24082,38856,40363,36700,21609,38836,39232,38842,21292,24880,26924,21466,39946,40194,19515,38465,27008,20646,30022,137069,39386,21107,null,37209,38529,37212,null,37201,167575,25471,159011,27338,22033,37262,30074,25221,132092,29519,31856,154657,146685,null,149785,30422,39837,20010,134356,33726,34882,null,23626,27072,20717,22394,21023,24053,20174,27697,131570,20281,21660,21722,21146,36226,13822,24332,13811,null,27474,37244,40869,39831,38958,39092,39610,40616,40580,29050,31508,null,27642,34840,32632,null,22048,173642,36471,40787,null,36308,36431,40476,36353,25218,164733,36392,36469,31443,150135,31294,30936,27882,35431,30215,166490,40742,27854,34774,30147,172722,30803,194624,36108,29410,29553,35629,29442,29937,36075,150203,34351,24506,34976,17591,null,137275,159237,null,35454,140571,null,24829,30311,39639,40260,37742,39823,34805,null,34831,36087,29484,38689,39856,13782,29362,19463,31825,39242,155993,24921,19460,40598,24957,null,22367,24943,25254,25145,25294,14940,25058,21418,144373,25444,26626,13778,23895,166850,36826,167481,null,20697,138566,30982,21298,38456,134971,16485,null,30718,null,31938,155418,31962,31277,32870,32867,32077,29957,29938,35220,33306,26380,32866,160902,32859,29936,33027,30500,35209,157644,30035,159441,34729,34766,33224,34700,35401,36013,35651,30507,29944,34010,13877,27058,36262,null,35241,29800,28089,34753,147473,29927,15835,29046,24740,24988,15569,29026,24695,null,32625,166701,29264,24809,19326,21024,15384,146631,155351,161366,152881,137540,135934,170243,159196,159917,23745,156077,166415,145015,131310,157766,151310,17762,23327,156492,40784,40614,156267,12288,65292,12289,12290,65294,8231,65307,65306,65311,65281,65072,8230,8229,65104,65105,65106,183,65108,65109,65110,65111,65372,8211,65073,8212,65075,9588,65076,65103,65288,65289,65077,65078,65371,65373,65079,65080,12308,12309,65081,65082,12304,12305,65083,65084,12298,12299,65085,65086,12296,12297,65087,65088,12300,12301,65089,65090,12302,12303,65091,65092,65113,65114,65115,65116,65117,65118,8216,8217,8220,8221,12317,12318,8245,8242,65283,65286,65290,8251,167,12291,9675,9679,9651,9650,9678,9734,9733,9671,9670,9633,9632,9661,9660,12963,8453,175,65507,65343,717,65097,65098,65101,65102,65099,65100,65119,65120,65121,65291,65293,215,247,177,8730,65308,65310,65309,8806,8807,8800,8734,8786,8801,65122,65123,65124,65125,65126,65374,8745,8746,8869,8736,8735,8895,13266,13265,8747,8750,8757,8756,9792,9794,8853,8857,8593,8595,8592,8594,8598,8599,8601,8600,8741,8739,65295,65340,8725,65128,65284,65509,12306,65504,65505,65285,65312,8451,8457,65129,65130,65131,13269,13212,13213,13214,13262,13217,13198,13199,13252,176,20825,20827,20830,20829,20833,20835,21991,29929,31950,9601,9602,9603,9604,9605,9606,9607,9608,9615,9614,9613,9612,9611,9610,9609,9532,9524,9516,9508,9500,9620,9472,9474,9621,9484,9488,9492,9496,9581,9582,9584,9583,9552,9566,9578,9569,9698,9699,9701,9700,9585,9586,9587,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,12321,12322,12323,12324,12325,12326,12327,12328,12329,21313,21316,21317,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,729,713,714,711,715,9216,9217,9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,9249,8364,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19968,20057,19969,19971,20035,20061,20102,20108,20154,20799,20837,20843,20960,20992,20993,21147,21269,21313,21340,21448,19977,19979,19976,19978,20011,20024,20961,20037,20040,20063,20062,20110,20129,20800,20995,21242,21315,21449,21475,22303,22763,22805,22823,22899,23376,23377,23379,23544,23567,23586,23608,23665,24029,24037,24049,24050,24051,24062,24178,24318,24331,24339,25165,19985,19984,19981,20013,20016,20025,20043,23609,20104,20113,20117,20114,20116,20130,20161,20160,20163,20166,20167,20173,20170,20171,20164,20803,20801,20839,20845,20846,20844,20887,20982,20998,20999,21e3,21243,21246,21247,21270,21305,21320,21319,21317,21342,21380,21451,21450,21453,22764,22825,22827,22826,22829,23380,23569,23588,23610,23663,24052,24187,24319,24340,24341,24515,25096,25142,25163,25166,25903,25991,26007,26020,26041,26085,26352,26376,26408,27424,27490,27513,27595,27604,27611,27663,27700,28779,29226,29238,29243,29255,29273,29275,29356,29579,19993,19990,19989,19988,19992,20027,20045,20047,20046,20197,20184,20180,20181,20182,20183,20195,20196,20185,20190,20805,20804,20873,20874,20908,20985,20986,20984,21002,21152,21151,21253,21254,21271,21277,20191,21322,21321,21345,21344,21359,21358,21435,21487,21476,21491,21484,21486,21481,21480,21500,21496,21493,21483,21478,21482,21490,21489,21488,21477,21485,21499,22235,22234,22806,22830,22833,22900,22902,23381,23427,23612,24040,24039,24038,24066,24067,24179,24188,24321,24344,24343,24517,25098,25171,25172,25170,25169,26021,26086,26414,26412,26410,26411,26413,27491,27597,27665,27664,27704,27713,27712,27710,29359,29572,29577,29916,29926,29976,29983,29992,29993,3e4,30001,30002,30003,30091,30333,30382,30399,30446,30683,30690,30707,31034,31166,31348,31435,19998,19999,20050,20051,20073,20121,20132,20134,20133,20223,20233,20249,20234,20245,20237,20240,20241,20239,20210,20214,20219,20208,20211,20221,20225,20235,20809,20807,20806,20808,20840,20849,20877,20912,21015,21009,21010,21006,21014,21155,21256,21281,21280,21360,21361,21513,21519,21516,21514,21520,21505,21515,21508,21521,21517,21512,21507,21518,21510,21522,22240,22238,22237,22323,22320,22312,22317,22316,22319,22313,22809,22810,22839,22840,22916,22904,22915,22909,22905,22914,22913,23383,23384,23431,23432,23429,23433,23546,23574,23673,24030,24070,24182,24180,24335,24347,24537,24534,25102,25100,25101,25104,25187,25179,25176,25910,26089,26088,26092,26093,26354,26355,26377,26429,26420,26417,26421,27425,27492,27515,27670,27741,27735,27737,27743,27744,27728,27733,27745,27739,27725,27726,28784,29279,29277,30334,31481,31859,31992,32566,32650,32701,32769,32771,32780,32786,32819,32895,32905,32907,32908,33251,33258,33267,33276,33292,33307,33311,33390,33394,33406,34411,34880,34892,34915,35199,38433,20018,20136,20301,20303,20295,20311,20318,20276,20315,20309,20272,20304,20305,20285,20282,20280,20291,20308,20284,20294,20323,20316,20320,20271,20302,20278,20313,20317,20296,20314,20812,20811,20813,20853,20918,20919,21029,21028,21033,21034,21032,21163,21161,21162,21164,21283,21363,21365,21533,21549,21534,21566,21542,21582,21543,21574,21571,21555,21576,21570,21531,21545,21578,21561,21563,21560,21550,21557,21558,21536,21564,21568,21553,21547,21535,21548,22250,22256,22244,22251,22346,22353,22336,22349,22343,22350,22334,22352,22351,22331,22767,22846,22941,22930,22952,22942,22947,22937,22934,22925,22948,22931,22922,22949,23389,23388,23386,23387,23436,23435,23439,23596,23616,23617,23615,23614,23696,23697,23700,23692,24043,24076,24207,24199,24202,24311,24324,24351,24420,24418,24439,24441,24536,24524,24535,24525,24561,24555,24568,24554,25106,25105,25220,25239,25238,25216,25206,25225,25197,25226,25212,25214,25209,25203,25234,25199,25240,25198,25237,25235,25233,25222,25913,25915,25912,26097,26356,26463,26446,26447,26448,26449,26460,26454,26462,26441,26438,26464,26451,26455,27493,27599,27714,27742,27801,27777,27784,27785,27781,27803,27754,27770,27792,27760,27788,27752,27798,27794,27773,27779,27762,27774,27764,27782,27766,27789,27796,27800,27778,28790,28796,28797,28792,29282,29281,29280,29380,29378,29590,29996,29995,30007,30008,30338,30447,30691,31169,31168,31167,31350,31995,32597,32918,32915,32925,32920,32923,32922,32946,33391,33426,33419,33421,35211,35282,35328,35895,35910,35925,35997,36196,36208,36275,36523,36554,36763,36784,36802,36806,36805,36804,24033,37009,37026,37034,37030,37027,37193,37318,37324,38450,38446,38449,38442,38444,20006,20054,20083,20107,20123,20126,20139,20140,20335,20381,20365,20339,20351,20332,20379,20363,20358,20355,20336,20341,20360,20329,20347,20374,20350,20367,20369,20346,20820,20818,20821,20841,20855,20854,20856,20925,20989,21051,21048,21047,21050,21040,21038,21046,21057,21182,21179,21330,21332,21331,21329,21350,21367,21368,21369,21462,21460,21463,21619,21621,21654,21624,21653,21632,21627,21623,21636,21650,21638,21628,21648,21617,21622,21644,21658,21602,21608,21643,21629,21646,22266,22403,22391,22378,22377,22369,22374,22372,22396,22812,22857,22855,22856,22852,22868,22974,22971,22996,22969,22958,22993,22982,22992,22989,22987,22995,22986,22959,22963,22994,22981,23391,23396,23395,23447,23450,23448,23452,23449,23451,23578,23624,23621,23622,23735,23713,23736,23721,23723,23729,23731,24088,24090,24086,24085,24091,24081,24184,24218,24215,24220,24213,24214,24310,24358,24359,24361,24448,24449,24447,24444,24541,24544,24573,24565,24575,24591,24596,24623,24629,24598,24618,24597,24609,24615,24617,24619,24603,25110,25109,25151,25150,25152,25215,25289,25292,25284,25279,25282,25273,25298,25307,25259,25299,25300,25291,25288,25256,25277,25276,25296,25305,25287,25293,25269,25306,25265,25304,25302,25303,25286,25260,25294,25918,26023,26044,26106,26132,26131,26124,26118,26114,26126,26112,26127,26133,26122,26119,26381,26379,26477,26507,26517,26481,26524,26483,26487,26503,26525,26519,26479,26480,26495,26505,26494,26512,26485,26522,26515,26492,26474,26482,27427,27494,27495,27519,27667,27675,27875,27880,27891,27825,27852,27877,27827,27837,27838,27836,27874,27819,27861,27859,27832,27844,27833,27841,27822,27863,27845,27889,27839,27835,27873,27867,27850,27820,27887,27868,27862,27872,28821,28814,28818,28810,28825,29228,29229,29240,29256,29287,29289,29376,29390,29401,29399,29392,29609,29608,29599,29611,29605,30013,30109,30105,30106,30340,30402,30450,30452,30693,30717,31038,31040,31041,31177,31176,31354,31353,31482,31998,32596,32652,32651,32773,32954,32933,32930,32945,32929,32939,32937,32948,32938,32943,33253,33278,33293,33459,33437,33433,33453,33469,33439,33465,33457,33452,33445,33455,33464,33443,33456,33470,33463,34382,34417,21021,34920,36555,36814,36820,36817,37045,37048,37041,37046,37319,37329,38263,38272,38428,38464,38463,38459,38468,38466,38585,38632,38738,38750,20127,20141,20142,20449,20405,20399,20415,20448,20433,20431,20445,20419,20406,20440,20447,20426,20439,20398,20432,20420,20418,20442,20430,20446,20407,20823,20882,20881,20896,21070,21059,21066,21069,21068,21067,21063,21191,21193,21187,21185,21261,21335,21371,21402,21467,21676,21696,21672,21710,21705,21688,21670,21683,21703,21698,21693,21674,21697,21700,21704,21679,21675,21681,21691,21673,21671,21695,22271,22402,22411,22432,22435,22434,22478,22446,22419,22869,22865,22863,22862,22864,23004,23e3,23039,23011,23016,23043,23013,23018,23002,23014,23041,23035,23401,23459,23462,23460,23458,23461,23553,23630,23631,23629,23627,23769,23762,24055,24093,24101,24095,24189,24224,24230,24314,24328,24365,24421,24456,24453,24458,24459,24455,24460,24457,24594,24605,24608,24613,24590,24616,24653,24688,24680,24674,24646,24643,24684,24683,24682,24676,25153,25308,25366,25353,25340,25325,25345,25326,25341,25351,25329,25335,25327,25324,25342,25332,25361,25346,25919,25925,26027,26045,26082,26149,26157,26144,26151,26159,26143,26152,26161,26148,26359,26623,26579,26609,26580,26576,26604,26550,26543,26613,26601,26607,26564,26577,26548,26586,26597,26552,26575,26590,26611,26544,26585,26594,26589,26578,27498,27523,27526,27573,27602,27607,27679,27849,27915,27954,27946,27969,27941,27916,27953,27934,27927,27963,27965,27966,27958,27931,27893,27961,27943,27960,27945,27950,27957,27918,27947,28843,28858,28851,28844,28847,28845,28856,28846,28836,29232,29298,29295,29300,29417,29408,29409,29623,29642,29627,29618,29645,29632,29619,29978,29997,30031,30028,30030,30027,30123,30116,30117,30114,30115,30328,30342,30343,30344,30408,30406,30403,30405,30465,30457,30456,30473,30475,30462,30460,30471,30684,30722,30740,30732,30733,31046,31049,31048,31047,31161,31162,31185,31186,31179,31359,31361,31487,31485,31869,32002,32005,32e3,32009,32007,32004,32006,32568,32654,32703,32772,32784,32781,32785,32822,32982,32997,32986,32963,32964,32972,32993,32987,32974,32990,32996,32989,33268,33314,33511,33539,33541,33507,33499,33510,33540,33509,33538,33545,33490,33495,33521,33537,33500,33492,33489,33502,33491,33503,33519,33542,34384,34425,34427,34426,34893,34923,35201,35284,35336,35330,35331,35998,36e3,36212,36211,36276,36557,36556,36848,36838,36834,36842,36837,36845,36843,36836,36840,37066,37070,37057,37059,37195,37194,37325,38274,38480,38475,38476,38477,38754,38761,38859,38893,38899,38913,39080,39131,39135,39318,39321,20056,20147,20492,20493,20515,20463,20518,20517,20472,20521,20502,20486,20540,20511,20506,20498,20497,20474,20480,20500,20520,20465,20513,20491,20505,20504,20467,20462,20525,20522,20478,20523,20489,20860,20900,20901,20898,20941,20940,20934,20939,21078,21084,21076,21083,21085,21290,21375,21407,21405,21471,21736,21776,21761,21815,21756,21733,21746,21766,21754,21780,21737,21741,21729,21769,21742,21738,21734,21799,21767,21757,21775,22275,22276,22466,22484,22475,22467,22537,22799,22871,22872,22874,23057,23064,23068,23071,23067,23059,23020,23072,23075,23081,23077,23052,23049,23403,23640,23472,23475,23478,23476,23470,23477,23481,23480,23556,23633,23637,23632,23789,23805,23803,23786,23784,23792,23798,23809,23796,24046,24109,24107,24235,24237,24231,24369,24466,24465,24464,24665,24675,24677,24656,24661,24685,24681,24687,24708,24735,24730,24717,24724,24716,24709,24726,25159,25331,25352,25343,25422,25406,25391,25429,25410,25414,25423,25417,25402,25424,25405,25386,25387,25384,25421,25420,25928,25929,26009,26049,26053,26178,26185,26191,26179,26194,26188,26181,26177,26360,26388,26389,26391,26657,26680,26696,26694,26707,26681,26690,26708,26665,26803,26647,26700,26705,26685,26612,26704,26688,26684,26691,26666,26693,26643,26648,26689,27530,27529,27575,27683,27687,27688,27686,27684,27888,28010,28053,28040,28039,28006,28024,28023,27993,28051,28012,28041,28014,27994,28020,28009,28044,28042,28025,28037,28005,28052,28874,28888,28900,28889,28872,28879,29241,29305,29436,29433,29437,29432,29431,29574,29677,29705,29678,29664,29674,29662,30036,30045,30044,30042,30041,30142,30149,30151,30130,30131,30141,30140,30137,30146,30136,30347,30384,30410,30413,30414,30505,30495,30496,30504,30697,30768,30759,30776,30749,30772,30775,30757,30765,30752,30751,30770,31061,31056,31072,31071,31062,31070,31069,31063,31066,31204,31203,31207,31199,31206,31209,31192,31364,31368,31449,31494,31505,31881,32033,32023,32011,32010,32032,32034,32020,32016,32021,32026,32028,32013,32025,32027,32570,32607,32660,32709,32705,32774,32792,32789,32793,32791,32829,32831,33009,33026,33008,33029,33005,33012,33030,33016,33011,33032,33021,33034,33020,33007,33261,33260,33280,33296,33322,33323,33320,33324,33467,33579,33618,33620,33610,33592,33616,33609,33589,33588,33615,33586,33593,33590,33559,33600,33585,33576,33603,34388,34442,34474,34451,34468,34473,34444,34467,34460,34928,34935,34945,34946,34941,34937,35352,35344,35342,35340,35349,35338,35351,35347,35350,35343,35345,35912,35962,35961,36001,36002,36215,36524,36562,36564,36559,36785,36865,36870,36855,36864,36858,36852,36867,36861,36869,36856,37013,37089,37085,37090,37202,37197,37196,37336,37341,37335,37340,37337,38275,38498,38499,38497,38491,38493,38500,38488,38494,38587,39138,39340,39592,39640,39717,39730,39740,20094,20602,20605,20572,20551,20547,20556,20570,20553,20581,20598,20558,20565,20597,20596,20599,20559,20495,20591,20589,20828,20885,20976,21098,21103,21202,21209,21208,21205,21264,21263,21273,21311,21312,21310,21443,26364,21830,21866,21862,21828,21854,21857,21827,21834,21809,21846,21839,21845,21807,21860,21816,21806,21852,21804,21859,21811,21825,21847,22280,22283,22281,22495,22533,22538,22534,22496,22500,22522,22530,22581,22519,22521,22816,22882,23094,23105,23113,23142,23146,23104,23100,23138,23130,23110,23114,23408,23495,23493,23492,23490,23487,23494,23561,23560,23559,23648,23644,23645,23815,23814,23822,23835,23830,23842,23825,23849,23828,23833,23844,23847,23831,24034,24120,24118,24115,24119,24247,24248,24246,24245,24254,24373,24375,24407,24428,24425,24427,24471,24473,24478,24472,24481,24480,24476,24703,24739,24713,24736,24744,24779,24756,24806,24765,24773,24763,24757,24796,24764,24792,24789,24774,24799,24760,24794,24775,25114,25115,25160,25504,25511,25458,25494,25506,25509,25463,25447,25496,25514,25457,25513,25481,25475,25499,25451,25512,25476,25480,25497,25505,25516,25490,25487,25472,25467,25449,25448,25466,25949,25942,25937,25945,25943,21855,25935,25944,25941,25940,26012,26011,26028,26063,26059,26060,26062,26205,26202,26212,26216,26214,26206,26361,21207,26395,26753,26799,26786,26771,26805,26751,26742,26801,26791,26775,26800,26755,26820,26797,26758,26757,26772,26781,26792,26783,26785,26754,27442,27578,27627,27628,27691,28046,28092,28147,28121,28082,28129,28108,28132,28155,28154,28165,28103,28107,28079,28113,28078,28126,28153,28088,28151,28149,28101,28114,28186,28085,28122,28139,28120,28138,28145,28142,28136,28102,28100,28074,28140,28095,28134,28921,28937,28938,28925,28911,29245,29309,29313,29468,29467,29462,29459,29465,29575,29701,29706,29699,29702,29694,29709,29920,29942,29943,29980,29986,30053,30054,30050,30064,30095,30164,30165,30133,30154,30157,30350,30420,30418,30427,30519,30526,30524,30518,30520,30522,30827,30787,30798,31077,31080,31085,31227,31378,31381,31520,31528,31515,31532,31526,31513,31518,31534,31890,31895,31893,32070,32067,32113,32046,32057,32060,32064,32048,32051,32068,32047,32066,32050,32049,32573,32670,32666,32716,32718,32722,32796,32842,32838,33071,33046,33059,33067,33065,33072,33060,33282,33333,33335,33334,33337,33678,33694,33688,33656,33698,33686,33725,33707,33682,33674,33683,33673,33696,33655,33659,33660,33670,33703,34389,24426,34503,34496,34486,34500,34485,34502,34507,34481,34479,34505,34899,34974,34952,34987,34962,34966,34957,34955,35219,35215,35370,35357,35363,35365,35377,35373,35359,35355,35362,35913,35930,36009,36012,36011,36008,36010,36007,36199,36198,36286,36282,36571,36575,36889,36877,36890,36887,36899,36895,36893,36880,36885,36894,36896,36879,36898,36886,36891,36884,37096,37101,37117,37207,37326,37365,37350,37347,37351,37357,37353,38281,38506,38517,38515,38520,38512,38516,38518,38519,38508,38592,38634,38633,31456,31455,38914,38915,39770,40165,40565,40575,40613,40635,20642,20621,20613,20633,20625,20608,20630,20632,20634,26368,20977,21106,21108,21109,21097,21214,21213,21211,21338,21413,21883,21888,21927,21884,21898,21917,21912,21890,21916,21930,21908,21895,21899,21891,21939,21934,21919,21822,21938,21914,21947,21932,21937,21886,21897,21931,21913,22285,22575,22570,22580,22564,22576,22577,22561,22557,22560,22777,22778,22880,23159,23194,23167,23186,23195,23207,23411,23409,23506,23500,23507,23504,23562,23563,23601,23884,23888,23860,23879,24061,24133,24125,24128,24131,24190,24266,24257,24258,24260,24380,24429,24489,24490,24488,24785,24801,24754,24758,24800,24860,24867,24826,24853,24816,24827,24820,24936,24817,24846,24822,24841,24832,24850,25119,25161,25507,25484,25551,25536,25577,25545,25542,25549,25554,25571,25552,25569,25558,25581,25582,25462,25588,25578,25563,25682,25562,25593,25950,25958,25954,25955,26001,26e3,26031,26222,26224,26228,26230,26223,26257,26234,26238,26231,26366,26367,26399,26397,26874,26837,26848,26840,26839,26885,26847,26869,26862,26855,26873,26834,26866,26851,26827,26829,26893,26898,26894,26825,26842,26990,26875,27454,27450,27453,27544,27542,27580,27631,27694,27695,27692,28207,28216,28244,28193,28210,28263,28234,28192,28197,28195,28187,28251,28248,28196,28246,28270,28205,28198,28271,28212,28237,28218,28204,28227,28189,28222,28363,28297,28185,28238,28259,28228,28274,28265,28255,28953,28954,28966,28976,28961,28982,29038,28956,29260,29316,29312,29494,29477,29492,29481,29754,29738,29747,29730,29733,29749,29750,29748,29743,29723,29734,29736,29989,29990,30059,30058,30178,30171,30179,30169,30168,30174,30176,30331,30332,30358,30355,30388,30428,30543,30701,30813,30828,30831,31245,31240,31243,31237,31232,31384,31383,31382,31461,31459,31561,31574,31558,31568,31570,31572,31565,31563,31567,31569,31903,31909,32094,32080,32104,32085,32043,32110,32114,32097,32102,32098,32112,32115,21892,32724,32725,32779,32850,32901,33109,33108,33099,33105,33102,33081,33094,33086,33100,33107,33140,33298,33308,33769,33795,33784,33805,33760,33733,33803,33729,33775,33777,33780,33879,33802,33776,33804,33740,33789,33778,33738,33848,33806,33796,33756,33799,33748,33759,34395,34527,34521,34541,34516,34523,34532,34512,34526,34903,35009,35010,34993,35203,35222,35387,35424,35413,35422,35388,35393,35412,35419,35408,35398,35380,35386,35382,35414,35937,35970,36015,36028,36019,36029,36033,36027,36032,36020,36023,36022,36031,36024,36234,36229,36225,36302,36317,36299,36314,36305,36300,36315,36294,36603,36600,36604,36764,36910,36917,36913,36920,36914,36918,37122,37109,37129,37118,37219,37221,37327,37396,37397,37411,37385,37406,37389,37392,37383,37393,38292,38287,38283,38289,38291,38290,38286,38538,38542,38539,38525,38533,38534,38541,38514,38532,38593,38597,38596,38598,38599,38639,38642,38860,38917,38918,38920,39143,39146,39151,39145,39154,39149,39342,39341,40643,40653,40657,20098,20653,20661,20658,20659,20677,20670,20652,20663,20667,20655,20679,21119,21111,21117,21215,21222,21220,21218,21219,21295,21983,21992,21971,21990,21966,21980,21959,21969,21987,21988,21999,21978,21985,21957,21958,21989,21961,22290,22291,22622,22609,22616,22615,22618,22612,22635,22604,22637,22602,22626,22610,22603,22887,23233,23241,23244,23230,23229,23228,23219,23234,23218,23913,23919,24140,24185,24265,24264,24338,24409,24492,24494,24858,24847,24904,24863,24819,24859,24825,24833,24840,24910,24908,24900,24909,24894,24884,24871,24845,24838,24887,25121,25122,25619,25662,25630,25642,25645,25661,25644,25615,25628,25620,25613,25654,25622,25623,25606,25964,26015,26032,26263,26249,26247,26248,26262,26244,26264,26253,26371,27028,26989,26970,26999,26976,26964,26997,26928,27010,26954,26984,26987,26974,26963,27001,27014,26973,26979,26971,27463,27506,27584,27583,27603,27645,28322,28335,28371,28342,28354,28304,28317,28359,28357,28325,28312,28348,28346,28331,28369,28310,28316,28356,28372,28330,28327,28340,29006,29017,29033,29028,29001,29031,29020,29036,29030,29004,29029,29022,28998,29032,29014,29242,29266,29495,29509,29503,29502,29807,29786,29781,29791,29790,29761,29759,29785,29787,29788,30070,30072,30208,30192,30209,30194,30193,30202,30207,30196,30195,30430,30431,30555,30571,30566,30558,30563,30585,30570,30572,30556,30565,30568,30562,30702,30862,30896,30871,30872,30860,30857,30844,30865,30867,30847,31098,31103,31105,33836,31165,31260,31258,31264,31252,31263,31262,31391,31392,31607,31680,31584,31598,31591,31921,31923,31925,32147,32121,32145,32129,32143,32091,32622,32617,32618,32626,32681,32680,32676,32854,32856,32902,32900,33137,33136,33144,33125,33134,33139,33131,33145,33146,33126,33285,33351,33922,33911,33853,33841,33909,33894,33899,33865,33900,33883,33852,33845,33889,33891,33897,33901,33862,34398,34396,34399,34553,34579,34568,34567,34560,34558,34555,34562,34563,34566,34570,34905,35039,35028,35033,35036,35032,35037,35041,35018,35029,35026,35228,35299,35435,35442,35443,35430,35433,35440,35463,35452,35427,35488,35441,35461,35437,35426,35438,35436,35449,35451,35390,35432,35938,35978,35977,36042,36039,36040,36036,36018,36035,36034,36037,36321,36319,36328,36335,36339,36346,36330,36324,36326,36530,36611,36617,36606,36618,36767,36786,36939,36938,36947,36930,36948,36924,36949,36944,36935,36943,36942,36941,36945,36926,36929,37138,37143,37228,37226,37225,37321,37431,37463,37432,37437,37440,37438,37467,37451,37476,37457,37428,37449,37453,37445,37433,37439,37466,38296,38552,38548,38549,38605,38603,38601,38602,38647,38651,38649,38646,38742,38772,38774,38928,38929,38931,38922,38930,38924,39164,39156,39165,39166,39347,39345,39348,39649,40169,40578,40718,40723,40736,20711,20718,20709,20694,20717,20698,20693,20687,20689,20721,20686,20713,20834,20979,21123,21122,21297,21421,22014,22016,22043,22039,22013,22036,22022,22025,22029,22030,22007,22038,22047,22024,22032,22006,22296,22294,22645,22654,22659,22675,22666,22649,22661,22653,22781,22821,22818,22820,22890,22889,23265,23270,23273,23255,23254,23256,23267,23413,23518,23527,23521,23525,23526,23528,23522,23524,23519,23565,23650,23940,23943,24155,24163,24149,24151,24148,24275,24278,24330,24390,24432,24505,24903,24895,24907,24951,24930,24931,24927,24922,24920,24949,25130,25735,25688,25684,25764,25720,25695,25722,25681,25703,25652,25709,25723,25970,26017,26071,26070,26274,26280,26269,27036,27048,27029,27073,27054,27091,27083,27035,27063,27067,27051,27060,27088,27085,27053,27084,27046,27075,27043,27465,27468,27699,28467,28436,28414,28435,28404,28457,28478,28448,28460,28431,28418,28450,28415,28399,28422,28465,28472,28466,28451,28437,28459,28463,28552,28458,28396,28417,28402,28364,28407,29076,29081,29053,29066,29060,29074,29246,29330,29334,29508,29520,29796,29795,29802,29808,29805,29956,30097,30247,30221,30219,30217,30227,30433,30435,30596,30589,30591,30561,30913,30879,30887,30899,30889,30883,31118,31119,31117,31278,31281,31402,31401,31469,31471,31649,31637,31627,31605,31639,31645,31636,31631,31672,31623,31620,31929,31933,31934,32187,32176,32156,32189,32190,32160,32202,32180,32178,32177,32186,32162,32191,32181,32184,32173,32210,32199,32172,32624,32736,32737,32735,32862,32858,32903,33104,33152,33167,33160,33162,33151,33154,33255,33274,33287,33300,33310,33355,33993,33983,33990,33988,33945,33950,33970,33948,33995,33976,33984,34003,33936,33980,34001,33994,34623,34588,34619,34594,34597,34612,34584,34645,34615,34601,35059,35074,35060,35065,35064,35069,35048,35098,35055,35494,35468,35486,35491,35469,35489,35475,35492,35498,35493,35496,35480,35473,35482,35495,35946,35981,35980,36051,36049,36050,36203,36249,36245,36348,36628,36626,36629,36627,36771,36960,36952,36956,36963,36953,36958,36962,36957,36955,37145,37144,37150,37237,37240,37239,37236,37496,37504,37509,37528,37526,37499,37523,37532,37544,37500,37521,38305,38312,38313,38307,38309,38308,38553,38556,38555,38604,38610,38656,38780,38789,38902,38935,38936,39087,39089,39171,39173,39180,39177,39361,39599,39600,39654,39745,39746,40180,40182,40179,40636,40763,40778,20740,20736,20731,20725,20729,20738,20744,20745,20741,20956,21127,21128,21129,21133,21130,21232,21426,22062,22075,22073,22066,22079,22068,22057,22099,22094,22103,22132,22070,22063,22064,22656,22687,22686,22707,22684,22702,22697,22694,22893,23305,23291,23307,23285,23308,23304,23534,23532,23529,23531,23652,23653,23965,23956,24162,24159,24161,24290,24282,24287,24285,24291,24288,24392,24433,24503,24501,24950,24935,24942,24925,24917,24962,24956,24944,24939,24958,24999,24976,25003,24974,25004,24986,24996,24980,25006,25134,25705,25711,25721,25758,25778,25736,25744,25776,25765,25747,25749,25769,25746,25774,25773,25771,25754,25772,25753,25762,25779,25973,25975,25976,26286,26283,26292,26289,27171,27167,27112,27137,27166,27161,27133,27169,27155,27146,27123,27138,27141,27117,27153,27472,27470,27556,27589,27590,28479,28540,28548,28497,28518,28500,28550,28525,28507,28536,28526,28558,28538,28528,28516,28567,28504,28373,28527,28512,28511,29087,29100,29105,29096,29270,29339,29518,29527,29801,29835,29827,29822,29824,30079,30240,30249,30239,30244,30246,30241,30242,30362,30394,30436,30606,30599,30604,30609,30603,30923,30917,30906,30922,30910,30933,30908,30928,31295,31292,31296,31293,31287,31291,31407,31406,31661,31665,31684,31668,31686,31687,31681,31648,31692,31946,32224,32244,32239,32251,32216,32236,32221,32232,32227,32218,32222,32233,32158,32217,32242,32249,32629,32631,32687,32745,32806,33179,33180,33181,33184,33178,33176,34071,34109,34074,34030,34092,34093,34067,34065,34083,34081,34068,34028,34085,34047,34054,34690,34676,34678,34656,34662,34680,34664,34649,34647,34636,34643,34907,34909,35088,35079,35090,35091,35093,35082,35516,35538,35527,35524,35477,35531,35576,35506,35529,35522,35519,35504,35542,35533,35510,35513,35547,35916,35918,35948,36064,36062,36070,36068,36076,36077,36066,36067,36060,36074,36065,36205,36255,36259,36395,36368,36381,36386,36367,36393,36383,36385,36382,36538,36637,36635,36639,36649,36646,36650,36636,36638,36645,36969,36974,36968,36973,36983,37168,37165,37159,37169,37255,37257,37259,37251,37573,37563,37559,37610,37548,37604,37569,37555,37564,37586,37575,37616,37554,38317,38321,38660,38662,38663,38665,38752,38797,38795,38799,38945,38955,38940,39091,39178,39187,39186,39192,39389,39376,39391,39387,39377,39381,39378,39385,39607,39662,39663,39719,39749,39748,39799,39791,40198,40201,40195,40617,40638,40654,22696,40786,20754,20760,20756,20752,20757,20864,20906,20957,21137,21139,21235,22105,22123,22137,22121,22116,22136,22122,22120,22117,22129,22127,22124,22114,22134,22721,22718,22727,22725,22894,23325,23348,23416,23536,23566,24394,25010,24977,25001,24970,25037,25014,25022,25034,25032,25136,25797,25793,25803,25787,25788,25818,25796,25799,25794,25805,25791,25810,25812,25790,25972,26310,26313,26297,26308,26311,26296,27197,27192,27194,27225,27243,27224,27193,27204,27234,27233,27211,27207,27189,27231,27208,27481,27511,27653,28610,28593,28577,28611,28580,28609,28583,28595,28608,28601,28598,28582,28576,28596,29118,29129,29136,29138,29128,29141,29113,29134,29145,29148,29123,29124,29544,29852,29859,29848,29855,29854,29922,29964,29965,30260,30264,30266,30439,30437,30624,30622,30623,30629,30952,30938,30956,30951,31142,31309,31310,31302,31308,31307,31418,31705,31761,31689,31716,31707,31713,31721,31718,31957,31958,32266,32273,32264,32283,32291,32286,32285,32265,32272,32633,32690,32752,32753,32750,32808,33203,33193,33192,33275,33288,33368,33369,34122,34137,34120,34152,34153,34115,34121,34157,34154,34142,34691,34719,34718,34722,34701,34913,35114,35122,35109,35115,35105,35242,35238,35558,35578,35563,35569,35584,35548,35559,35566,35582,35585,35586,35575,35565,35571,35574,35580,35947,35949,35987,36084,36420,36401,36404,36418,36409,36405,36667,36655,36664,36659,36776,36774,36981,36980,36984,36978,36988,36986,37172,37266,37664,37686,37624,37683,37679,37666,37628,37675,37636,37658,37648,37670,37665,37653,37678,37657,38331,38567,38568,38570,38613,38670,38673,38678,38669,38675,38671,38747,38748,38758,38808,38960,38968,38971,38967,38957,38969,38948,39184,39208,39198,39195,39201,39194,39405,39394,39409,39608,39612,39675,39661,39720,39825,40213,40227,40230,40232,40210,40219,40664,40660,40845,40860,20778,20767,20769,20786,21237,22158,22144,22160,22149,22151,22159,22741,22739,22737,22734,23344,23338,23332,23418,23607,23656,23996,23994,23997,23992,24171,24396,24509,25033,25026,25031,25062,25035,25138,25140,25806,25802,25816,25824,25840,25830,25836,25841,25826,25837,25986,25987,26329,26326,27264,27284,27268,27298,27292,27355,27299,27262,27287,27280,27296,27484,27566,27610,27656,28632,28657,28639,28640,28635,28644,28651,28655,28544,28652,28641,28649,28629,28654,28656,29159,29151,29166,29158,29157,29165,29164,29172,29152,29237,29254,29552,29554,29865,29872,29862,29864,30278,30274,30284,30442,30643,30634,30640,30636,30631,30637,30703,30967,30970,30964,30959,30977,31143,31146,31319,31423,31751,31757,31742,31735,31756,31712,31968,31964,31966,31970,31967,31961,31965,32302,32318,32326,32311,32306,32323,32299,32317,32305,32325,32321,32308,32313,32328,32309,32319,32303,32580,32755,32764,32881,32882,32880,32879,32883,33222,33219,33210,33218,33216,33215,33213,33225,33214,33256,33289,33393,34218,34180,34174,34204,34193,34196,34223,34203,34183,34216,34186,34407,34752,34769,34739,34770,34758,34731,34747,34746,34760,34763,35131,35126,35140,35128,35133,35244,35598,35607,35609,35611,35594,35616,35613,35588,35600,35905,35903,35955,36090,36093,36092,36088,36091,36264,36425,36427,36424,36426,36676,36670,36674,36677,36671,36991,36989,36996,36993,36994,36992,37177,37283,37278,37276,37709,37762,37672,37749,37706,37733,37707,37656,37758,37740,37723,37744,37722,37716,38346,38347,38348,38344,38342,38577,38584,38614,38684,38686,38816,38867,38982,39094,39221,39425,39423,39854,39851,39850,39853,40251,40255,40587,40655,40670,40668,40669,40667,40766,40779,21474,22165,22190,22745,22744,23352,24413,25059,25139,25844,25842,25854,25862,25850,25851,25847,26039,26332,26406,27315,27308,27331,27323,27320,27330,27310,27311,27487,27512,27567,28681,28683,28670,28678,28666,28689,28687,29179,29180,29182,29176,29559,29557,29863,29887,29973,30294,30296,30290,30653,30655,30651,30652,30990,31150,31329,31330,31328,31428,31429,31787,31783,31786,31774,31779,31777,31975,32340,32341,32350,32346,32353,32338,32345,32584,32761,32763,32887,32886,33229,33231,33290,34255,34217,34253,34256,34249,34224,34234,34233,34214,34799,34796,34802,34784,35206,35250,35316,35624,35641,35628,35627,35920,36101,36441,36451,36454,36452,36447,36437,36544,36681,36685,36999,36995,37e3,37291,37292,37328,37780,37770,37782,37794,37811,37806,37804,37808,37784,37786,37783,38356,38358,38352,38357,38626,38620,38617,38619,38622,38692,38819,38822,38829,38905,38989,38991,38988,38990,38995,39098,39230,39231,39229,39214,39333,39438,39617,39683,39686,39759,39758,39757,39882,39881,39933,39880,39872,40273,40285,40288,40672,40725,40748,20787,22181,22750,22751,22754,23541,40848,24300,25074,25079,25078,25077,25856,25871,26336,26333,27365,27357,27354,27347,28699,28703,28712,28698,28701,28693,28696,29190,29197,29272,29346,29560,29562,29885,29898,29923,30087,30086,30303,30305,30663,31001,31153,31339,31337,31806,31807,31800,31805,31799,31808,32363,32365,32377,32361,32362,32645,32371,32694,32697,32696,33240,34281,34269,34282,34261,34276,34277,34295,34811,34821,34829,34809,34814,35168,35167,35158,35166,35649,35676,35672,35657,35674,35662,35663,35654,35673,36104,36106,36476,36466,36487,36470,36460,36474,36468,36692,36686,36781,37002,37003,37297,37294,37857,37841,37855,37827,37832,37852,37853,37846,37858,37837,37848,37860,37847,37864,38364,38580,38627,38698,38695,38753,38876,38907,39006,39e3,39003,39100,39237,39241,39446,39449,39693,39912,39911,39894,39899,40329,40289,40306,40298,40300,40594,40599,40595,40628,21240,22184,22199,22198,22196,22204,22756,23360,23363,23421,23542,24009,25080,25082,25880,25876,25881,26342,26407,27372,28734,28720,28722,29200,29563,29903,30306,30309,31014,31018,31020,31019,31431,31478,31820,31811,31821,31983,31984,36782,32381,32380,32386,32588,32768,33242,33382,34299,34297,34321,34298,34310,34315,34311,34314,34836,34837,35172,35258,35320,35696,35692,35686,35695,35679,35691,36111,36109,36489,36481,36485,36482,37300,37323,37912,37891,37885,38369,38704,39108,39250,39249,39336,39467,39472,39479,39477,39955,39949,40569,40629,40680,40751,40799,40803,40801,20791,20792,22209,22208,22210,22804,23660,24013,25084,25086,25885,25884,26005,26345,27387,27396,27386,27570,28748,29211,29351,29910,29908,30313,30675,31824,32399,32396,32700,34327,34349,34330,34851,34850,34849,34847,35178,35180,35261,35700,35703,35709,36115,36490,36493,36491,36703,36783,37306,37934,37939,37941,37946,37944,37938,37931,38370,38712,38713,38706,38911,39015,39013,39255,39493,39491,39488,39486,39631,39764,39761,39981,39973,40367,40372,40386,40376,40605,40687,40729,40796,40806,40807,20796,20795,22216,22218,22217,23423,24020,24018,24398,25087,25892,27402,27489,28753,28760,29568,29924,30090,30318,30316,31155,31840,31839,32894,32893,33247,35186,35183,35324,35712,36118,36119,36497,36499,36705,37192,37956,37969,37970,38717,38718,38851,38849,39019,39253,39509,39501,39634,39706,40009,39985,39998,39995,40403,40407,40756,40812,40810,40852,22220,24022,25088,25891,25899,25898,26348,27408,29914,31434,31844,31843,31845,32403,32406,32404,33250,34360,34367,34865,35722,37008,37007,37987,37984,37988,38760,39023,39260,39514,39515,39511,39635,39636,39633,40020,40023,40022,40421,40607,40692,22225,22761,25900,28766,30321,30322,30679,32592,32648,34870,34873,34914,35731,35730,35734,33399,36123,37312,37994,38722,38728,38724,38854,39024,39519,39714,39768,40031,40441,40442,40572,40573,40711,40823,40818,24307,27414,28771,31852,31854,34875,35264,36513,37313,38002,38e3,39025,39262,39638,39715,40652,28772,30682,35738,38007,38857,39522,39525,32412,35740,36522,37317,38013,38014,38012,40055,40056,40695,35924,38015,40474,29224,39530,39729,40475,40478,31858,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,20022,20031,20101,20128,20866,20886,20907,21241,21304,21353,21430,22794,23424,24027,12083,24191,24308,24400,24417,25908,26080,30098,30326,36789,38582,168,710,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,65339,65341,10045,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8679,8632,8633,12751,131276,20058,131210,20994,17553,40880,20872,40881,161287,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65506,65508,65287,65282,12849,8470,8481,12443,12444,11904,11908,11910,11911,11912,11914,11916,11917,11925,11932,11933,11941,11943,11946,11948,11950,11958,11964,11966,11974,11978,11980,11981,11983,11990,11991,11998,12003,null,null,null,643,592,603,596,629,339,248,331,650,618,20034,20060,20981,21274,21378,19975,19980,20039,20109,22231,64012,23662,24435,19983,20871,19982,20014,20115,20162,20169,20168,20888,21244,21356,21433,22304,22787,22828,23568,24063,26081,27571,27596,27668,29247,20017,20028,20200,20188,20201,20193,20189,20186,21004,21276,21324,22306,22307,22807,22831,23425,23428,23570,23611,23668,23667,24068,24192,24194,24521,25097,25168,27669,27702,27715,27711,27707,29358,29360,29578,31160,32906,38430,20238,20248,20268,20213,20244,20209,20224,20215,20232,20253,20226,20229,20258,20243,20228,20212,20242,20913,21011,21001,21008,21158,21282,21279,21325,21386,21511,22241,22239,22318,22314,22324,22844,22912,22908,22917,22907,22910,22903,22911,23382,23573,23589,23676,23674,23675,23678,24031,24181,24196,24322,24346,24436,24533,24532,24527,25180,25182,25188,25185,25190,25186,25177,25184,25178,25189,26095,26094,26430,26425,26424,26427,26426,26431,26428,26419,27672,27718,27730,27740,27727,27722,27732,27723,27724,28785,29278,29364,29365,29582,29994,30335,31349,32593,33400,33404,33408,33405,33407,34381,35198,37017,37015,37016,37019,37012,38434,38436,38432,38435,20310,20283,20322,20297,20307,20324,20286,20327,20306,20319,20289,20312,20269,20275,20287,20321,20879,20921,21020,21022,21025,21165,21166,21257,21347,21362,21390,21391,21552,21559,21546,21588,21573,21529,21532,21541,21528,21565,21583,21569,21544,21540,21575,22254,22247,22245,22337,22341,22348,22345,22347,22354,22790,22848,22950,22936,22944,22935,22926,22946,22928,22927,22951,22945,23438,23442,23592,23594,23693,23695,23688,23691,23689,23698,23690,23686,23699,23701,24032,24074,24078,24203,24201,24204,24200,24205,24325,24349,24440,24438,24530,24529,24528,24557,24552,24558,24563,24545,24548,24547,24570,24559,24567,24571,24576,24564,25146,25219,25228,25230,25231,25236,25223,25201,25211,25210,25200,25217,25224,25207,25213,25202,25204,25911,26096,26100,26099,26098,26101,26437,26439,26457,26453,26444,26440,26461,26445,26458,26443,27600,27673,27674,27768,27751,27755,27780,27787,27791,27761,27759,27753,27802,27757,27783,27797,27804,27750,27763,27749,27771,27790,28788,28794,29283,29375,29373,29379,29382,29377,29370,29381,29589,29591,29587,29588,29586,30010,30009,30100,30101,30337,31037,32820,32917,32921,32912,32914,32924,33424,33423,33413,33422,33425,33427,33418,33411,33412,35960,36809,36799,37023,37025,37029,37022,37031,37024,38448,38440,38447,38445,20019,20376,20348,20357,20349,20352,20359,20342,20340,20361,20356,20343,20300,20375,20330,20378,20345,20353,20344,20368,20380,20372,20382,20370,20354,20373,20331,20334,20894,20924,20926,21045,21042,21043,21062,21041,21180,21258,21259,21308,21394,21396,21639,21631,21633,21649,21634,21640,21611,21626,21630,21605,21612,21620,21606,21645,21615,21601,21600,21656,21603,21607,21604,22263,22265,22383,22386,22381,22379,22385,22384,22390,22400,22389,22395,22387,22388,22370,22376,22397,22796,22853,22965,22970,22991,22990,22962,22988,22977,22966,22972,22979,22998,22961,22973,22976,22984,22964,22983,23394,23397,23443,23445,23620,23623,23726,23716,23712,23733,23727,23720,23724,23711,23715,23725,23714,23722,23719,23709,23717,23734,23728,23718,24087,24084,24089,24360,24354,24355,24356,24404,24450,24446,24445,24542,24549,24621,24614,24601,24626,24587,24628,24586,24599,24627,24602,24606,24620,24610,24589,24592,24622,24595,24593,24588,24585,24604,25108,25149,25261,25268,25297,25278,25258,25270,25290,25262,25267,25263,25275,25257,25264,25272,25917,26024,26043,26121,26108,26116,26130,26120,26107,26115,26123,26125,26117,26109,26129,26128,26358,26378,26501,26476,26510,26514,26486,26491,26520,26502,26500,26484,26509,26508,26490,26527,26513,26521,26499,26493,26497,26488,26489,26516,27429,27520,27518,27614,27677,27795,27884,27883,27886,27865,27830,27860,27821,27879,27831,27856,27842,27834,27843,27846,27885,27890,27858,27869,27828,27786,27805,27776,27870,27840,27952,27853,27847,27824,27897,27855,27881,27857,28820,28824,28805,28819,28806,28804,28817,28822,28802,28826,28803,29290,29398,29387,29400,29385,29404,29394,29396,29402,29388,29393,29604,29601,29613,29606,29602,29600,29612,29597,29917,29928,30015,30016,30014,30092,30104,30383,30451,30449,30448,30453,30712,30716,30713,30715,30714,30711,31042,31039,31173,31352,31355,31483,31861,31997,32821,32911,32942,32931,32952,32949,32941,33312,33440,33472,33451,33434,33432,33435,33461,33447,33454,33468,33438,33466,33460,33448,33441,33449,33474,33444,33475,33462,33442,34416,34415,34413,34414,35926,36818,36811,36819,36813,36822,36821,36823,37042,37044,37039,37043,37040,38457,38461,38460,38458,38467,20429,20421,20435,20402,20425,20427,20417,20436,20444,20441,20411,20403,20443,20423,20438,20410,20416,20409,20460,21060,21065,21184,21186,21309,21372,21399,21398,21401,21400,21690,21665,21677,21669,21711,21699,33549,21687,21678,21718,21686,21701,21702,21664,21616,21692,21666,21694,21618,21726,21680,22453,22430,22431,22436,22412,22423,22429,22427,22420,22424,22415,22425,22437,22426,22421,22772,22797,22867,23009,23006,23022,23040,23025,23005,23034,23037,23036,23030,23012,23026,23031,23003,23017,23027,23029,23008,23038,23028,23021,23464,23628,23760,23768,23756,23767,23755,23771,23774,23770,23753,23751,23754,23766,23763,23764,23759,23752,23750,23758,23775,23800,24057,24097,24098,24099,24096,24100,24240,24228,24226,24219,24227,24229,24327,24366,24406,24454,24631,24633,24660,24690,24670,24645,24659,24647,24649,24667,24652,24640,24642,24671,24612,24644,24664,24678,24686,25154,25155,25295,25357,25355,25333,25358,25347,25323,25337,25359,25356,25336,25334,25344,25363,25364,25338,25365,25339,25328,25921,25923,26026,26047,26166,26145,26162,26165,26140,26150,26146,26163,26155,26170,26141,26164,26169,26158,26383,26384,26561,26610,26568,26554,26588,26555,26616,26584,26560,26551,26565,26603,26596,26591,26549,26573,26547,26615,26614,26606,26595,26562,26553,26574,26599,26608,26546,26620,26566,26605,26572,26542,26598,26587,26618,26569,26570,26563,26602,26571,27432,27522,27524,27574,27606,27608,27616,27680,27681,27944,27956,27949,27935,27964,27967,27922,27914,27866,27955,27908,27929,27962,27930,27921,27904,27933,27970,27905,27928,27959,27907,27919,27968,27911,27936,27948,27912,27938,27913,27920,28855,28831,28862,28849,28848,28833,28852,28853,28841,29249,29257,29258,29292,29296,29299,29294,29386,29412,29416,29419,29407,29418,29414,29411,29573,29644,29634,29640,29637,29625,29622,29621,29620,29675,29631,29639,29630,29635,29638,29624,29643,29932,29934,29998,30023,30024,30119,30122,30329,30404,30472,30467,30468,30469,30474,30455,30459,30458,30695,30696,30726,30737,30738,30725,30736,30735,30734,30729,30723,30739,31050,31052,31051,31045,31044,31189,31181,31183,31190,31182,31360,31358,31441,31488,31489,31866,31864,31865,31871,31872,31873,32003,32008,32001,32600,32657,32653,32702,32775,32782,32783,32788,32823,32984,32967,32992,32977,32968,32962,32976,32965,32995,32985,32988,32970,32981,32969,32975,32983,32998,32973,33279,33313,33428,33497,33534,33529,33543,33512,33536,33493,33594,33515,33494,33524,33516,33505,33522,33525,33548,33531,33526,33520,33514,33508,33504,33530,33523,33517,34423,34420,34428,34419,34881,34894,34919,34922,34921,35283,35332,35335,36210,36835,36833,36846,36832,37105,37053,37055,37077,37061,37054,37063,37067,37064,37332,37331,38484,38479,38481,38483,38474,38478,20510,20485,20487,20499,20514,20528,20507,20469,20468,20531,20535,20524,20470,20471,20503,20508,20512,20519,20533,20527,20529,20494,20826,20884,20883,20938,20932,20933,20936,20942,21089,21082,21074,21086,21087,21077,21090,21197,21262,21406,21798,21730,21783,21778,21735,21747,21732,21786,21759,21764,21768,21739,21777,21765,21745,21770,21755,21751,21752,21728,21774,21763,21771,22273,22274,22476,22578,22485,22482,22458,22470,22461,22460,22456,22454,22463,22471,22480,22457,22465,22798,22858,23065,23062,23085,23086,23061,23055,23063,23050,23070,23091,23404,23463,23469,23468,23555,23638,23636,23788,23807,23790,23793,23799,23808,23801,24105,24104,24232,24238,24234,24236,24371,24368,24423,24669,24666,24679,24641,24738,24712,24704,24722,24705,24733,24707,24725,24731,24727,24711,24732,24718,25113,25158,25330,25360,25430,25388,25412,25413,25398,25411,25572,25401,25419,25418,25404,25385,25409,25396,25432,25428,25433,25389,25415,25395,25434,25425,25400,25431,25408,25416,25930,25926,26054,26051,26052,26050,26186,26207,26183,26193,26386,26387,26655,26650,26697,26674,26675,26683,26699,26703,26646,26673,26652,26677,26667,26669,26671,26702,26692,26676,26653,26642,26644,26662,26664,26670,26701,26682,26661,26656,27436,27439,27437,27441,27444,27501,32898,27528,27622,27620,27624,27619,27618,27623,27685,28026,28003,28004,28022,27917,28001,28050,27992,28002,28013,28015,28049,28045,28143,28031,28038,27998,28007,28e3,28055,28016,28028,27999,28034,28056,27951,28008,28043,28030,28032,28036,27926,28035,28027,28029,28021,28048,28892,28883,28881,28893,28875,32569,28898,28887,28882,28894,28896,28884,28877,28869,28870,28871,28890,28878,28897,29250,29304,29303,29302,29440,29434,29428,29438,29430,29427,29435,29441,29651,29657,29669,29654,29628,29671,29667,29673,29660,29650,29659,29652,29661,29658,29655,29656,29672,29918,29919,29940,29941,29985,30043,30047,30128,30145,30139,30148,30144,30143,30134,30138,30346,30409,30493,30491,30480,30483,30482,30499,30481,30485,30489,30490,30498,30503,30755,30764,30754,30773,30767,30760,30766,30763,30753,30761,30771,30762,30769,31060,31067,31055,31068,31059,31058,31057,31211,31212,31200,31214,31213,31210,31196,31198,31197,31366,31369,31365,31371,31372,31370,31367,31448,31504,31492,31507,31493,31503,31496,31498,31502,31497,31506,31876,31889,31882,31884,31880,31885,31877,32030,32029,32017,32014,32024,32022,32019,32031,32018,32015,32012,32604,32609,32606,32608,32605,32603,32662,32658,32707,32706,32704,32790,32830,32825,33018,33010,33017,33013,33025,33019,33024,33281,33327,33317,33587,33581,33604,33561,33617,33573,33622,33599,33601,33574,33564,33570,33602,33614,33563,33578,33544,33596,33613,33558,33572,33568,33591,33583,33577,33607,33605,33612,33619,33566,33580,33611,33575,33608,34387,34386,34466,34472,34454,34445,34449,34462,34439,34455,34438,34443,34458,34437,34469,34457,34465,34471,34453,34456,34446,34461,34448,34452,34883,34884,34925,34933,34934,34930,34944,34929,34943,34927,34947,34942,34932,34940,35346,35911,35927,35963,36004,36003,36214,36216,36277,36279,36278,36561,36563,36862,36853,36866,36863,36859,36868,36860,36854,37078,37088,37081,37082,37091,37087,37093,37080,37083,37079,37084,37092,37200,37198,37199,37333,37346,37338,38492,38495,38588,39139,39647,39727,20095,20592,20586,20577,20574,20576,20563,20555,20573,20594,20552,20557,20545,20571,20554,20578,20501,20549,20575,20585,20587,20579,20580,20550,20544,20590,20595,20567,20561,20944,21099,21101,21100,21102,21206,21203,21293,21404,21877,21878,21820,21837,21840,21812,21802,21841,21858,21814,21813,21808,21842,21829,21772,21810,21861,21838,21817,21832,21805,21819,21824,21835,22282,22279,22523,22548,22498,22518,22492,22516,22528,22509,22525,22536,22520,22539,22515,22479,22535,22510,22499,22514,22501,22508,22497,22542,22524,22544,22503,22529,22540,22513,22505,22512,22541,22532,22876,23136,23128,23125,23143,23134,23096,23093,23149,23120,23135,23141,23148,23123,23140,23127,23107,23133,23122,23108,23131,23112,23182,23102,23117,23097,23116,23152,23145,23111,23121,23126,23106,23132,23410,23406,23489,23488,23641,23838,23819,23837,23834,23840,23820,23848,23821,23846,23845,23823,23856,23826,23843,23839,23854,24126,24116,24241,24244,24249,24242,24243,24374,24376,24475,24470,24479,24714,24720,24710,24766,24752,24762,24787,24788,24783,24804,24793,24797,24776,24753,24795,24759,24778,24767,24771,24781,24768,25394,25445,25482,25474,25469,25533,25502,25517,25501,25495,25515,25486,25455,25479,25488,25454,25519,25461,25500,25453,25518,25468,25508,25403,25503,25464,25477,25473,25489,25485,25456,25939,26061,26213,26209,26203,26201,26204,26210,26392,26745,26759,26768,26780,26733,26734,26798,26795,26966,26735,26787,26796,26793,26741,26740,26802,26767,26743,26770,26748,26731,26738,26794,26752,26737,26750,26779,26774,26763,26784,26761,26788,26744,26747,26769,26764,26762,26749,27446,27443,27447,27448,27537,27535,27533,27534,27532,27690,28096,28075,28084,28083,28276,28076,28137,28130,28087,28150,28116,28160,28104,28128,28127,28118,28094,28133,28124,28125,28123,28148,28106,28093,28141,28144,28090,28117,28098,28111,28105,28112,28146,28115,28157,28119,28109,28131,28091,28922,28941,28919,28951,28916,28940,28912,28932,28915,28944,28924,28927,28934,28947,28928,28920,28918,28939,28930,28942,29310,29307,29308,29311,29469,29463,29447,29457,29464,29450,29448,29439,29455,29470,29576,29686,29688,29685,29700,29697,29693,29703,29696,29690,29692,29695,29708,29707,29684,29704,30052,30051,30158,30162,30159,30155,30156,30161,30160,30351,30345,30419,30521,30511,30509,30513,30514,30516,30515,30525,30501,30523,30517,30792,30802,30793,30797,30794,30796,30758,30789,30800,31076,31079,31081,31082,31075,31083,31073,31163,31226,31224,31222,31223,31375,31380,31376,31541,31559,31540,31525,31536,31522,31524,31539,31512,31530,31517,31537,31531,31533,31535,31538,31544,31514,31523,31892,31896,31894,31907,32053,32061,32056,32054,32058,32069,32044,32041,32065,32071,32062,32063,32074,32059,32040,32611,32661,32668,32669,32667,32714,32715,32717,32720,32721,32711,32719,32713,32799,32798,32795,32839,32835,32840,33048,33061,33049,33051,33069,33055,33068,33054,33057,33045,33063,33053,33058,33297,33336,33331,33338,33332,33330,33396,33680,33699,33704,33677,33658,33651,33700,33652,33679,33665,33685,33689,33653,33684,33705,33661,33667,33676,33693,33691,33706,33675,33662,33701,33711,33672,33687,33712,33663,33702,33671,33710,33654,33690,34393,34390,34495,34487,34498,34497,34501,34490,34480,34504,34489,34483,34488,34508,34484,34491,34492,34499,34493,34494,34898,34953,34965,34984,34978,34986,34970,34961,34977,34975,34968,34983,34969,34971,34967,34980,34988,34956,34963,34958,35202,35286,35289,35285,35376,35367,35372,35358,35897,35899,35932,35933,35965,36005,36221,36219,36217,36284,36290,36281,36287,36289,36568,36574,36573,36572,36567,36576,36577,36900,36875,36881,36892,36876,36897,37103,37098,37104,37108,37106,37107,37076,37099,37100,37097,37206,37208,37210,37203,37205,37356,37364,37361,37363,37368,37348,37369,37354,37355,37367,37352,37358,38266,38278,38280,38524,38509,38507,38513,38511,38591,38762,38916,39141,39319,20635,20629,20628,20638,20619,20643,20611,20620,20622,20637,20584,20636,20626,20610,20615,20831,20948,21266,21265,21412,21415,21905,21928,21925,21933,21879,22085,21922,21907,21896,21903,21941,21889,21923,21906,21924,21885,21900,21926,21887,21909,21921,21902,22284,22569,22583,22553,22558,22567,22563,22568,22517,22600,22565,22556,22555,22579,22591,22582,22574,22585,22584,22573,22572,22587,22881,23215,23188,23199,23162,23202,23198,23160,23206,23164,23205,23212,23189,23214,23095,23172,23178,23191,23171,23179,23209,23163,23165,23180,23196,23183,23187,23197,23530,23501,23499,23508,23505,23498,23502,23564,23600,23863,23875,23915,23873,23883,23871,23861,23889,23886,23893,23859,23866,23890,23869,23857,23897,23874,23865,23881,23864,23868,23858,23862,23872,23877,24132,24129,24408,24486,24485,24491,24777,24761,24780,24802,24782,24772,24852,24818,24842,24854,24837,24821,24851,24824,24828,24830,24769,24835,24856,24861,24848,24831,24836,24843,25162,25492,25521,25520,25550,25573,25576,25583,25539,25757,25587,25546,25568,25590,25557,25586,25589,25697,25567,25534,25565,25564,25540,25560,25555,25538,25543,25548,25547,25544,25584,25559,25561,25906,25959,25962,25956,25948,25960,25957,25996,26013,26014,26030,26064,26066,26236,26220,26235,26240,26225,26233,26218,26226,26369,26892,26835,26884,26844,26922,26860,26858,26865,26895,26838,26871,26859,26852,26870,26899,26896,26867,26849,26887,26828,26888,26992,26804,26897,26863,26822,26900,26872,26832,26877,26876,26856,26891,26890,26903,26830,26824,26845,26846,26854,26868,26833,26886,26836,26857,26901,26917,26823,27449,27451,27455,27452,27540,27543,27545,27541,27581,27632,27634,27635,27696,28156,28230,28231,28191,28233,28296,28220,28221,28229,28258,28203,28223,28225,28253,28275,28188,28211,28235,28224,28241,28219,28163,28206,28254,28264,28252,28257,28209,28200,28256,28273,28267,28217,28194,28208,28243,28261,28199,28280,28260,28279,28245,28281,28242,28262,28213,28214,28250,28960,28958,28975,28923,28974,28977,28963,28965,28962,28978,28959,28968,28986,28955,29259,29274,29320,29321,29318,29317,29323,29458,29451,29488,29474,29489,29491,29479,29490,29485,29478,29475,29493,29452,29742,29740,29744,29739,29718,29722,29729,29741,29745,29732,29731,29725,29737,29728,29746,29947,29999,30063,30060,30183,30170,30177,30182,30173,30175,30180,30167,30357,30354,30426,30534,30535,30532,30541,30533,30538,30542,30539,30540,30686,30700,30816,30820,30821,30812,30829,30833,30826,30830,30832,30825,30824,30814,30818,31092,31091,31090,31088,31234,31242,31235,31244,31236,31385,31462,31460,31562,31547,31556,31560,31564,31566,31552,31576,31557,31906,31902,31912,31905,32088,32111,32099,32083,32086,32103,32106,32079,32109,32092,32107,32082,32084,32105,32081,32095,32078,32574,32575,32613,32614,32674,32672,32673,32727,32849,32847,32848,33022,32980,33091,33098,33106,33103,33095,33085,33101,33082,33254,33262,33271,33272,33273,33284,33340,33341,33343,33397,33595,33743,33785,33827,33728,33768,33810,33767,33764,33788,33782,33808,33734,33736,33771,33763,33727,33793,33757,33765,33752,33791,33761,33739,33742,33750,33781,33737,33801,33807,33758,33809,33798,33730,33779,33749,33786,33735,33745,33770,33811,33731,33772,33774,33732,33787,33751,33762,33819,33755,33790,34520,34530,34534,34515,34531,34522,34538,34525,34539,34524,34540,34537,34519,34536,34513,34888,34902,34901,35002,35031,35001,35e3,35008,35006,34998,35004,34999,35005,34994,35073,35017,35221,35224,35223,35293,35290,35291,35406,35405,35385,35417,35392,35415,35416,35396,35397,35410,35400,35409,35402,35404,35407,35935,35969,35968,36026,36030,36016,36025,36021,36228,36224,36233,36312,36307,36301,36295,36310,36316,36303,36309,36313,36296,36311,36293,36591,36599,36602,36601,36582,36590,36581,36597,36583,36584,36598,36587,36593,36588,36596,36585,36909,36916,36911,37126,37164,37124,37119,37116,37128,37113,37115,37121,37120,37127,37125,37123,37217,37220,37215,37218,37216,37377,37386,37413,37379,37402,37414,37391,37388,37376,37394,37375,37373,37382,37380,37415,37378,37404,37412,37401,37399,37381,37398,38267,38285,38284,38288,38535,38526,38536,38537,38531,38528,38594,38600,38595,38641,38640,38764,38768,38766,38919,39081,39147,40166,40697,20099,20100,20150,20669,20671,20678,20654,20676,20682,20660,20680,20674,20656,20673,20666,20657,20683,20681,20662,20664,20951,21114,21112,21115,21116,21955,21979,21964,21968,21963,21962,21981,21952,21972,21956,21993,21951,21970,21901,21967,21973,21986,21974,21960,22002,21965,21977,21954,22292,22611,22632,22628,22607,22605,22601,22639,22613,22606,22621,22617,22629,22619,22589,22627,22641,22780,23239,23236,23243,23226,23224,23217,23221,23216,23231,23240,23227,23238,23223,23232,23242,23220,23222,23245,23225,23184,23510,23512,23513,23583,23603,23921,23907,23882,23909,23922,23916,23902,23912,23911,23906,24048,24143,24142,24138,24141,24139,24261,24268,24262,24267,24263,24384,24495,24493,24823,24905,24906,24875,24901,24886,24882,24878,24902,24879,24911,24873,24896,25120,37224,25123,25125,25124,25541,25585,25579,25616,25618,25609,25632,25636,25651,25667,25631,25621,25624,25657,25655,25634,25635,25612,25638,25648,25640,25665,25653,25647,25610,25626,25664,25637,25639,25611,25575,25627,25646,25633,25614,25967,26002,26067,26246,26252,26261,26256,26251,26250,26265,26260,26232,26400,26982,26975,26936,26958,26978,26993,26943,26949,26986,26937,26946,26967,26969,27002,26952,26953,26933,26988,26931,26941,26981,26864,27e3,26932,26985,26944,26991,26948,26998,26968,26945,26996,26956,26939,26955,26935,26972,26959,26961,26930,26962,26927,27003,26940,27462,27461,27459,27458,27464,27457,27547,64013,27643,27644,27641,27639,27640,28315,28374,28360,28303,28352,28319,28307,28308,28320,28337,28345,28358,28370,28349,28353,28318,28361,28343,28336,28365,28326,28367,28338,28350,28355,28380,28376,28313,28306,28302,28301,28324,28321,28351,28339,28368,28362,28311,28334,28323,28999,29012,29010,29027,29024,28993,29021,29026,29042,29048,29034,29025,28994,29016,28995,29003,29040,29023,29008,29011,28996,29005,29018,29263,29325,29324,29329,29328,29326,29500,29506,29499,29498,29504,29514,29513,29764,29770,29771,29778,29777,29783,29760,29775,29776,29774,29762,29766,29773,29780,29921,29951,29950,29949,29981,30073,30071,27011,30191,30223,30211,30199,30206,30204,30201,30200,30224,30203,30198,30189,30197,30205,30361,30389,30429,30549,30559,30560,30546,30550,30554,30569,30567,30548,30553,30573,30688,30855,30874,30868,30863,30852,30869,30853,30854,30881,30851,30841,30873,30848,30870,30843,31100,31106,31101,31097,31249,31256,31257,31250,31255,31253,31266,31251,31259,31248,31395,31394,31390,31467,31590,31588,31597,31604,31593,31602,31589,31603,31601,31600,31585,31608,31606,31587,31922,31924,31919,32136,32134,32128,32141,32127,32133,32122,32142,32123,32131,32124,32140,32148,32132,32125,32146,32621,32619,32615,32616,32620,32678,32677,32679,32731,32732,32801,33124,33120,33143,33116,33129,33115,33122,33138,26401,33118,33142,33127,33135,33092,33121,33309,33353,33348,33344,33346,33349,34033,33855,33878,33910,33913,33935,33933,33893,33873,33856,33926,33895,33840,33869,33917,33882,33881,33908,33907,33885,34055,33886,33847,33850,33844,33914,33859,33912,33842,33861,33833,33753,33867,33839,33858,33837,33887,33904,33849,33870,33868,33874,33903,33989,33934,33851,33863,33846,33843,33896,33918,33860,33835,33888,33876,33902,33872,34571,34564,34551,34572,34554,34518,34549,34637,34552,34574,34569,34561,34550,34573,34565,35030,35019,35021,35022,35038,35035,35034,35020,35024,35205,35227,35295,35301,35300,35297,35296,35298,35292,35302,35446,35462,35455,35425,35391,35447,35458,35460,35445,35459,35457,35444,35450,35900,35915,35914,35941,35940,35942,35974,35972,35973,36044,36200,36201,36241,36236,36238,36239,36237,36243,36244,36240,36242,36336,36320,36332,36337,36334,36304,36329,36323,36322,36327,36338,36331,36340,36614,36607,36609,36608,36613,36615,36616,36610,36619,36946,36927,36932,36937,36925,37136,37133,37135,37137,37142,37140,37131,37134,37230,37231,37448,37458,37424,37434,37478,37427,37477,37470,37507,37422,37450,37446,37485,37484,37455,37472,37479,37487,37430,37473,37488,37425,37460,37475,37456,37490,37454,37459,37452,37462,37426,38303,38300,38302,38299,38546,38547,38545,38551,38606,38650,38653,38648,38645,38771,38775,38776,38770,38927,38925,38926,39084,39158,39161,39343,39346,39344,39349,39597,39595,39771,40170,40173,40167,40576,40701,20710,20692,20695,20712,20723,20699,20714,20701,20708,20691,20716,20720,20719,20707,20704,20952,21120,21121,21225,21227,21296,21420,22055,22037,22028,22034,22012,22031,22044,22017,22035,22018,22010,22045,22020,22015,22009,22665,22652,22672,22680,22662,22657,22655,22644,22667,22650,22663,22673,22670,22646,22658,22664,22651,22676,22671,22782,22891,23260,23278,23269,23253,23274,23258,23277,23275,23283,23266,23264,23259,23276,23262,23261,23257,23272,23263,23415,23520,23523,23651,23938,23936,23933,23942,23930,23937,23927,23946,23945,23944,23934,23932,23949,23929,23935,24152,24153,24147,24280,24273,24279,24270,24284,24277,24281,24274,24276,24388,24387,24431,24502,24876,24872,24897,24926,24945,24947,24914,24915,24946,24940,24960,24948,24916,24954,24923,24933,24891,24938,24929,24918,25129,25127,25131,25643,25677,25691,25693,25716,25718,25714,25715,25725,25717,25702,25766,25678,25730,25694,25692,25675,25683,25696,25680,25727,25663,25708,25707,25689,25701,25719,25971,26016,26273,26272,26271,26373,26372,26402,27057,27062,27081,27040,27086,27030,27056,27052,27068,27025,27033,27022,27047,27021,27049,27070,27055,27071,27076,27069,27044,27092,27065,27082,27034,27087,27059,27027,27050,27041,27038,27097,27031,27024,27074,27061,27045,27078,27466,27469,27467,27550,27551,27552,27587,27588,27646,28366,28405,28401,28419,28453,28408,28471,28411,28462,28425,28494,28441,28442,28455,28440,28475,28434,28397,28426,28470,28531,28409,28398,28461,28480,28464,28476,28469,28395,28423,28430,28483,28421,28413,28406,28473,28444,28412,28474,28447,28429,28446,28424,28449,29063,29072,29065,29056,29061,29058,29071,29051,29062,29057,29079,29252,29267,29335,29333,29331,29507,29517,29521,29516,29794,29811,29809,29813,29810,29799,29806,29952,29954,29955,30077,30096,30230,30216,30220,30229,30225,30218,30228,30392,30593,30588,30597,30594,30574,30592,30575,30590,30595,30898,30890,30900,30893,30888,30846,30891,30878,30885,30880,30892,30882,30884,31128,31114,31115,31126,31125,31124,31123,31127,31112,31122,31120,31275,31306,31280,31279,31272,31270,31400,31403,31404,31470,31624,31644,31626,31633,31632,31638,31629,31628,31643,31630,31621,31640,21124,31641,31652,31618,31931,31935,31932,31930,32167,32183,32194,32163,32170,32193,32192,32197,32157,32206,32196,32198,32203,32204,32175,32185,32150,32188,32159,32166,32174,32169,32161,32201,32627,32738,32739,32741,32734,32804,32861,32860,33161,33158,33155,33159,33165,33164,33163,33301,33943,33956,33953,33951,33978,33998,33986,33964,33966,33963,33977,33972,33985,33997,33962,33946,33969,34e3,33949,33959,33979,33954,33940,33991,33996,33947,33961,33967,33960,34006,33944,33974,33999,33952,34007,34004,34002,34011,33968,33937,34401,34611,34595,34600,34667,34624,34606,34590,34593,34585,34587,34627,34604,34625,34622,34630,34592,34610,34602,34605,34620,34578,34618,34609,34613,34626,34598,34599,34616,34596,34586,34608,34577,35063,35047,35057,35058,35066,35070,35054,35068,35062,35067,35056,35052,35051,35229,35233,35231,35230,35305,35307,35304,35499,35481,35467,35474,35471,35478,35901,35944,35945,36053,36047,36055,36246,36361,36354,36351,36365,36349,36362,36355,36359,36358,36357,36350,36352,36356,36624,36625,36622,36621,37155,37148,37152,37154,37151,37149,37146,37156,37153,37147,37242,37234,37241,37235,37541,37540,37494,37531,37498,37536,37524,37546,37517,37542,37530,37547,37497,37527,37503,37539,37614,37518,37506,37525,37538,37501,37512,37537,37514,37510,37516,37529,37543,37502,37511,37545,37533,37515,37421,38558,38561,38655,38744,38781,38778,38782,38787,38784,38786,38779,38788,38785,38783,38862,38861,38934,39085,39086,39170,39168,39175,39325,39324,39363,39353,39355,39354,39362,39357,39367,39601,39651,39655,39742,39743,39776,39777,39775,40177,40178,40181,40615,20735,20739,20784,20728,20742,20743,20726,20734,20747,20748,20733,20746,21131,21132,21233,21231,22088,22082,22092,22069,22081,22090,22089,22086,22104,22106,22080,22067,22077,22060,22078,22072,22058,22074,22298,22699,22685,22705,22688,22691,22703,22700,22693,22689,22783,23295,23284,23293,23287,23286,23299,23288,23298,23289,23297,23303,23301,23311,23655,23961,23959,23967,23954,23970,23955,23957,23968,23964,23969,23962,23966,24169,24157,24160,24156,32243,24283,24286,24289,24393,24498,24971,24963,24953,25009,25008,24994,24969,24987,24979,25007,25005,24991,24978,25002,24993,24973,24934,25011,25133,25710,25712,25750,25760,25733,25751,25756,25743,25739,25738,25740,25763,25759,25704,25777,25752,25974,25978,25977,25979,26034,26035,26293,26288,26281,26290,26295,26282,26287,27136,27142,27159,27109,27128,27157,27121,27108,27168,27135,27116,27106,27163,27165,27134,27175,27122,27118,27156,27127,27111,27200,27144,27110,27131,27149,27132,27115,27145,27140,27160,27173,27151,27126,27174,27143,27124,27158,27473,27557,27555,27554,27558,27649,27648,27647,27650,28481,28454,28542,28551,28614,28562,28557,28553,28556,28514,28495,28549,28506,28566,28534,28524,28546,28501,28530,28498,28496,28503,28564,28563,28509,28416,28513,28523,28541,28519,28560,28499,28555,28521,28543,28565,28515,28535,28522,28539,29106,29103,29083,29104,29088,29082,29097,29109,29085,29093,29086,29092,29089,29098,29084,29095,29107,29336,29338,29528,29522,29534,29535,29536,29533,29531,29537,29530,29529,29538,29831,29833,29834,29830,29825,29821,29829,29832,29820,29817,29960,29959,30078,30245,30238,30233,30237,30236,30243,30234,30248,30235,30364,30365,30366,30363,30605,30607,30601,30600,30925,30907,30927,30924,30929,30926,30932,30920,30915,30916,30921,31130,31137,31136,31132,31138,31131,27510,31289,31410,31412,31411,31671,31691,31678,31660,31694,31663,31673,31690,31669,31941,31944,31948,31947,32247,32219,32234,32231,32215,32225,32259,32250,32230,32246,32241,32240,32238,32223,32630,32684,32688,32685,32749,32747,32746,32748,32742,32744,32868,32871,33187,33183,33182,33173,33186,33177,33175,33302,33359,33363,33362,33360,33358,33361,34084,34107,34063,34048,34089,34062,34057,34061,34079,34058,34087,34076,34043,34091,34042,34056,34060,34036,34090,34034,34069,34039,34027,34035,34044,34066,34026,34025,34070,34046,34088,34077,34094,34050,34045,34078,34038,34097,34086,34023,34024,34032,34031,34041,34072,34080,34096,34059,34073,34095,34402,34646,34659,34660,34679,34785,34675,34648,34644,34651,34642,34657,34650,34641,34654,34669,34666,34640,34638,34655,34653,34671,34668,34682,34670,34652,34661,34639,34683,34677,34658,34663,34665,34906,35077,35084,35092,35083,35095,35096,35097,35078,35094,35089,35086,35081,35234,35236,35235,35309,35312,35308,35535,35526,35512,35539,35537,35540,35541,35515,35543,35518,35520,35525,35544,35523,35514,35517,35545,35902,35917,35983,36069,36063,36057,36072,36058,36061,36071,36256,36252,36257,36251,36384,36387,36389,36388,36398,36373,36379,36374,36369,36377,36390,36391,36372,36370,36376,36371,36380,36375,36378,36652,36644,36632,36634,36640,36643,36630,36631,36979,36976,36975,36967,36971,37167,37163,37161,37162,37170,37158,37166,37253,37254,37258,37249,37250,37252,37248,37584,37571,37572,37568,37593,37558,37583,37617,37599,37592,37609,37591,37597,37580,37615,37570,37608,37578,37576,37582,37606,37581,37589,37577,37600,37598,37607,37585,37587,37557,37601,37574,37556,38268,38316,38315,38318,38320,38564,38562,38611,38661,38664,38658,38746,38794,38798,38792,38864,38863,38942,38941,38950,38953,38952,38944,38939,38951,39090,39176,39162,39185,39188,39190,39191,39189,39388,39373,39375,39379,39380,39374,39369,39382,39384,39371,39383,39372,39603,39660,39659,39667,39666,39665,39750,39747,39783,39796,39793,39782,39798,39797,39792,39784,39780,39788,40188,40186,40189,40191,40183,40199,40192,40185,40187,40200,40197,40196,40579,40659,40719,40720,20764,20755,20759,20762,20753,20958,21300,21473,22128,22112,22126,22131,22118,22115,22125,22130,22110,22135,22300,22299,22728,22717,22729,22719,22714,22722,22716,22726,23319,23321,23323,23329,23316,23315,23312,23318,23336,23322,23328,23326,23535,23980,23985,23977,23975,23989,23984,23982,23978,23976,23986,23981,23983,23988,24167,24168,24166,24175,24297,24295,24294,24296,24293,24395,24508,24989,25e3,24982,25029,25012,25030,25025,25036,25018,25023,25016,24972,25815,25814,25808,25807,25801,25789,25737,25795,25819,25843,25817,25907,25983,25980,26018,26312,26302,26304,26314,26315,26319,26301,26299,26298,26316,26403,27188,27238,27209,27239,27186,27240,27198,27229,27245,27254,27227,27217,27176,27226,27195,27199,27201,27242,27236,27216,27215,27220,27247,27241,27232,27196,27230,27222,27221,27213,27214,27206,27477,27476,27478,27559,27562,27563,27592,27591,27652,27651,27654,28589,28619,28579,28615,28604,28622,28616,28510,28612,28605,28574,28618,28584,28676,28581,28590,28602,28588,28586,28623,28607,28600,28578,28617,28587,28621,28591,28594,28592,29125,29122,29119,29112,29142,29120,29121,29131,29140,29130,29127,29135,29117,29144,29116,29126,29146,29147,29341,29342,29545,29542,29543,29548,29541,29547,29546,29823,29850,29856,29844,29842,29845,29857,29963,30080,30255,30253,30257,30269,30259,30268,30261,30258,30256,30395,30438,30618,30621,30625,30620,30619,30626,30627,30613,30617,30615,30941,30953,30949,30954,30942,30947,30939,30945,30946,30957,30943,30944,31140,31300,31304,31303,31414,31416,31413,31409,31415,31710,31715,31719,31709,31701,31717,31706,31720,31737,31700,31722,31714,31708,31723,31704,31711,31954,31956,31959,31952,31953,32274,32289,32279,32268,32287,32288,32275,32270,32284,32277,32282,32290,32267,32271,32278,32269,32276,32293,32292,32579,32635,32636,32634,32689,32751,32810,32809,32876,33201,33190,33198,33209,33205,33195,33200,33196,33204,33202,33207,33191,33266,33365,33366,33367,34134,34117,34155,34125,34131,34145,34136,34112,34118,34148,34113,34146,34116,34129,34119,34147,34110,34139,34161,34126,34158,34165,34133,34151,34144,34188,34150,34141,34132,34149,34156,34403,34405,34404,34715,34703,34711,34707,34706,34696,34689,34710,34712,34681,34695,34723,34693,34704,34705,34717,34692,34708,34716,34714,34697,35102,35110,35120,35117,35118,35111,35121,35106,35113,35107,35119,35116,35103,35313,35552,35554,35570,35572,35573,35549,35604,35556,35551,35568,35528,35550,35553,35560,35583,35567,35579,35985,35986,35984,36085,36078,36081,36080,36083,36204,36206,36261,36263,36403,36414,36408,36416,36421,36406,36412,36413,36417,36400,36415,36541,36662,36654,36661,36658,36665,36663,36660,36982,36985,36987,36998,37114,37171,37173,37174,37267,37264,37265,37261,37263,37671,37662,37640,37663,37638,37647,37754,37688,37692,37659,37667,37650,37633,37702,37677,37646,37645,37579,37661,37626,37669,37651,37625,37623,37684,37634,37668,37631,37673,37689,37685,37674,37652,37644,37643,37630,37641,37632,37627,37654,38332,38349,38334,38329,38330,38326,38335,38325,38333,38569,38612,38667,38674,38672,38809,38807,38804,38896,38904,38965,38959,38962,39204,39199,39207,39209,39326,39406,39404,39397,39396,39408,39395,39402,39401,39399,39609,39615,39604,39611,39670,39674,39673,39671,39731,39808,39813,39815,39804,39806,39803,39810,39827,39826,39824,39802,39829,39805,39816,40229,40215,40224,40222,40212,40233,40221,40216,40226,40208,40217,40223,40584,40582,40583,40622,40621,40661,40662,40698,40722,40765,20774,20773,20770,20772,20768,20777,21236,22163,22156,22157,22150,22148,22147,22142,22146,22143,22145,22742,22740,22735,22738,23341,23333,23346,23331,23340,23335,23334,23343,23342,23419,23537,23538,23991,24172,24170,24510,24507,25027,25013,25020,25063,25056,25061,25060,25064,25054,25839,25833,25827,25835,25828,25832,25985,25984,26038,26074,26322,27277,27286,27265,27301,27273,27295,27291,27297,27294,27271,27283,27278,27285,27267,27304,27300,27281,27263,27302,27290,27269,27276,27282,27483,27565,27657,28620,28585,28660,28628,28643,28636,28653,28647,28646,28638,28658,28637,28642,28648,29153,29169,29160,29170,29156,29168,29154,29555,29550,29551,29847,29874,29867,29840,29866,29869,29873,29861,29871,29968,29969,29970,29967,30084,30275,30280,30281,30279,30372,30441,30645,30635,30642,30647,30646,30644,30641,30632,30704,30963,30973,30978,30971,30972,30962,30981,30969,30974,30980,31147,31144,31324,31323,31318,31320,31316,31322,31422,31424,31425,31749,31759,31730,31744,31743,31739,31758,31732,31755,31731,31746,31753,31747,31745,31736,31741,31750,31728,31729,31760,31754,31976,32301,32316,32322,32307,38984,32312,32298,32329,32320,32327,32297,32332,32304,32315,32310,32324,32314,32581,32639,32638,32637,32756,32754,32812,33211,33220,33228,33226,33221,33223,33212,33257,33371,33370,33372,34179,34176,34191,34215,34197,34208,34187,34211,34171,34212,34202,34206,34167,34172,34185,34209,34170,34168,34135,34190,34198,34182,34189,34201,34205,34177,34210,34178,34184,34181,34169,34166,34200,34192,34207,34408,34750,34730,34733,34757,34736,34732,34745,34741,34748,34734,34761,34755,34754,34764,34743,34735,34756,34762,34740,34742,34751,34744,34749,34782,34738,35125,35123,35132,35134,35137,35154,35127,35138,35245,35247,35246,35314,35315,35614,35608,35606,35601,35589,35595,35618,35599,35602,35605,35591,35597,35592,35590,35612,35603,35610,35919,35952,35954,35953,35951,35989,35988,36089,36207,36430,36429,36435,36432,36428,36423,36675,36672,36997,36990,37176,37274,37282,37275,37273,37279,37281,37277,37280,37793,37763,37807,37732,37718,37703,37756,37720,37724,37750,37705,37712,37713,37728,37741,37775,37708,37738,37753,37719,37717,37714,37711,37745,37751,37755,37729,37726,37731,37735,37760,37710,37721,38343,38336,38345,38339,38341,38327,38574,38576,38572,38688,38687,38680,38685,38681,38810,38817,38812,38814,38813,38869,38868,38897,38977,38980,38986,38985,38981,38979,39205,39211,39212,39210,39219,39218,39215,39213,39217,39216,39320,39331,39329,39426,39418,39412,39415,39417,39416,39414,39419,39421,39422,39420,39427,39614,39678,39677,39681,39676,39752,39834,39848,39838,39835,39846,39841,39845,39844,39814,39842,39840,39855,40243,40257,40295,40246,40238,40239,40241,40248,40240,40261,40258,40259,40254,40247,40256,40253,32757,40237,40586,40585,40589,40624,40648,40666,40699,40703,40740,40739,40738,40788,40864,20785,20781,20782,22168,22172,22167,22170,22173,22169,22896,23356,23657,23658,24e3,24173,24174,25048,25055,25069,25070,25073,25066,25072,25067,25046,25065,25855,25860,25853,25848,25857,25859,25852,26004,26075,26330,26331,26328,27333,27321,27325,27361,27334,27322,27318,27319,27335,27316,27309,27486,27593,27659,28679,28684,28685,28673,28677,28692,28686,28671,28672,28667,28710,28668,28663,28682,29185,29183,29177,29187,29181,29558,29880,29888,29877,29889,29886,29878,29883,29890,29972,29971,30300,30308,30297,30288,30291,30295,30298,30374,30397,30444,30658,30650,30975,30988,30995,30996,30985,30992,30994,30993,31149,31148,31327,31772,31785,31769,31776,31775,31789,31773,31782,31784,31778,31781,31792,32348,32336,32342,32355,32344,32354,32351,32337,32352,32343,32339,32693,32691,32759,32760,32885,33233,33234,33232,33375,33374,34228,34246,34240,34243,34242,34227,34229,34237,34247,34244,34239,34251,34254,34248,34245,34225,34230,34258,34340,34232,34231,34238,34409,34791,34790,34786,34779,34795,34794,34789,34783,34803,34788,34772,34780,34771,34797,34776,34787,34724,34775,34777,34817,34804,34792,34781,35155,35147,35151,35148,35142,35152,35153,35145,35626,35623,35619,35635,35632,35637,35655,35631,35644,35646,35633,35621,35639,35622,35638,35630,35620,35643,35645,35642,35906,35957,35993,35992,35991,36094,36100,36098,36096,36444,36450,36448,36439,36438,36446,36453,36455,36443,36442,36449,36445,36457,36436,36678,36679,36680,36683,37160,37178,37179,37182,37288,37285,37287,37295,37290,37813,37772,37778,37815,37787,37789,37769,37799,37774,37802,37790,37798,37781,37768,37785,37791,37773,37809,37777,37810,37796,37800,37812,37795,37797,38354,38355,38353,38579,38615,38618,24002,38623,38616,38621,38691,38690,38693,38828,38830,38824,38827,38820,38826,38818,38821,38871,38873,38870,38872,38906,38992,38993,38994,39096,39233,39228,39226,39439,39435,39433,39437,39428,39441,39434,39429,39431,39430,39616,39644,39688,39684,39685,39721,39733,39754,39756,39755,39879,39878,39875,39871,39873,39861,39864,39891,39862,39876,39865,39869,40284,40275,40271,40266,40283,40267,40281,40278,40268,40279,40274,40276,40287,40280,40282,40590,40588,40671,40705,40704,40726,40741,40747,40746,40745,40744,40780,40789,20788,20789,21142,21239,21428,22187,22189,22182,22183,22186,22188,22746,22749,22747,22802,23357,23358,23359,24003,24176,24511,25083,25863,25872,25869,25865,25868,25870,25988,26078,26077,26334,27367,27360,27340,27345,27353,27339,27359,27356,27344,27371,27343,27341,27358,27488,27568,27660,28697,28711,28704,28694,28715,28705,28706,28707,28713,28695,28708,28700,28714,29196,29194,29191,29186,29189,29349,29350,29348,29347,29345,29899,29893,29879,29891,29974,30304,30665,30666,30660,30705,31005,31003,31009,31004,30999,31006,31152,31335,31336,31795,31804,31801,31788,31803,31980,31978,32374,32373,32376,32368,32375,32367,32378,32370,32372,32360,32587,32586,32643,32646,32695,32765,32766,32888,33239,33237,33380,33377,33379,34283,34289,34285,34265,34273,34280,34266,34263,34284,34290,34296,34264,34271,34275,34268,34257,34288,34278,34287,34270,34274,34816,34810,34819,34806,34807,34825,34828,34827,34822,34812,34824,34815,34826,34818,35170,35162,35163,35159,35169,35164,35160,35165,35161,35208,35255,35254,35318,35664,35656,35658,35648,35667,35670,35668,35659,35669,35665,35650,35666,35671,35907,35959,35958,35994,36102,36103,36105,36268,36266,36269,36267,36461,36472,36467,36458,36463,36475,36546,36690,36689,36687,36688,36691,36788,37184,37183,37296,37293,37854,37831,37839,37826,37850,37840,37881,37868,37836,37849,37801,37862,37834,37844,37870,37859,37845,37828,37838,37824,37842,37863,38269,38362,38363,38625,38697,38699,38700,38696,38694,38835,38839,38838,38877,38878,38879,39004,39001,39005,38999,39103,39101,39099,39102,39240,39239,39235,39334,39335,39450,39445,39461,39453,39460,39451,39458,39456,39463,39459,39454,39452,39444,39618,39691,39690,39694,39692,39735,39914,39915,39904,39902,39908,39910,39906,39920,39892,39895,39916,39900,39897,39909,39893,39905,39898,40311,40321,40330,40324,40328,40305,40320,40312,40326,40331,40332,40317,40299,40308,40309,40304,40297,40325,40307,40315,40322,40303,40313,40319,40327,40296,40596,40593,40640,40700,40749,40768,40769,40781,40790,40791,40792,21303,22194,22197,22195,22755,23365,24006,24007,24302,24303,24512,24513,25081,25879,25878,25877,25875,26079,26344,26339,26340,27379,27376,27370,27368,27385,27377,27374,27375,28732,28725,28719,28727,28724,28721,28738,28728,28735,28730,28729,28736,28731,28723,28737,29203,29204,29352,29565,29564,29882,30379,30378,30398,30445,30668,30670,30671,30669,30706,31013,31011,31015,31016,31012,31017,31154,31342,31340,31341,31479,31817,31816,31818,31815,31813,31982,32379,32382,32385,32384,32698,32767,32889,33243,33241,33291,33384,33385,34338,34303,34305,34302,34331,34304,34294,34308,34313,34309,34316,34301,34841,34832,34833,34839,34835,34838,35171,35174,35257,35319,35680,35690,35677,35688,35683,35685,35687,35693,36270,36486,36488,36484,36697,36694,36695,36693,36696,36698,37005,37187,37185,37303,37301,37298,37299,37899,37907,37883,37920,37903,37908,37886,37909,37904,37928,37913,37901,37877,37888,37879,37895,37902,37910,37906,37882,37897,37880,37898,37887,37884,37900,37878,37905,37894,38366,38368,38367,38702,38703,38841,38843,38909,38910,39008,39010,39011,39007,39105,39106,39248,39246,39257,39244,39243,39251,39474,39476,39473,39468,39466,39478,39465,39470,39480,39469,39623,39626,39622,39696,39698,39697,39947,39944,39927,39941,39954,39928,4e4,39943,39950,39942,39959,39956,39945,40351,40345,40356,40349,40338,40344,40336,40347,40352,40340,40348,40362,40343,40353,40346,40354,40360,40350,40355,40383,40361,40342,40358,40359,40601,40603,40602,40677,40676,40679,40678,40752,40750,40795,40800,40798,40797,40793,40849,20794,20793,21144,21143,22211,22205,22206,23368,23367,24011,24015,24305,25085,25883,27394,27388,27395,27384,27392,28739,28740,28746,28744,28745,28741,28742,29213,29210,29209,29566,29975,30314,30672,31021,31025,31023,31828,31827,31986,32394,32391,32392,32395,32390,32397,32589,32699,32816,33245,34328,34346,34342,34335,34339,34332,34329,34343,34350,34337,34336,34345,34334,34341,34857,34845,34843,34848,34852,34844,34859,34890,35181,35177,35182,35179,35322,35705,35704,35653,35706,35707,36112,36116,36271,36494,36492,36702,36699,36701,37190,37188,37189,37305,37951,37947,37942,37929,37949,37948,37936,37945,37930,37943,37932,37952,37937,38373,38372,38371,38709,38714,38847,38881,39012,39113,39110,39104,39256,39254,39481,39485,39494,39492,39490,39489,39482,39487,39629,39701,39703,39704,39702,39738,39762,39979,39965,39964,39980,39971,39976,39977,39972,39969,40375,40374,40380,40385,40391,40394,40399,40382,40389,40387,40379,40373,40398,40377,40378,40364,40392,40369,40365,40396,40371,40397,40370,40570,40604,40683,40686,40685,40731,40728,40730,40753,40782,40805,40804,40850,20153,22214,22213,22219,22897,23371,23372,24021,24017,24306,25889,25888,25894,25890,27403,27400,27401,27661,28757,28758,28759,28754,29214,29215,29353,29567,29912,29909,29913,29911,30317,30381,31029,31156,31344,31345,31831,31836,31833,31835,31834,31988,31985,32401,32591,32647,33246,33387,34356,34357,34355,34348,34354,34358,34860,34856,34854,34858,34853,35185,35263,35262,35323,35710,35716,35714,35718,35717,35711,36117,36501,36500,36506,36498,36496,36502,36503,36704,36706,37191,37964,37968,37962,37963,37967,37959,37957,37960,37961,37958,38719,38883,39018,39017,39115,39252,39259,39502,39507,39508,39500,39503,39496,39498,39497,39506,39504,39632,39705,39723,39739,39766,39765,40006,40008,39999,40004,39993,39987,40001,39996,39991,39988,39986,39997,39990,40411,40402,40414,40410,40395,40400,40412,40401,40415,40425,40409,40408,40406,40437,40405,40413,40630,40688,40757,40755,40754,40770,40811,40853,40866,20797,21145,22760,22759,22898,23373,24024,34863,24399,25089,25091,25092,25897,25893,26006,26347,27409,27410,27407,27594,28763,28762,29218,29570,29569,29571,30320,30676,31847,31846,32405,33388,34362,34368,34361,34364,34353,34363,34366,34864,34866,34862,34867,35190,35188,35187,35326,35724,35726,35723,35720,35909,36121,36504,36708,36707,37308,37986,37973,37981,37975,37982,38852,38853,38912,39510,39513,39710,39711,39712,40018,40024,40016,40010,40013,40011,40021,40025,40012,40014,40443,40439,40431,40419,40427,40440,40420,40438,40417,40430,40422,40434,40432,40418,40428,40436,40435,40424,40429,40642,40656,40690,40691,40710,40732,40760,40759,40758,40771,40783,40817,40816,40814,40815,22227,22221,23374,23661,25901,26349,26350,27411,28767,28769,28765,28768,29219,29915,29925,30677,31032,31159,31158,31850,32407,32649,33389,34371,34872,34871,34869,34891,35732,35733,36510,36511,36512,36509,37310,37309,37314,37995,37992,37993,38629,38726,38723,38727,38855,38885,39518,39637,39769,40035,40039,40038,40034,40030,40032,40450,40446,40455,40451,40454,40453,40448,40449,40457,40447,40445,40452,40608,40734,40774,40820,40821,40822,22228,25902,26040,27416,27417,27415,27418,28770,29222,29354,30680,30681,31033,31849,31851,31990,32410,32408,32411,32409,33248,33249,34374,34375,34376,35193,35194,35196,35195,35327,35736,35737,36517,36516,36515,37998,37997,37999,38001,38003,38729,39026,39263,40040,40046,40045,40459,40461,40464,40463,40466,40465,40609,40693,40713,40775,40824,40827,40826,40825,22302,28774,31855,34876,36274,36518,37315,38004,38008,38006,38005,39520,40052,40051,40049,40053,40468,40467,40694,40714,40868,28776,28773,31991,34410,34878,34877,34879,35742,35996,36521,36553,38731,39027,39028,39116,39265,39339,39524,39526,39527,39716,40469,40471,40776,25095,27422,29223,34380,36520,38018,38016,38017,39529,39528,39726,40473,29225,34379,35743,38019,40057,40631,30325,39531,40058,40477,28777,28778,40612,40830,40777,40856,30849,37561,35023,22715,24658,31911,23290,9556,9574,9559,9568,9580,9571,9562,9577,9565,9554,9572,9557,9566,9578,9569,9560,9575,9563,9555,9573,9558,9567,9579,9570,9561,9576,9564,9553,9552,9581,9582,9584,9583,65517,132423,37595,132575,147397,34124,17077,29679,20917,13897,149826,166372,37700,137691,33518,146632,30780,26436,25311,149811,166314,131744,158643,135941,20395,140525,20488,159017,162436,144896,150193,140563,20521,131966,24484,131968,131911,28379,132127,20605,20737,13434,20750,39020,14147,33814,149924,132231,20832,144308,20842,134143,139516,131813,140592,132494,143923,137603,23426,34685,132531,146585,20914,20920,40244,20937,20943,20945,15580,20947,150182,20915,20962,21314,20973,33741,26942,145197,24443,21003,21030,21052,21173,21079,21140,21177,21189,31765,34114,21216,34317,158483,21253,166622,21833,28377,147328,133460,147436,21299,21316,134114,27851,136998,26651,29653,24650,16042,14540,136936,29149,17570,21357,21364,165547,21374,21375,136598,136723,30694,21395,166555,21408,21419,21422,29607,153458,16217,29596,21441,21445,27721,20041,22526,21465,15019,134031,21472,147435,142755,21494,134263,21523,28793,21803,26199,27995,21613,158547,134516,21853,21647,21668,18342,136973,134877,15796,134477,166332,140952,21831,19693,21551,29719,21894,21929,22021,137431,147514,17746,148533,26291,135348,22071,26317,144010,26276,26285,22093,22095,30961,22257,38791,21502,22272,22255,22253,166758,13859,135759,22342,147877,27758,28811,22338,14001,158846,22502,136214,22531,136276,148323,22566,150517,22620,22698,13665,22752,22748,135740,22779,23551,22339,172368,148088,37843,13729,22815,26790,14019,28249,136766,23076,21843,136850,34053,22985,134478,158849,159018,137180,23001,137211,137138,159142,28017,137256,136917,23033,159301,23211,23139,14054,149929,23159,14088,23190,29797,23251,159649,140628,15749,137489,14130,136888,24195,21200,23414,25992,23420,162318,16388,18525,131588,23509,24928,137780,154060,132517,23539,23453,19728,23557,138052,23571,29646,23572,138405,158504,23625,18653,23685,23785,23791,23947,138745,138807,23824,23832,23878,138916,23738,24023,33532,14381,149761,139337,139635,33415,14390,15298,24110,27274,24181,24186,148668,134355,21414,20151,24272,21416,137073,24073,24308,164994,24313,24315,14496,24316,26686,37915,24333,131521,194708,15070,18606,135994,24378,157832,140240,24408,140401,24419,38845,159342,24434,37696,166454,24487,23990,15711,152144,139114,159992,140904,37334,131742,166441,24625,26245,137335,14691,15815,13881,22416,141236,31089,15936,24734,24740,24755,149890,149903,162387,29860,20705,23200,24932,33828,24898,194726,159442,24961,20980,132694,24967,23466,147383,141407,25043,166813,170333,25040,14642,141696,141505,24611,24924,25886,25483,131352,25285,137072,25301,142861,25452,149983,14871,25656,25592,136078,137212,25744,28554,142902,38932,147596,153373,25825,25829,38011,14950,25658,14935,25933,28438,150056,150051,25989,25965,25951,143486,26037,149824,19255,26065,16600,137257,26080,26083,24543,144384,26136,143863,143864,26180,143780,143781,26187,134773,26215,152038,26227,26228,138813,143921,165364,143816,152339,30661,141559,39332,26370,148380,150049,15147,27130,145346,26462,26471,26466,147917,168173,26583,17641,26658,28240,37436,26625,144358,159136,26717,144495,27105,27147,166623,26995,26819,144845,26881,26880,15666,14849,144956,15232,26540,26977,166474,17148,26934,27032,15265,132041,33635,20624,27129,144985,139562,27205,145155,27293,15347,26545,27336,168348,15373,27421,133411,24798,27445,27508,141261,28341,146139,132021,137560,14144,21537,146266,27617,147196,27612,27703,140427,149745,158545,27738,33318,27769,146876,17605,146877,147876,149772,149760,146633,14053,15595,134450,39811,143865,140433,32655,26679,159013,159137,159211,28054,27996,28284,28420,149887,147589,159346,34099,159604,20935,27804,28189,33838,166689,28207,146991,29779,147330,31180,28239,23185,143435,28664,14093,28573,146992,28410,136343,147517,17749,37872,28484,28508,15694,28532,168304,15675,28575,147780,28627,147601,147797,147513,147440,147380,147775,20959,147798,147799,147776,156125,28747,28798,28839,28801,28876,28885,28886,28895,16644,15848,29108,29078,148087,28971,28997,23176,29002,29038,23708,148325,29007,37730,148161,28972,148570,150055,150050,29114,166888,28861,29198,37954,29205,22801,37955,29220,37697,153093,29230,29248,149876,26813,29269,29271,15957,143428,26637,28477,29314,29482,29483,149539,165931,18669,165892,29480,29486,29647,29610,134202,158254,29641,29769,147938,136935,150052,26147,14021,149943,149901,150011,29687,29717,26883,150054,29753,132547,16087,29788,141485,29792,167602,29767,29668,29814,33721,29804,14128,29812,37873,27180,29826,18771,150156,147807,150137,166799,23366,166915,137374,29896,137608,29966,29929,29982,167641,137803,23511,167596,37765,30029,30026,30055,30062,151426,16132,150803,30094,29789,30110,30132,30210,30252,30289,30287,30319,30326,156661,30352,33263,14328,157969,157966,30369,30373,30391,30412,159647,33890,151709,151933,138780,30494,30502,30528,25775,152096,30552,144044,30639,166244,166248,136897,30708,30729,136054,150034,26826,30895,30919,30931,38565,31022,153056,30935,31028,30897,161292,36792,34948,166699,155779,140828,31110,35072,26882,31104,153687,31133,162617,31036,31145,28202,160038,16040,31174,168205,31188],"euc-kr":[44034,44035,44037,44038,44043,44044,44045,44046,44047,44056,44062,44063,44065,44066,44067,44069,44070,44071,44072,44073,44074,44075,44078,44082,44083,44084,null,null,null,null,null,null,44085,44086,44087,44090,44091,44093,44094,44095,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44108,44110,44111,44112,44113,44114,44115,44117,null,null,null,null,null,null,44118,44119,44121,44122,44123,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44146,44147,44149,44150,44153,44155,44156,44157,44158,44159,44162,44167,44168,44173,44174,44175,44177,44178,44179,44181,44182,44183,44184,44185,44186,44187,44190,44194,44195,44196,44197,44198,44199,44203,44205,44206,44209,44210,44211,44212,44213,44214,44215,44218,44222,44223,44224,44226,44227,44229,44230,44231,44233,44234,44235,44237,44238,44239,44240,44241,44242,44243,44244,44246,44248,44249,44250,44251,44252,44253,44254,44255,44258,44259,44261,44262,44265,44267,44269,44270,44274,44276,44279,44280,44281,44282,44283,44286,44287,44289,44290,44291,44293,44295,44296,44297,44298,44299,44302,44304,44306,44307,44308,44309,44310,44311,44313,44314,44315,44317,44318,44319,44321,44322,44323,44324,44325,44326,44327,44328,44330,44331,44334,44335,44336,44337,44338,44339,null,null,null,null,null,null,44342,44343,44345,44346,44347,44349,44350,44351,44352,44353,44354,44355,44358,44360,44362,44363,44364,44365,44366,44367,44369,44370,44371,44373,44374,44375,null,null,null,null,null,null,44377,44378,44379,44380,44381,44382,44383,44384,44386,44388,44389,44390,44391,44392,44393,44394,44395,44398,44399,44401,44402,44407,44408,44409,44410,44414,44416,44419,44420,44421,44422,44423,44426,44427,44429,44430,44431,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44446,44447,44448,44449,44450,44451,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44472,44473,44474,44475,44476,44477,44478,44479,44482,44483,44485,44486,44487,44489,44490,44491,44492,44493,44494,44495,44498,44500,44501,44502,44503,44504,44505,44506,44507,44509,44510,44511,44513,44514,44515,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44538,44539,44541,44542,44546,44547,44548,44549,44550,44551,44554,44556,44558,44559,44560,44561,44562,44563,44565,44566,44567,44568,44569,44570,44571,44572,null,null,null,null,null,null,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589,44590,44591,44594,44595,44597,44598,44601,44603,44604,null,null,null,null,null,null,44605,44606,44607,44610,44612,44615,44616,44617,44619,44623,44625,44626,44627,44629,44631,44632,44633,44634,44635,44638,44642,44643,44644,44646,44647,44650,44651,44653,44654,44655,44657,44658,44659,44660,44661,44662,44663,44666,44670,44671,44672,44673,44674,44675,44678,44679,44680,44681,44682,44683,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44735,44737,44738,44739,44741,44742,44743,44744,44745,44746,44747,44750,44754,44755,44756,44757,44758,44759,44762,44763,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44777,44778,44780,44782,44783,44784,44785,44786,44787,44789,44790,44791,44793,44794,44795,44797,44798,44799,44800,44801,44802,44803,44804,44805,null,null,null,null,null,null,44806,44809,44810,44811,44812,44814,44815,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,null,null,null,null,null,null,44836,44837,44838,44839,44840,44841,44842,44843,44846,44847,44849,44851,44853,44854,44855,44856,44857,44858,44859,44862,44864,44868,44869,44870,44871,44874,44875,44876,44877,44878,44879,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44894,44895,44896,44897,44898,44899,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44922,44923,44924,44925,44926,44927,44929,44930,44931,44933,44934,44935,44937,44938,44939,44940,44941,44942,44943,44946,44947,44948,44950,44951,44952,44953,44954,44955,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44986,44987,44989,44990,44991,44993,44994,44995,44996,44997,44998,45002,45004,45007,45008,45009,45010,45011,45013,45014,45015,45016,45017,45018,45019,45021,45022,45023,45024,45025,null,null,null,null,null,null,45026,45027,45028,45029,45030,45031,45034,45035,45036,45037,45038,45039,45042,45043,45045,45046,45047,45049,45050,45051,45052,45053,45054,45055,45058,45059,null,null,null,null,null,null,45061,45062,45063,45064,45065,45066,45067,45069,45070,45071,45073,45074,45075,45077,45078,45079,45080,45081,45082,45083,45086,45087,45088,45089,45090,45091,45092,45093,45094,45095,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45126,45127,45129,45131,45133,45135,45136,45137,45138,45142,45144,45146,45147,45148,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45182,45183,45185,45186,45187,45189,45190,45191,45192,45193,45194,45195,45198,45200,45202,45203,45204,45205,45206,45207,45211,45213,45214,45219,45220,45221,45222,45223,45226,45232,45234,45238,45239,45241,45242,45243,45245,45246,45247,45248,45249,45250,45251,45254,45258,45259,45260,45261,45262,45263,45266,null,null,null,null,null,null,45267,45269,45270,45271,45273,45274,45275,45276,45277,45278,45279,45281,45282,45283,45284,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,null,null,null,null,null,null,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45322,45325,45326,45327,45329,45332,45333,45334,45335,45338,45342,45343,45344,45345,45346,45350,45351,45353,45354,45355,45357,45358,45359,45360,45361,45362,45363,45366,45370,45371,45372,45373,45374,45375,45378,45379,45381,45382,45383,45385,45386,45387,45388,45389,45390,45391,45394,45395,45398,45399,45401,45402,45403,45405,45406,45407,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,45420,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45434,45435,45437,45438,45439,45441,45443,45444,45445,45446,45447,45450,45452,45454,45455,45456,45457,45461,45462,45463,45465,45466,45467,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,null,null,null,null,null,null,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45517,45518,45519,45521,45522,45523,45525,null,null,null,null,null,null,45526,45527,45528,45529,45530,45531,45534,45536,45537,45538,45539,45540,45541,45542,45543,45546,45547,45549,45550,45551,45553,45554,45555,45556,45557,45558,45559,45560,45562,45564,45566,45567,45568,45569,45570,45571,45574,45575,45577,45578,45581,45582,45583,45584,45585,45586,45587,45590,45592,45594,45595,45596,45597,45598,45599,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45621,45622,45623,45624,45625,45626,45627,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45657,45658,45659,45661,45662,45663,45665,45666,45667,45668,45669,45670,45671,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45686,45687,45688,45689,45690,45691,45693,45694,45695,45696,45697,45698,45699,45702,45703,45704,45706,45707,45708,45709,45710,null,null,null,null,null,null,45711,45714,45715,45717,45718,45719,45723,45724,45725,45726,45727,45730,45732,45735,45736,45737,45739,45741,45742,45743,45745,45746,45747,45749,45750,45751,null,null,null,null,null,null,45752,45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45770,45771,45773,45774,45775,45777,45779,45780,45781,45782,45783,45786,45788,45790,45791,45792,45793,45795,45799,45801,45802,45808,45809,45810,45814,45820,45821,45822,45826,45827,45829,45830,45831,45833,45834,45835,45836,45837,45838,45839,45842,45846,45847,45848,45849,45850,45851,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45911,45913,45914,45917,45920,45921,45922,45923,45926,45928,45930,45932,45933,45935,45938,45939,45941,45942,45943,45945,45946,45947,45948,45949,45950,45951,45954,45958,45959,45960,45961,45962,45963,45965,null,null,null,null,null,null,45966,45967,45969,45970,45971,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45986,45987,45988,45989,45990,45991,45993,45994,45995,45997,null,null,null,null,null,null,45998,45999,46e3,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46022,46023,46025,46026,46029,46031,46033,46034,46035,46038,46040,46042,46044,46046,46047,46049,46050,46051,46053,46054,46055,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46077,46078,46079,46080,46081,46082,46083,46084,46085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46097,46098,46099,46100,46101,46102,46103,46105,46106,46107,46109,46110,46111,46113,46114,46115,46116,46117,46118,46119,46122,46124,46125,46126,46127,46128,46129,46130,46131,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46162,46163,46165,46166,46167,46169,46170,46171,46172,46173,46174,46175,46178,46180,46182,null,null,null,null,null,null,46183,46184,46185,46186,46187,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46209,46210,null,null,null,null,null,null,46211,46212,46213,46214,46215,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46238,46239,46240,46241,46242,46243,46245,46246,46247,46249,46250,46251,46253,46254,46255,46256,46257,46258,46259,46260,46262,46264,46266,46267,46268,46269,46270,46271,46273,46274,46275,46277,46278,46279,46281,46282,46283,46284,46285,46286,46287,46289,46290,46291,46292,46294,46295,46296,46297,46298,46299,46302,46303,46305,46306,46309,46311,46312,46313,46314,46315,46318,46320,46322,46323,46324,46325,46326,46327,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46358,46359,46361,46362,46365,46366,46367,46368,46369,46370,46371,46374,46379,46380,46381,46382,46383,46386,46387,46389,46390,46391,46393,46394,46395,46396,46397,46398,46399,46402,46406,null,null,null,null,null,null,46407,46408,46409,46410,46414,46415,46417,46418,46419,46421,46422,46423,46424,46425,46426,46427,46430,46434,46435,46436,46437,46438,46439,46440,46441,46442,null,null,null,null,null,null,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46498,46499,46501,46502,46503,46505,46508,46509,46510,46511,46514,46518,46519,46520,46521,46522,46526,46527,46529,46530,46531,46533,46534,46535,46536,46537,46538,46539,46542,46546,46547,46548,46549,46550,46551,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46610,46611,46613,46614,46615,46617,46618,46619,46620,46621,null,null,null,null,null,null,46622,46623,46624,46625,46626,46627,46628,46630,46631,46632,46633,46634,46635,46637,46638,46639,46640,46641,46642,46643,46645,46646,46647,46648,46649,46650,null,null,null,null,null,null,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46693,46694,46695,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46750,46751,46753,46754,46755,46757,46758,46759,46760,46761,46762,46765,46766,46767,46768,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46805,46806,46807,46808,46809,46810,46811,46812,46813,null,null,null,null,null,null,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46833,46834,46835,46837,46838,46839,46841,46842,null,null,null,null,null,null,46843,46844,46845,46846,46847,46850,46851,46852,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46890,46891,46893,46894,46897,46898,46899,46900,46901,46902,46903,46906,46908,46909,46910,46911,46912,46913,46914,46915,46917,46918,46919,46921,46922,46923,46925,46926,46927,46928,46929,46930,46931,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46945,46946,46947,46949,46950,46951,46953,46954,46955,46956,46957,46958,46959,46962,46964,46966,46967,46968,46969,46970,46971,46974,46975,46977,46978,46979,46981,46982,46983,46984,46985,46986,46987,46990,46995,46996,46997,47002,47003,47005,47006,47007,47009,47010,47011,47012,47013,47014,47015,47018,47022,47023,47024,47025,47026,47027,47030,47031,47033,47034,47035,47036,47037,47038,47039,47040,47041,null,null,null,null,null,null,47042,47043,47044,47045,47046,47048,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,null,null,null,null,null,null,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47082,47083,47086,47087,47089,47090,47091,47093,47094,47095,47096,47097,47098,47099,47102,47106,47107,47108,47109,47110,47114,47115,47117,47118,47119,47121,47122,47123,47124,47125,47126,47127,47130,47132,47134,47135,47136,47137,47138,47139,47142,47143,47145,47146,47147,47149,47150,47151,47152,47153,47154,47155,47158,47162,47163,47164,47165,47166,47167,47169,47170,47171,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47186,47188,47189,47190,47191,47192,47193,47194,47195,47198,47199,47201,47202,47203,47205,47206,47207,47208,47209,47210,47211,47214,47216,47218,47219,47220,47221,47222,47223,47225,47226,47227,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47246,47247,47248,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,null,null,null,null,null,null,47264,47265,47266,47267,47268,47269,47270,47271,47273,47274,47275,47276,47277,47278,47279,47281,47282,47283,47285,47286,47287,47289,47290,47291,47292,47293,null,null,null,null,null,null,47294,47295,47298,47300,47302,47303,47304,47305,47306,47307,47309,47310,47311,47313,47314,47315,47317,47318,47319,47320,47321,47322,47323,47324,47326,47328,47330,47331,47332,47333,47334,47335,47338,47339,47341,47342,47343,47345,47346,47347,47348,47349,47350,47351,47354,47356,47358,47359,47360,47361,47362,47363,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47385,47386,47387,47388,47389,47390,47391,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,47414,47415,47416,47417,47418,47419,47422,47423,47425,47426,47427,47429,47430,47431,47432,47433,47434,47435,47437,47438,47440,47442,47443,47444,47445,47446,47447,47450,47451,47453,47454,47455,47457,47458,47459,47460,47461,47462,47463,47466,47468,47470,47471,47472,47473,47474,47475,47478,47479,47481,47482,47483,47485,null,null,null,null,null,null,47486,47487,47488,47489,47490,47491,47494,47496,47499,47500,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,null,null,null,null,null,null,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47534,47535,47537,47538,47539,47541,47542,47543,47544,47545,47546,47547,47550,47552,47554,47555,47556,47557,47558,47559,47562,47563,47565,47571,47572,47573,47574,47575,47578,47580,47583,47584,47586,47590,47591,47593,47594,47595,47597,47598,47599,47600,47601,47602,47603,47606,47611,47612,47613,47614,47615,47618,47619,47620,47621,47622,47623,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47674,47675,47677,47678,47679,47681,47683,47684,47685,47686,47687,47690,47692,47695,47696,47697,47698,47702,47703,47705,47706,47707,47709,47710,47711,47712,47713,47714,47715,47718,47722,47723,47724,47725,47726,47727,null,null,null,null,null,null,47730,47731,47733,47734,47735,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,47750,47752,47753,47754,47755,47757,47758,47759,47760,47761,47762,null,null,null,null,null,null,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47786,47789,47790,47791,47793,47795,47796,47797,47798,47799,47802,47804,47806,47807,47808,47809,47810,47811,47813,47814,47815,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47869,47870,47871,47873,47874,47875,47877,47878,47879,47880,47881,47882,47883,47884,47886,47888,47890,47891,47892,47893,47894,47895,47897,47898,47899,47901,47902,47903,47905,47906,47907,47908,47909,47910,47911,47912,47914,47916,47917,47918,47919,47920,47921,47922,47923,47927,47929,47930,47935,47936,47937,47938,47939,47942,47944,47946,47947,47948,47950,47953,47954,null,null,null,null,null,null,47955,47957,47958,47959,47961,47962,47963,47964,47965,47966,47967,47968,47970,47972,47973,47974,47975,47976,47977,47978,47979,47981,47982,47983,47984,47985,null,null,null,null,null,null,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48e3,48001,48002,48003,48004,48005,48006,48007,48009,48010,48011,48013,48014,48015,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48037,48038,48039,48041,48042,48043,48045,48046,48047,48048,48049,48050,48051,48053,48054,48056,48057,48058,48059,48060,48061,48062,48063,48065,48066,48067,48069,48070,48071,48073,48074,48075,48076,48077,48078,48079,48081,48082,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48122,48123,48125,48126,48129,48131,48132,48133,48134,48135,48138,48142,48144,48146,48147,48153,48154,48160,48161,48162,48163,48166,48168,48170,48171,48172,48174,48175,48178,48179,48181,null,null,null,null,null,null,48182,48183,48185,48186,48187,48188,48189,48190,48191,48194,48198,48199,48200,48202,48203,48206,48207,48209,48210,48211,48212,48213,48214,48215,48216,48217,null,null,null,null,null,null,48218,48219,48220,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,48245,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48262,48263,48265,48266,48269,48271,48272,48273,48274,48275,48278,48280,48283,48284,48285,48286,48287,48290,48291,48293,48294,48297,48298,48299,48300,48301,48302,48303,48306,48310,48311,48312,48313,48314,48315,48318,48319,48321,48322,48323,48325,48326,48327,48328,48329,48330,48331,48332,48334,48338,48339,48340,48342,48343,48345,48346,48347,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48375,48377,48378,48379,48381,48382,48383,48384,48385,48386,48387,48390,48392,48394,48395,48396,48397,48398,48399,48401,48402,48403,48405,48406,48407,48408,48409,48410,48411,48412,48413,null,null,null,null,null,null,48414,48415,48416,48417,48418,48419,48421,48422,48423,48424,48425,48426,48427,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,null,null,null,null,null,null,48442,48443,48444,48445,48446,48447,48449,48450,48451,48452,48453,48454,48455,48458,48459,48461,48462,48463,48465,48466,48467,48468,48469,48470,48471,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48485,48486,48487,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48514,48515,48517,48518,48523,48524,48525,48526,48527,48530,48532,48534,48535,48536,48539,48541,48542,48543,48544,48545,48546,48547,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48561,48562,48563,48564,48565,48566,48567,48569,48570,48571,48572,48573,48574,48575,48576,48577,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48598,48599,48601,48602,48603,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48618,48619,48620,48621,48622,48623,48625,null,null,null,null,null,null,48626,48627,48629,48630,48631,48633,48634,48635,48636,48637,48638,48639,48641,48642,48644,48646,48647,48648,48649,48650,48651,48654,48655,48657,48658,48659,null,null,null,null,null,null,48661,48662,48663,48664,48665,48666,48667,48670,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48710,48711,48713,48714,48715,48717,48719,48720,48721,48722,48723,48726,48728,48732,48733,48734,48735,48738,48739,48741,48742,48743,48745,48747,48748,48749,48750,48751,48754,48758,48759,48760,48761,48762,48766,48767,48769,48770,48771,48773,48774,48775,48776,48777,48778,48779,48782,48786,48787,48788,48789,48790,48791,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48850,48851,null,null,null,null,null,null,48853,48854,48857,48858,48859,48860,48861,48862,48863,48865,48866,48870,48871,48872,48873,48874,48875,48877,48878,48879,48880,48881,48882,48883,48884,48885,null,null,null,null,null,null,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48898,48899,48900,48901,48902,48903,48906,48907,48908,48909,48910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48922,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48962,48963,48965,48966,48967,48969,48970,48971,48972,48973,48974,48975,48978,48979,48980,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49e3,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49045,49046,49047,49048,49049,49050,49051,49052,49053,null,null,null,null,null,null,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49073,49074,49075,49076,49077,49078,49079,49080,null,null,null,null,null,null,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49094,49095,49096,49097,49098,49099,49102,49103,49105,49106,49107,49109,49110,49111,49112,49113,49114,49115,49117,49118,49120,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49234,49235,49236,49237,49238,49239,49241,49242,49243,null,null,null,null,null,null,49245,49246,49247,49249,49250,49251,49252,49253,49254,49255,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,null,null,null,null,null,null,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49298,49299,49301,49302,49303,49305,49306,49307,49308,49309,49310,49311,49314,49316,49318,49319,49320,49321,49322,49323,49326,49329,49330,49335,49336,49337,49338,49339,49342,49346,49347,49348,49350,49351,49354,49355,49357,49358,49359,49361,49362,49363,49364,49365,49366,49367,49370,49374,49375,49376,49377,49378,49379,49382,49383,49385,49386,49387,49389,49390,49391,49392,49393,49394,49395,49398,49400,49402,49403,49404,49405,49406,49407,49409,49410,49411,49413,49414,49415,49417,49418,49419,49420,49421,49422,49423,49425,49426,49427,49428,49430,49431,49432,49433,49434,49435,49441,49442,49445,49448,49449,49450,49451,49454,49458,49459,49460,49461,49463,49466,49467,49469,49470,49471,49473,49474,49475,49476,49477,49478,49479,49482,49486,49487,49488,49489,49490,49491,49494,49495,null,null,null,null,null,null,49497,49498,49499,49501,49502,49503,49504,49505,49506,49507,49510,49514,49515,49516,49517,49518,49519,49521,49522,49523,49525,49526,49527,49529,49530,49531,null,null,null,null,null,null,49532,49533,49534,49535,49536,49537,49538,49539,49540,49542,49543,49544,49545,49546,49547,49551,49553,49554,49555,49557,49559,49560,49561,49562,49563,49566,49568,49570,49571,49572,49574,49575,49578,49579,49581,49582,49583,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49598,49599,49600,49601,49602,49603,49605,49606,49607,49609,49610,49611,49613,49614,49615,49616,49617,49618,49619,49621,49622,49625,49626,49627,49628,49629,49630,49631,49633,49634,49635,49637,49638,49639,49641,49642,49643,49644,49645,49646,49647,49650,49652,49653,49654,49655,49656,49657,49658,49659,49662,49663,49665,49666,49667,49669,49670,49671,49672,49673,49674,49675,49678,49680,49682,49683,49684,49685,49686,49687,49690,49691,49693,49694,49697,49698,49699,49700,49701,49702,49703,49706,49708,49710,49712,49715,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,null,null,null,null,null,null,49734,49735,49737,49738,49739,49740,49741,49742,49743,49746,49747,49749,49750,49751,49753,49754,49755,49756,49757,49758,49759,49761,49762,49763,49764,49766,null,null,null,null,null,null,49767,49768,49769,49770,49771,49774,49775,49777,49778,49779,49781,49782,49783,49784,49785,49786,49787,49790,49792,49794,49795,49796,49797,49798,49799,49802,49803,49804,49805,49806,49807,49809,49810,49811,49812,49813,49814,49815,49817,49818,49820,49822,49823,49824,49825,49826,49827,49830,49831,49833,49834,49835,49838,49839,49840,49841,49842,49843,49846,49848,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49886,49887,49889,49890,49893,49894,49895,49896,49897,49898,49902,49904,49906,49907,49908,49909,49911,49914,49917,49918,49919,49921,49922,49923,49924,49925,49926,49927,49930,49931,49934,49935,49936,49937,49938,49942,49943,49945,49946,49947,49949,49950,49951,49952,49953,49954,49955,49958,49959,49962,49963,49964,49965,49966,49967,49968,49969,49970,null,null,null,null,null,null,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49990,49991,49992,49993,49994,49995,49996,49997,null,null,null,null,null,null,49998,49999,5e4,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50026,50027,50029,50030,50031,50033,50035,50036,50037,50038,50039,50042,50043,50046,50047,50048,50049,50050,50051,50053,50054,50055,50057,50058,50059,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50138,50139,50141,50142,50145,50147,50148,50149,50150,50151,50154,50155,50156,50158,50159,50160,50161,50162,50163,50166,50167,50169,50170,50171,50172,50173,50174,null,null,null,null,null,null,50175,50176,50177,50178,50179,50180,50181,50182,50183,50185,50186,50187,50188,50189,50190,50191,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,null,null,null,null,null,null,50203,50204,50205,50206,50207,50208,50209,50210,50211,50213,50214,50215,50216,50217,50218,50219,50221,50222,50223,50225,50226,50227,50229,50230,50231,50232,50233,50234,50235,50238,50239,50240,50241,50242,50243,50244,50245,50246,50247,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50278,50279,50281,50282,50283,50285,50286,50287,50288,50289,50290,50291,50294,50295,50296,50298,50299,50300,50301,50302,50303,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50325,50326,50327,50328,50329,50330,50331,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50361,50362,50363,50365,50366,50367,50368,50369,50370,50371,50372,50373,null,null,null,null,null,null,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,null,null,null,null,null,null,50400,50401,50402,50403,50404,50405,50406,50407,50408,50410,50411,50412,50413,50414,50415,50418,50419,50421,50422,50423,50425,50427,50428,50429,50430,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50445,50446,50447,50449,50450,50451,50453,50454,50455,50456,50457,50458,50459,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50474,50475,50477,50478,50479,50481,50482,50483,50484,50485,50486,50487,50490,50492,50494,50495,50496,50497,50498,50499,50502,50503,50507,50511,50512,50513,50514,50518,50522,50523,50524,50527,50530,50531,50533,50534,50535,50537,50538,50539,50540,50541,50542,50543,50546,50550,50551,50552,50553,50554,50555,50558,50559,50561,50562,50563,50565,50566,50568,50569,50570,50571,50574,50576,50578,50579,50580,50582,50585,50586,50587,50589,50590,50591,50593,50594,50595,50596,50597,50598,50599,50600,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50614,null,null,null,null,null,null,50615,50618,50623,50624,50625,50626,50627,50635,50637,50639,50642,50643,50645,50646,50647,50649,50650,50651,50652,50653,50654,50655,50658,50660,50662,50663,null,null,null,null,null,null,50664,50665,50666,50667,50671,50673,50674,50675,50677,50680,50681,50682,50683,50690,50691,50692,50697,50698,50699,50701,50702,50703,50705,50706,50707,50708,50709,50710,50711,50714,50717,50718,50719,50720,50721,50722,50723,50726,50727,50729,50730,50731,50735,50737,50738,50742,50744,50746,50748,50749,50750,50751,50754,50755,50757,50758,50759,50761,50762,50763,50764,50765,50766,50767,50770,50774,50775,50776,50777,50778,50779,50782,50783,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50797,50798,50800,50802,50803,50804,50805,50806,50807,50810,50811,50813,50814,50815,50817,50818,50819,50820,50821,50822,50823,50826,50828,50830,50831,50832,50833,50834,50835,50838,50839,50841,50842,50843,50845,50846,50847,50848,50849,50850,50851,50854,50856,50858,50859,50860,50861,50862,50863,50866,50867,50869,50870,50871,50875,50876,50877,50878,50879,50882,50884,50886,50887,50888,50889,50890,50891,50894,null,null,null,null,null,null,50895,50897,50898,50899,50901,50902,50903,50904,50905,50906,50907,50910,50911,50914,50915,50916,50917,50918,50919,50922,50923,50925,50926,50927,50929,50930,null,null,null,null,null,null,50931,50932,50933,50934,50935,50938,50939,50940,50942,50943,50944,50945,50946,50947,50950,50951,50953,50954,50955,50957,50958,50959,50960,50961,50962,50963,50966,50968,50970,50971,50972,50973,50974,50975,50978,50979,50981,50982,50983,50985,50986,50987,50988,50989,50990,50991,50994,50996,50998,51e3,51001,51002,51003,51006,51007,51009,51010,51011,51013,51014,51015,51016,51017,51019,51022,51024,51033,51034,51035,51037,51038,51039,51041,51042,51043,51044,51045,51046,51047,51049,51050,51052,51053,51054,51055,51056,51057,51058,51059,51062,51063,51065,51066,51067,51071,51072,51073,51074,51078,51083,51084,51085,51087,51090,51091,51093,51097,51099,51100,51101,51102,51103,51106,51111,51112,51113,51114,51115,51118,51119,51121,51122,51123,51125,51126,51127,51128,51129,51130,51131,51134,51138,51139,51140,51141,51142,51143,51146,51147,51149,51151,51153,51154,51155,51156,51157,51158,51159,51161,51162,51163,51164,null,null,null,null,null,null,51166,51167,51168,51169,51170,51171,51173,51174,51175,51177,51178,51179,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,null,null,null,null,null,null,51195,51196,51197,51198,51199,51202,51203,51205,51206,51207,51209,51211,51212,51213,51214,51215,51218,51220,51223,51224,51225,51226,51227,51230,51231,51233,51234,51235,51237,51238,51239,51240,51241,51242,51243,51246,51248,51250,51251,51252,51253,51254,51255,51257,51258,51259,51261,51262,51263,51265,51266,51267,51268,51269,51270,51271,51274,51275,51278,51279,51280,51281,51282,51283,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51314,51315,51317,51318,51319,51321,51323,51324,51325,51326,51327,51330,51332,51336,51337,51338,51342,51343,51344,51345,51346,51347,51349,51350,51351,51352,51353,51354,51355,51356,51358,51360,51362,51363,51364,51365,51366,51367,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51390,51391,51392,51393,null,null,null,null,null,null,51394,51395,51397,51398,51399,51401,51402,51403,51405,51406,51407,51408,51409,51410,51411,51414,51416,51418,51419,51420,51421,51422,51423,51426,51427,51429,null,null,null,null,null,null,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51446,51447,51448,51449,51450,51451,51454,51455,51457,51458,51459,51463,51464,51465,51466,51467,51470,12288,12289,12290,183,8229,8230,168,12291,173,8213,8741,65340,8764,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,177,215,247,8800,8804,8805,8734,8756,176,8242,8243,8451,8491,65504,65505,65509,9794,9792,8736,8869,8978,8706,8711,8801,8786,167,8251,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8594,8592,8593,8595,8596,12307,8810,8811,8730,8765,8733,8757,8747,8748,8712,8715,8838,8839,8834,8835,8746,8745,8743,8744,65506,51472,51474,51475,51476,51477,51478,51479,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,null,null,null,null,null,null,51501,51502,51503,51504,51505,51506,51507,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,null,null,null,null,null,null,51528,51529,51530,51531,51532,51533,51534,51535,51538,51539,51541,51542,51543,51545,51546,51547,51548,51549,51550,51551,51554,51556,51557,51558,51559,51560,51561,51562,51563,51565,51566,51567,8658,8660,8704,8707,180,65374,711,728,733,730,729,184,731,161,191,720,8750,8721,8719,164,8457,8240,9665,9664,9655,9654,9828,9824,9825,9829,9831,9827,8857,9672,9635,9680,9681,9618,9636,9637,9640,9639,9638,9641,9832,9743,9742,9756,9758,182,8224,8225,8597,8599,8601,8598,8600,9837,9833,9834,9836,12927,12828,8470,13255,8482,13250,13272,8481,8364,174,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51569,51570,51571,51573,51574,51575,51576,51577,51578,51579,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51594,51595,51597,51598,51599,null,null,null,null,null,null,51601,51602,51603,51604,51605,51606,51607,51610,51612,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,null,null,null,null,null,null,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51650,51651,51653,51654,51657,51659,51660,51661,51662,51663,51666,51668,51671,51672,51675,65281,65282,65283,65284,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65510,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,51678,51679,51681,51683,51685,51686,51688,51689,51690,51691,51694,51698,51699,51700,51701,51702,51703,51706,51707,51709,51710,51711,51713,51714,51715,51716,null,null,null,null,null,null,51717,51718,51719,51722,51726,51727,51728,51729,51730,51731,51733,51734,51735,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,null,null,null,null,null,null,51750,51751,51752,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,12683,12684,12685,12686,51783,51784,51785,51786,51787,51790,51791,51793,51794,51795,51797,51798,51799,51800,51801,51802,51803,51806,51810,51811,51812,51813,51814,51815,51817,51818,null,null,null,null,null,null,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51838,51839,51840,51841,51842,51843,51845,51846,null,null,null,null,null,null,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,null,null,null,null,null,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51902,51903,51905,51906,51907,51909,null,null,null,null,null,null,51910,51911,51912,51913,51914,51915,51918,51920,51922,51924,51925,51926,51927,51930,51931,51932,51933,51934,51935,51937,51938,51939,51940,51941,51942,51943,null,null,null,null,null,null,51944,51945,51946,51947,51949,51950,51951,51952,51953,51954,51955,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51977,51978,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,9490,9489,9498,9497,9494,9493,9486,9485,9502,9503,9505,9506,9510,9511,9513,9514,9517,9518,9521,9522,9525,9526,9529,9530,9533,9534,9536,9537,9539,9540,9541,9542,9543,9544,9545,9546,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,51979,51980,51981,51982,51983,51985,51986,51987,51989,51990,51991,51993,51994,51995,51996,51997,51998,51999,52002,52003,52004,52005,52006,52007,52008,52009,null,null,null,null,null,null,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52034,52035,52036,null,null,null,null,null,null,52037,52038,52039,52042,52043,52045,52046,52047,52049,52050,52051,52052,52053,52054,52055,52058,52059,52060,52062,52063,52064,52065,52066,52067,52069,52070,52071,52072,52073,52074,52075,52076,13205,13206,13207,8467,13208,13252,13219,13220,13221,13222,13209,13210,13211,13212,13213,13214,13215,13216,13217,13218,13258,13197,13198,13199,13263,13192,13193,13256,13223,13224,13232,13233,13234,13235,13236,13237,13238,13239,13240,13241,13184,13185,13186,13187,13188,13242,13243,13244,13245,13246,13247,13200,13201,13202,13203,13204,8486,13248,13249,13194,13195,13196,13270,13253,13229,13230,13231,13275,13225,13226,13227,13228,13277,13264,13267,13251,13257,13276,13254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,null,null,null,null,null,null,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52125,52126,52127,52128,52129,52130,52131,null,null,null,null,null,null,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,198,208,170,294,null,306,null,319,321,216,338,186,222,358,330,null,12896,12897,12898,12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,12923,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433,9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,189,8531,8532,188,190,8539,8540,8541,8542,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,null,null,null,null,null,null,52192,52193,52194,52195,52197,52198,52200,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,null,null,null,null,null,null,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,52233,52234,52235,52238,52239,52241,52242,52243,52245,52246,52247,52248,52249,52250,52251,52254,52255,52256,52259,52260,230,273,240,295,305,307,312,320,322,248,339,223,254,359,331,329,12800,12801,12802,12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,12827,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,185,178,179,8308,8319,8321,8322,8323,8324,52261,52262,52266,52267,52269,52271,52273,52274,52275,52276,52277,52278,52279,52282,52287,52288,52289,52290,52291,52294,52295,52297,52298,52299,52301,52302,null,null,null,null,null,null,52303,52304,52305,52306,52307,52310,52314,52315,52316,52317,52318,52319,52321,52322,52323,52325,52327,52329,52330,52331,52332,52333,52334,52335,52337,52338,null,null,null,null,null,null,52339,52340,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,52372,52373,52374,52375,52378,52379,52381,52382,52383,52385,52386,52387,52388,52389,52390,52391,52394,52398,52399,52400,52401,52402,52403,52406,52407,52409,null,null,null,null,null,null,52410,52411,52413,52414,52415,52416,52417,52418,52419,52422,52424,52426,52427,52428,52429,52430,52431,52433,52434,52435,52437,52438,52439,52440,52441,52442,null,null,null,null,null,null,52443,52444,52445,52446,52447,52448,52449,52450,52451,52453,52454,52455,52456,52457,52458,52459,52461,52462,52463,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,52478,52479,52480,52482,52483,52484,52485,52486,52487,52490,52491,52493,52494,52495,52497,52498,52499,52500,52501,52502,52503,52506,52508,52510,52511,52512,null,null,null,null,null,null,52513,52514,52515,52517,52518,52519,52521,52522,52523,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52538,52539,52540,52541,52542,null,null,null,null,null,null,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565,52566,52567,52568,52569,52570,52571,52573,52574,52575,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,52577,52578,52579,52581,52582,52583,52584,52585,52586,52587,52590,52592,52594,52595,52596,52597,52598,52599,52601,52602,52603,52604,52605,52606,52607,52608,null,null,null,null,null,null,52609,52610,52611,52612,52613,52614,52615,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52630,52631,52633,52634,52635,52637,52638,52639,null,null,null,null,null,null,52640,52641,52642,52643,52646,52648,52650,52651,52652,52653,52654,52655,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52677,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52678,52679,52680,52681,52682,52683,52685,52686,52687,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,null,null,null,null,null,null,52706,52707,52708,52709,52710,52711,52713,52714,52715,52717,52718,52719,52721,52722,52723,52724,52725,52726,52727,52730,52732,52734,52735,52736,52737,52738,null,null,null,null,null,null,52739,52741,52742,52743,52745,52746,52747,52749,52750,52751,52752,52753,52754,52755,52757,52758,52759,52760,52762,52763,52764,52765,52766,52767,52770,52771,52773,52774,52775,52777,52778,52779,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52780,52781,52782,52783,52786,52788,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,null,null,null,null,null,null,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52826,52827,52829,52830,52834,52835,52836,52837,52838,52839,52842,52844,null,null,null,null,null,null,52846,52847,52848,52849,52850,52851,52854,52855,52857,52858,52859,52861,52862,52863,52864,52865,52866,52867,52870,52872,52874,52875,52876,52877,52878,52879,52882,52883,52885,52886,52887,52889,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,52890,52891,52892,52893,52894,52895,52898,52902,52903,52904,52905,52906,52907,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,null,null,null,null,null,null,52923,52924,52925,52926,52927,52928,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,null,null,null,null,null,null,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52966,52967,52969,52970,52973,52974,52975,52976,52977,52978,52979,52982,52986,52987,52988,52989,52990,52991,44032,44033,44036,44039,44040,44041,44042,44048,44049,44050,44051,44052,44053,44054,44055,44057,44058,44059,44060,44061,44064,44068,44076,44077,44079,44080,44081,44088,44089,44092,44096,44107,44109,44116,44120,44124,44144,44145,44148,44151,44152,44154,44160,44161,44163,44164,44165,44166,44169,44170,44171,44172,44176,44180,44188,44189,44191,44192,44193,44200,44201,44202,44204,44207,44208,44216,44217,44219,44220,44221,44225,44228,44232,44236,44245,44247,44256,44257,44260,44263,44264,44266,44268,44271,44272,44273,44275,44277,44278,44284,44285,44288,44292,44294,52994,52995,52997,52998,52999,53001,53002,53003,53004,53005,53006,53007,53010,53012,53014,53015,53016,53017,53018,53019,53021,53022,53023,53025,53026,53027,null,null,null,null,null,null,53029,53030,53031,53032,53033,53034,53035,53038,53042,53043,53044,53045,53046,53047,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,null,null,null,null,null,null,53061,53062,53063,53064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53078,53079,53081,53082,53083,53085,53086,53087,53088,53089,53090,53091,53094,53096,53098,53099,53100,44300,44301,44303,44305,44312,44316,44320,44329,44332,44333,44340,44341,44344,44348,44356,44357,44359,44361,44368,44372,44376,44385,44387,44396,44397,44400,44403,44404,44405,44406,44411,44412,44413,44415,44417,44418,44424,44425,44428,44432,44444,44445,44452,44471,44480,44481,44484,44488,44496,44497,44499,44508,44512,44516,44536,44537,44540,44543,44544,44545,44552,44553,44555,44557,44564,44592,44593,44596,44599,44600,44602,44608,44609,44611,44613,44614,44618,44620,44621,44622,44624,44628,44630,44636,44637,44639,44640,44641,44645,44648,44649,44652,44656,44664,53101,53102,53103,53106,53107,53109,53110,53111,53113,53114,53115,53116,53117,53118,53119,53121,53122,53123,53124,53126,53127,53128,53129,53130,53131,53133,null,null,null,null,null,null,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53154,53155,53156,53157,53158,53159,53161,null,null,null,null,null,null,53162,53163,53164,53165,53166,53167,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53189,53190,53191,53192,53193,53194,53195,44665,44667,44668,44669,44676,44677,44684,44732,44733,44734,44736,44740,44748,44749,44751,44752,44753,44760,44761,44764,44776,44779,44781,44788,44792,44796,44807,44808,44813,44816,44844,44845,44848,44850,44852,44860,44861,44863,44865,44866,44867,44872,44873,44880,44892,44893,44900,44901,44921,44928,44932,44936,44944,44945,44949,44956,44984,44985,44988,44992,44999,45e3,45001,45003,45005,45006,45012,45020,45032,45033,45040,45041,45044,45048,45056,45057,45060,45068,45072,45076,45084,45085,45096,45124,45125,45128,45130,45132,45134,45139,45140,45141,45143,45145,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53218,53219,53221,53222,53223,53225,null,null,null,null,null,null,53226,53227,53228,53229,53230,53231,53234,53236,53238,53239,53240,53241,53242,53243,53245,53246,53247,53249,53250,53251,53253,53254,53255,53256,53257,53258,null,null,null,null,null,null,53259,53260,53261,53262,53263,53264,53266,53267,53268,53269,53270,53271,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,45149,45180,45181,45184,45188,45196,45197,45199,45201,45208,45209,45210,45212,45215,45216,45217,45218,45224,45225,45227,45228,45229,45230,45231,45233,45235,45236,45237,45240,45244,45252,45253,45255,45256,45257,45264,45265,45268,45272,45280,45285,45320,45321,45323,45324,45328,45330,45331,45336,45337,45339,45340,45341,45347,45348,45349,45352,45356,45364,45365,45367,45368,45369,45376,45377,45380,45384,45392,45393,45396,45397,45400,45404,45408,45432,45433,45436,45440,45442,45448,45449,45451,45453,45458,45459,45460,45464,45468,45480,45516,45520,45524,45532,45533,53294,53295,53296,53297,53298,53299,53302,53303,53305,53306,53307,53309,53310,53311,53312,53313,53314,53315,53318,53320,53322,53323,53324,53325,53326,53327,null,null,null,null,null,null,53329,53330,53331,53333,53334,53335,53337,53338,53339,53340,53341,53342,53343,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53358,53359,null,null,null,null,null,null,53361,53362,53363,53365,53366,53367,53368,53369,53370,53371,53374,53375,53376,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,53396,45535,45544,45545,45548,45552,45561,45563,45565,45572,45573,45576,45579,45580,45588,45589,45591,45593,45600,45620,45628,45656,45660,45664,45672,45673,45684,45685,45692,45700,45701,45705,45712,45713,45716,45720,45721,45722,45728,45729,45731,45733,45734,45738,45740,45744,45748,45768,45769,45772,45776,45778,45784,45785,45787,45789,45794,45796,45797,45798,45800,45803,45804,45805,45806,45807,45811,45812,45813,45815,45816,45817,45818,45819,45823,45824,45825,45828,45832,45840,45841,45843,45844,45845,45852,45908,45909,45910,45912,45915,45916,45918,45919,45924,45925,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53414,53415,53417,53418,53419,53421,53422,53423,53424,53425,53426,null,null,null,null,null,null,53427,53430,53432,53434,53435,53436,53437,53438,53439,53442,53443,53445,53446,53447,53450,53451,53452,53453,53454,53455,53458,53462,53463,53464,53465,53466,null,null,null,null,null,null,53467,53470,53471,53473,53474,53475,53477,53478,53479,53480,53481,53482,53483,53486,53490,53491,53492,53493,53494,53495,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,45927,45929,45931,45934,45936,45937,45940,45944,45952,45953,45955,45956,45957,45964,45968,45972,45984,45985,45992,45996,46020,46021,46024,46027,46028,46030,46032,46036,46037,46039,46041,46043,46045,46048,46052,46056,46076,46096,46104,46108,46112,46120,46121,46123,46132,46160,46161,46164,46168,46176,46177,46179,46181,46188,46208,46216,46237,46244,46248,46252,46261,46263,46265,46272,46276,46280,46288,46293,46300,46301,46304,46307,46308,46310,46316,46317,46319,46321,46328,46356,46357,46360,46363,46364,46372,46373,46375,46376,46377,46378,46384,46385,46388,46392,53509,53510,53511,53512,53513,53514,53515,53516,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,null,null,null,null,null,null,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53554,53555,53557,53558,53559,53561,53563,53564,53565,53566,null,null,null,null,null,null,53567,53570,53574,53575,53576,53577,53578,53579,53582,53583,53585,53586,53587,53589,53590,53591,53592,53593,53594,53595,53598,53600,53602,53603,53604,53605,53606,53607,53609,53610,53611,53613,46400,46401,46403,46404,46405,46411,46412,46413,46416,46420,46428,46429,46431,46432,46433,46496,46497,46500,46504,46506,46507,46512,46513,46515,46516,46517,46523,46524,46525,46528,46532,46540,46541,46543,46544,46545,46552,46572,46608,46609,46612,46616,46629,46636,46644,46664,46692,46696,46748,46749,46752,46756,46763,46764,46769,46804,46832,46836,46840,46848,46849,46853,46888,46889,46892,46895,46896,46904,46905,46907,46916,46920,46924,46932,46933,46944,46948,46952,46960,46961,46963,46965,46972,46973,46976,46980,46988,46989,46991,46992,46993,46994,46998,46999,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53629,53630,53631,53632,53633,53634,53635,53637,53638,53639,53641,53642,null,null,null,null,null,null,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53666,53667,53669,53670,53671,null,null,null,null,null,null,53673,53674,53675,53676,53677,53678,53679,53682,53684,53686,53687,53688,53689,53691,53693,53694,53695,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,47e3,47001,47004,47008,47016,47017,47019,47020,47021,47028,47029,47032,47047,47049,47084,47085,47088,47092,47100,47101,47103,47104,47105,47111,47112,47113,47116,47120,47128,47129,47131,47133,47140,47141,47144,47148,47156,47157,47159,47160,47161,47168,47172,47185,47187,47196,47197,47200,47204,47212,47213,47215,47217,47224,47228,47245,47272,47280,47284,47288,47296,47297,47299,47301,47308,47312,47316,47325,47327,47329,47336,47337,47340,47344,47352,47353,47355,47357,47364,47384,47392,47420,47421,47424,47428,47436,47439,47441,47448,47449,47452,47456,47464,47465,53712,53713,53714,53715,53716,53717,53718,53719,53721,53722,53723,53724,53725,53726,53727,53728,53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,null,null,null,null,null,null,53739,53740,53741,53742,53743,53744,53745,53746,53747,53749,53750,53751,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,null,null,null,null,null,null,53768,53770,53771,53772,53773,53774,53775,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,47467,47469,47476,47477,47480,47484,47492,47493,47495,47497,47498,47501,47502,47532,47533,47536,47540,47548,47549,47551,47553,47560,47561,47564,47566,47567,47568,47569,47570,47576,47577,47579,47581,47582,47585,47587,47588,47589,47592,47596,47604,47605,47607,47608,47609,47610,47616,47617,47624,47637,47672,47673,47676,47680,47682,47688,47689,47691,47693,47694,47699,47700,47701,47704,47708,47716,47717,47719,47720,47721,47728,47729,47732,47736,47747,47748,47749,47751,47756,47784,47785,47787,47788,47792,47794,47800,47801,47803,47805,47812,47816,47832,47833,47868,53802,53803,53806,53807,53809,53810,53811,53813,53814,53815,53816,53817,53818,53819,53822,53824,53826,53827,53828,53829,53830,53831,53833,53834,53835,53836,null,null,null,null,null,null,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53853,53854,53855,53856,53857,53858,53859,53861,53862,53863,53864,null,null,null,null,null,null,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53890,53891,53893,53894,53895,53897,53898,53899,53900,47872,47876,47885,47887,47889,47896,47900,47904,47913,47915,47924,47925,47926,47928,47931,47932,47933,47934,47940,47941,47943,47945,47949,47951,47952,47956,47960,47969,47971,47980,48008,48012,48016,48036,48040,48044,48052,48055,48064,48068,48072,48080,48083,48120,48121,48124,48127,48128,48130,48136,48137,48139,48140,48141,48143,48145,48148,48149,48150,48151,48152,48155,48156,48157,48158,48159,48164,48165,48167,48169,48173,48176,48177,48180,48184,48192,48193,48195,48196,48197,48201,48204,48205,48208,48221,48260,48261,48264,48267,48268,48270,48276,48277,48279,53901,53902,53903,53906,53907,53908,53910,53911,53912,53913,53914,53915,53917,53918,53919,53921,53922,53923,53925,53926,53927,53928,53929,53930,53931,53933,null,null,null,null,null,null,53934,53935,53936,53938,53939,53940,53941,53942,53943,53946,53947,53949,53950,53953,53955,53956,53957,53958,53959,53962,53964,53965,53966,53967,53968,53969,null,null,null,null,null,null,53970,53971,53973,53974,53975,53977,53978,53979,53981,53982,53983,53984,53985,53986,53987,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54002,54003,54005,54006,54007,54009,54010,48281,48282,48288,48289,48292,48295,48296,48304,48305,48307,48308,48309,48316,48317,48320,48324,48333,48335,48336,48337,48341,48344,48348,48372,48373,48374,48376,48380,48388,48389,48391,48393,48400,48404,48420,48428,48448,48456,48457,48460,48464,48472,48473,48484,48488,48512,48513,48516,48519,48520,48521,48522,48528,48529,48531,48533,48537,48538,48540,48548,48560,48568,48596,48597,48600,48604,48617,48624,48628,48632,48640,48643,48645,48652,48653,48656,48660,48668,48669,48671,48708,48709,48712,48716,48718,48724,48725,48727,48729,48730,48731,48736,48737,48740,54011,54012,54013,54014,54015,54018,54020,54022,54023,54024,54025,54026,54027,54031,54033,54034,54035,54037,54039,54040,54041,54042,54043,54046,54050,54051,null,null,null,null,null,null,54052,54054,54055,54058,54059,54061,54062,54063,54065,54066,54067,54068,54069,54070,54071,54074,54078,54079,54080,54081,54082,54083,54086,54087,54088,54089,null,null,null,null,null,null,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,48744,48746,48752,48753,48755,48756,48757,48763,48764,48765,48768,48772,48780,48781,48783,48784,48785,48792,48793,48808,48848,48849,48852,48855,48856,48864,48867,48868,48869,48876,48897,48904,48905,48920,48921,48923,48924,48925,48960,48961,48964,48968,48976,48977,48981,49044,49072,49093,49100,49101,49104,49108,49116,49119,49121,49212,49233,49240,49244,49248,49256,49257,49296,49297,49300,49304,49312,49313,49315,49317,49324,49325,49327,49328,49331,49332,49333,49334,49340,49341,49343,49344,49345,49349,49352,49353,49356,49360,49368,49369,49371,49372,49373,49380,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54142,54143,54145,54146,54147,54149,54150,54151,null,null,null,null,null,null,54152,54153,54154,54155,54158,54162,54163,54164,54165,54166,54167,54170,54171,54173,54174,54175,54177,54178,54179,54180,54181,54182,54183,54186,54188,54190,null,null,null,null,null,null,54191,54192,54193,54194,54195,54197,54198,54199,54201,54202,54203,54205,54206,54207,54208,54209,54210,54211,54214,54215,54218,54219,54220,54221,54222,54223,54225,54226,54227,54228,54229,54230,49381,49384,49388,49396,49397,49399,49401,49408,49412,49416,49424,49429,49436,49437,49438,49439,49440,49443,49444,49446,49447,49452,49453,49455,49456,49457,49462,49464,49465,49468,49472,49480,49481,49483,49484,49485,49492,49493,49496,49500,49508,49509,49511,49512,49513,49520,49524,49528,49541,49548,49549,49550,49552,49556,49558,49564,49565,49567,49569,49573,49576,49577,49580,49584,49597,49604,49608,49612,49620,49623,49624,49632,49636,49640,49648,49649,49651,49660,49661,49664,49668,49676,49677,49679,49681,49688,49689,49692,49695,49696,49704,49705,49707,49709,54231,54233,54234,54235,54236,54237,54238,54239,54240,54242,54244,54245,54246,54247,54248,54249,54250,54251,54254,54255,54257,54258,54259,54261,54262,54263,null,null,null,null,null,null,54264,54265,54266,54267,54270,54272,54274,54275,54276,54277,54278,54279,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,null,null,null,null,null,null,54295,54296,54297,54298,54299,54300,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,49711,49713,49714,49716,49736,49744,49745,49748,49752,49760,49765,49772,49773,49776,49780,49788,49789,49791,49793,49800,49801,49808,49816,49819,49821,49828,49829,49832,49836,49837,49844,49845,49847,49849,49884,49885,49888,49891,49892,49899,49900,49901,49903,49905,49910,49912,49913,49915,49916,49920,49928,49929,49932,49933,49939,49940,49941,49944,49948,49956,49957,49960,49961,49989,50024,50025,50028,50032,50034,50040,50041,50044,50045,50052,50056,50060,50112,50136,50137,50140,50143,50144,50146,50152,50153,50157,50164,50165,50168,50184,50192,50212,50220,50224,54328,54329,54330,54331,54332,54333,54334,54335,54337,54338,54339,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,null,null,null,null,null,null,54356,54357,54358,54359,54360,54361,54362,54363,54365,54366,54367,54369,54370,54371,54373,54374,54375,54376,54377,54378,54379,54380,54382,54384,54385,54386,null,null,null,null,null,null,54387,54388,54389,54390,54391,54394,54395,54397,54398,54401,54403,54404,54405,54406,54407,54410,54412,54414,54415,54416,54417,54418,54419,54421,54422,54423,54424,54425,54426,54427,54428,54429,50228,50236,50237,50248,50276,50277,50280,50284,50292,50293,50297,50304,50324,50332,50360,50364,50409,50416,50417,50420,50424,50426,50431,50432,50433,50444,50448,50452,50460,50472,50473,50476,50480,50488,50489,50491,50493,50500,50501,50504,50505,50506,50508,50509,50510,50515,50516,50517,50519,50520,50521,50525,50526,50528,50529,50532,50536,50544,50545,50547,50548,50549,50556,50557,50560,50564,50567,50572,50573,50575,50577,50581,50583,50584,50588,50592,50601,50612,50613,50616,50617,50619,50620,50621,50622,50628,50629,50630,50631,50632,50633,50634,50636,50638,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,null,null,null,null,null,null,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54477,54478,54479,54481,54482,54483,54485,null,null,null,null,null,null,54486,54487,54488,54489,54490,54491,54493,54494,54496,54497,54498,54499,54500,54501,54502,54503,54505,54506,54507,54509,54510,54511,54513,54514,54515,54516,54517,54518,54519,54521,54522,54524,50640,50641,50644,50648,50656,50657,50659,50661,50668,50669,50670,50672,50676,50678,50679,50684,50685,50686,50687,50688,50689,50693,50694,50695,50696,50700,50704,50712,50713,50715,50716,50724,50725,50728,50732,50733,50734,50736,50739,50740,50741,50743,50745,50747,50752,50753,50756,50760,50768,50769,50771,50772,50773,50780,50781,50784,50796,50799,50801,50808,50809,50812,50816,50824,50825,50827,50829,50836,50837,50840,50844,50852,50853,50855,50857,50864,50865,50868,50872,50873,50874,50880,50881,50883,50885,50892,50893,50896,50900,50908,50909,50912,50913,50920,54526,54527,54528,54529,54530,54531,54533,54534,54535,54537,54538,54539,54541,54542,54543,54544,54545,54546,54547,54550,54552,54553,54554,54555,54556,54557,null,null,null,null,null,null,54558,54559,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,null,null,null,null,null,null,54584,54585,54586,54587,54590,54591,54593,54594,54595,54597,54598,54599,54600,54601,54602,54603,54606,54608,54610,54611,54612,54613,54614,54615,54618,54619,54621,54622,54623,54625,54626,54627,50921,50924,50928,50936,50937,50941,50948,50949,50952,50956,50964,50965,50967,50969,50976,50977,50980,50984,50992,50993,50995,50997,50999,51004,51005,51008,51012,51018,51020,51021,51023,51025,51026,51027,51028,51029,51030,51031,51032,51036,51040,51048,51051,51060,51061,51064,51068,51069,51070,51075,51076,51077,51079,51080,51081,51082,51086,51088,51089,51092,51094,51095,51096,51098,51104,51105,51107,51108,51109,51110,51116,51117,51120,51124,51132,51133,51135,51136,51137,51144,51145,51148,51150,51152,51160,51165,51172,51176,51180,51200,51201,51204,51208,51210,54628,54630,54631,54634,54636,54638,54639,54640,54641,54642,54643,54646,54647,54649,54650,54651,54653,54654,54655,54656,54657,54658,54659,54662,54666,54667,null,null,null,null,null,null,54668,54669,54670,54671,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54694,54695,null,null,null,null,null,null,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,54726,54727,51216,51217,51219,51221,51222,51228,51229,51232,51236,51244,51245,51247,51249,51256,51260,51264,51272,51273,51276,51277,51284,51312,51313,51316,51320,51322,51328,51329,51331,51333,51334,51335,51339,51340,51341,51348,51357,51359,51361,51368,51388,51389,51396,51400,51404,51412,51413,51415,51417,51424,51425,51428,51445,51452,51453,51456,51460,51461,51462,51468,51469,51471,51473,51480,51500,51508,51536,51537,51540,51544,51552,51553,51555,51564,51568,51572,51580,51592,51593,51596,51600,51608,51609,51611,51613,51648,51649,51652,51655,51656,51658,51664,51665,51667,54730,54731,54733,54734,54735,54737,54739,54740,54741,54742,54743,54746,54748,54750,54751,54752,54753,54754,54755,54758,54759,54761,54762,54763,54765,54766,null,null,null,null,null,null,54767,54768,54769,54770,54771,54774,54776,54778,54779,54780,54781,54782,54783,54786,54787,54789,54790,54791,54793,54794,54795,54796,54797,54798,54799,54802,null,null,null,null,null,null,54806,54807,54808,54809,54810,54811,54813,54814,54815,54817,54818,54819,54821,54822,54823,54824,54825,54826,54827,54828,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54842,54843,51669,51670,51673,51674,51676,51677,51680,51682,51684,51687,51692,51693,51695,51696,51697,51704,51705,51708,51712,51720,51721,51723,51724,51725,51732,51736,51753,51788,51789,51792,51796,51804,51805,51807,51808,51809,51816,51837,51844,51864,51900,51901,51904,51908,51916,51917,51919,51921,51923,51928,51929,51936,51948,51956,51976,51984,51988,51992,52e3,52001,52033,52040,52041,52044,52048,52056,52057,52061,52068,52088,52089,52124,52152,52180,52196,52199,52201,52236,52237,52240,52244,52252,52253,52257,52258,52263,52264,52265,52268,52270,52272,52280,52281,52283,54845,54846,54847,54849,54850,54851,54852,54854,54855,54858,54860,54862,54863,54864,54866,54867,54870,54871,54873,54874,54875,54877,54878,54879,54880,54881,null,null,null,null,null,null,54882,54883,54884,54885,54886,54888,54890,54891,54892,54893,54894,54895,54898,54899,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,null,null,null,null,null,null,54913,54914,54916,54918,54919,54920,54921,54922,54923,54926,54927,54929,54930,54931,54933,54934,54935,54936,54937,54938,54939,54940,54942,54944,54946,54947,54948,54949,54950,54951,54953,54954,52284,52285,52286,52292,52293,52296,52300,52308,52309,52311,52312,52313,52320,52324,52326,52328,52336,52341,52376,52377,52380,52384,52392,52393,52395,52396,52397,52404,52405,52408,52412,52420,52421,52423,52425,52432,52436,52452,52460,52464,52481,52488,52489,52492,52496,52504,52505,52507,52509,52516,52520,52524,52537,52572,52576,52580,52588,52589,52591,52593,52600,52616,52628,52629,52632,52636,52644,52645,52647,52649,52656,52676,52684,52688,52712,52716,52720,52728,52729,52731,52733,52740,52744,52748,52756,52761,52768,52769,52772,52776,52784,52785,52787,52789,54955,54957,54958,54959,54961,54962,54963,54964,54965,54966,54967,54968,54970,54972,54973,54974,54975,54976,54977,54978,54979,54982,54983,54985,54986,54987,null,null,null,null,null,null,54989,54990,54991,54992,54994,54995,54997,54998,55e3,55002,55003,55004,55005,55006,55007,55009,55010,55011,55013,55014,55015,55017,55018,55019,55020,55021,null,null,null,null,null,null,55022,55023,55025,55026,55027,55028,55030,55031,55032,55033,55034,55035,55038,55039,55041,55042,55043,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55058,55059,55060,52824,52825,52828,52831,52832,52833,52840,52841,52843,52845,52852,52853,52856,52860,52868,52869,52871,52873,52880,52881,52884,52888,52896,52897,52899,52900,52901,52908,52909,52929,52964,52965,52968,52971,52972,52980,52981,52983,52984,52985,52992,52993,52996,53e3,53008,53009,53011,53013,53020,53024,53028,53036,53037,53039,53040,53041,53048,53076,53077,53080,53084,53092,53093,53095,53097,53104,53105,53108,53112,53120,53125,53132,53153,53160,53168,53188,53216,53217,53220,53224,53232,53233,53235,53237,53244,53248,53252,53265,53272,53293,53300,53301,53304,53308,55061,55062,55063,55066,55067,55069,55070,55071,55073,55074,55075,55076,55077,55078,55079,55082,55084,55086,55087,55088,55089,55090,55091,55094,55095,55097,null,null,null,null,null,null,55098,55099,55101,55102,55103,55104,55105,55106,55107,55109,55110,55112,55114,55115,55116,55117,55118,55119,55122,55123,55125,55130,55131,55132,55133,55134,null,null,null,null,null,null,55135,55138,55140,55142,55143,55144,55146,55147,55149,55150,55151,55153,55154,55155,55157,55158,55159,55160,55161,55162,55163,55166,55167,55168,55170,55171,55172,55173,55174,55175,55178,55179,53316,53317,53319,53321,53328,53332,53336,53344,53356,53357,53360,53364,53372,53373,53377,53412,53413,53416,53420,53428,53429,53431,53433,53440,53441,53444,53448,53449,53456,53457,53459,53460,53461,53468,53469,53472,53476,53484,53485,53487,53488,53489,53496,53517,53552,53553,53556,53560,53562,53568,53569,53571,53572,53573,53580,53581,53584,53588,53596,53597,53599,53601,53608,53612,53628,53636,53640,53664,53665,53668,53672,53680,53681,53683,53685,53690,53692,53696,53720,53748,53752,53767,53769,53776,53804,53805,53808,53812,53820,53821,53823,53825,53832,53852,55181,55182,55183,55185,55186,55187,55188,55189,55190,55191,55194,55196,55198,55199,55200,55201,55202,55203,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,53860,53888,53889,53892,53896,53904,53905,53909,53916,53920,53924,53932,53937,53944,53945,53948,53951,53952,53954,53960,53961,53963,53972,53976,53980,53988,53989,54e3,54001,54004,54008,54016,54017,54019,54021,54028,54029,54030,54032,54036,54038,54044,54045,54047,54048,54049,54053,54056,54057,54060,54064,54072,54073,54075,54076,54077,54084,54085,54140,54141,54144,54148,54156,54157,54159,54160,54161,54168,54169,54172,54176,54184,54185,54187,54189,54196,54200,54204,54212,54213,54216,54217,54224,54232,54241,54243,54252,54253,54256,54260,54268,54269,54271,54273,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54280,54301,54336,54340,54364,54368,54372,54381,54383,54392,54393,54396,54399,54400,54402,54408,54409,54411,54413,54420,54441,54476,54480,54484,54492,54495,54504,54508,54512,54520,54523,54525,54532,54536,54540,54548,54549,54551,54588,54589,54592,54596,54604,54605,54607,54609,54616,54617,54620,54624,54629,54632,54633,54635,54637,54644,54645,54648,54652,54660,54661,54663,54664,54665,54672,54693,54728,54729,54732,54736,54738,54744,54745,54747,54749,54756,54757,54760,54764,54772,54773,54775,54777,54784,54785,54788,54792,54800,54801,54803,54804,54805,54812,54816,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,54820,54829,54840,54841,54844,54848,54853,54856,54857,54859,54861,54865,54868,54869,54872,54876,54887,54889,54896,54897,54900,54915,54917,54924,54925,54928,54932,54941,54943,54945,54952,54956,54960,54969,54971,54980,54981,54984,54988,54993,54996,54999,55001,55008,55012,55016,55024,55029,55036,55037,55040,55044,55057,55064,55065,55068,55072,55080,55081,55083,55085,55092,55093,55096,55100,55108,55111,55113,55120,55121,55124,55126,55127,55128,55129,55136,55137,55139,55141,55145,55148,55152,55156,55164,55165,55169,55176,55177,55180,55184,55192,55193,55195,55197,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20285,20339,20551,20729,21152,21487,21621,21733,22025,23233,23478,26247,26550,26551,26607,27468,29634,30146,31292,33499,33540,34903,34952,35382,36040,36303,36603,36838,39381,21051,21364,21508,24682,24932,27580,29647,33050,35258,35282,38307,20355,21002,22718,22904,23014,24178,24185,25031,25536,26438,26604,26751,28567,30286,30475,30965,31240,31487,31777,32925,33390,33393,35563,38291,20075,21917,26359,28212,30883,31469,33883,35088,34638,38824,21208,22350,22570,23884,24863,25022,25121,25954,26577,27204,28187,29976,30131,30435,30640,32058,37039,37969,37970,40853,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21283,23724,30002,32987,37440,38296,21083,22536,23004,23713,23831,24247,24378,24394,24951,27743,30074,30086,31968,32115,32177,32652,33108,33313,34193,35137,35611,37628,38477,40007,20171,20215,20491,20977,22607,24887,24894,24936,25913,27114,28433,30117,30342,30422,31623,33445,33995,63744,37799,38283,21888,23458,22353,63745,31923,32697,37301,20520,21435,23621,24040,25298,25454,25818,25831,28192,28844,31067,36317,36382,63746,36989,37445,37624,20094,20214,20581,24062,24314,24838,26967,33137,34388,36423,37749,39467,20062,20625,26480,26688,20745,21133,21138,27298,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30652,37392,40660,21163,24623,36850,20552,25001,25581,25802,26684,27268,28608,33160,35233,38548,22533,29309,29356,29956,32121,32365,32937,35211,35700,36963,40273,25225,27770,28500,32080,32570,35363,20860,24906,31645,35609,37463,37772,20140,20435,20510,20670,20742,21185,21197,21375,22384,22659,24218,24465,24950,25004,25806,25964,26223,26299,26356,26775,28039,28805,28913,29855,29861,29898,30169,30828,30956,31455,31478,32069,32147,32789,32831,33051,33686,35686,36629,36885,37857,38915,38968,39514,39912,20418,21843,22586,22865,23395,23622,24760,25106,26690,26800,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26856,28330,30028,30328,30926,31293,31995,32363,32380,35336,35489,35903,38542,40388,21476,21481,21578,21617,22266,22993,23396,23611,24235,25335,25911,25925,25970,26272,26543,27073,27837,30204,30352,30590,31295,32660,32771,32929,33167,33510,33533,33776,34241,34865,34996,35493,63747,36764,37678,38599,39015,39640,40723,21741,26011,26354,26767,31296,35895,40288,22256,22372,23825,26118,26801,26829,28414,29736,34974,39908,27752,63748,39592,20379,20844,20849,21151,23380,24037,24656,24685,25329,25511,25915,29657,31354,34467,36002,38799,20018,23521,25096,26524,29916,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31185,33747,35463,35506,36328,36942,37707,38982,24275,27112,34303,37101,63749,20896,23448,23532,24931,26874,27454,28748,29743,29912,31649,32592,33733,35264,36011,38364,39208,21038,24669,25324,36866,20362,20809,21281,22745,24291,26336,27960,28826,29378,29654,31568,33009,37979,21350,25499,32619,20054,20608,22602,22750,24618,24871,25296,27088,39745,23439,32024,32945,36703,20132,20689,21676,21932,23308,23968,24039,25898,25934,26657,27211,29409,30350,30703,32094,32761,33184,34126,34527,36611,36686,37066,39171,39509,39851,19992,20037,20061,20167,20465,20855,21246,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21312,21475,21477,21646,22036,22389,22434,23495,23943,24272,25084,25304,25937,26552,26601,27083,27472,27590,27628,27714,28317,28792,29399,29590,29699,30655,30697,31350,32127,32777,33276,33285,33290,33503,34914,35635,36092,36544,36881,37041,37476,37558,39378,39493,40169,40407,40860,22283,23616,33738,38816,38827,40628,21531,31384,32676,35033,36557,37089,22528,23624,25496,31391,23470,24339,31353,31406,33422,36524,20518,21048,21240,21367,22280,25331,25458,27402,28099,30519,21413,29527,34152,36470,38357,26426,27331,28528,35437,36556,39243,63750,26231,27512,36020,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,39740,63751,21483,22317,22862,25542,27131,29674,30789,31418,31429,31998,33909,35215,36211,36917,38312,21243,22343,30023,31584,33740,37406,63752,27224,20811,21067,21127,25119,26840,26997,38553,20677,21156,21220,25027,26020,26681,27135,29822,31563,33465,33771,35250,35641,36817,39241,63753,20170,22935,25810,26129,27278,29748,31105,31165,33449,34942,34943,35167,63754,37670,20235,21450,24613,25201,27762,32026,32102,20120,20834,30684,32943,20225,20238,20854,20864,21980,22120,22331,22522,22524,22804,22855,22931,23492,23696,23822,24049,24190,24524,25216,26071,26083,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26398,26399,26462,26827,26820,27231,27450,27683,27773,27778,28103,29592,29734,29738,29826,29859,30072,30079,30849,30959,31041,31047,31048,31098,31637,32e3,32186,32648,32774,32813,32908,35352,35663,35912,36215,37665,37668,39138,39249,39438,39439,39525,40594,32202,20342,21513,25326,26708,37329,21931,20794,63755,63756,23068,25062,63757,25295,25343,63758,63759,63760,63761,63762,63763,37027,63764,63765,63766,63767,63768,35582,63769,63770,63771,63772,26262,63773,29014,63774,63775,38627,63776,25423,25466,21335,63777,26511,26976,28275,63778,30007,63779,63780,63781,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32013,63782,63783,34930,22218,23064,63784,63785,63786,63787,63788,20035,63789,20839,22856,26608,32784,63790,22899,24180,25754,31178,24565,24684,25288,25467,23527,23511,21162,63791,22900,24361,24594,63792,63793,63794,29785,63795,63796,63797,63798,63799,63800,39377,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,28611,63812,63813,33215,36786,24817,63814,63815,33126,63816,63817,23615,63818,63819,63820,63821,63822,63823,63824,63825,23273,35365,26491,32016,63826,63827,63828,63829,63830,63831,33021,63832,63833,23612,27877,21311,28346,22810,33590,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20025,20150,20294,21934,22296,22727,24406,26039,26086,27264,27573,28237,30701,31471,31774,32222,34507,34962,37170,37723,25787,28606,29562,30136,36948,21846,22349,25018,25812,26311,28129,28251,28525,28601,30192,32835,33213,34113,35203,35527,35674,37663,27795,30035,31572,36367,36957,21776,22530,22616,24162,25095,25758,26848,30070,31958,34739,40680,20195,22408,22382,22823,23565,23729,24118,24453,25140,25825,29619,33274,34955,36024,38538,40667,23429,24503,24755,20498,20992,21040,22294,22581,22615,23566,23648,23798,23947,24230,24466,24764,25361,25481,25623,26691,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26873,27330,28120,28193,28372,28644,29182,30428,30585,31153,31291,33796,35241,36077,36339,36424,36867,36884,36947,37117,37709,38518,38876,27602,28678,29272,29346,29544,30563,31167,31716,32411,35712,22697,24775,25958,26109,26302,27788,28958,29129,35930,38931,20077,31361,20189,20908,20941,21205,21516,24999,26481,26704,26847,27934,28540,30140,30643,31461,33012,33891,37509,20828,26007,26460,26515,30168,31431,33651,63834,35910,36887,38957,23663,33216,33434,36929,36975,37389,24471,23965,27225,29128,30331,31561,34276,35588,37159,39472,21895,25078,63835,30313,32645,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34367,34746,35064,37007,63836,27931,28889,29662,32097,33853,63837,37226,39409,63838,20098,21365,27396,27410,28734,29211,34349,40478,21068,36771,23888,25829,25900,27414,28651,31811,32412,34253,35172,35261,25289,33240,34847,24266,26391,28010,29436,29701,29807,34690,37086,20358,23821,24480,33802,20919,25504,30053,20142,20486,20841,20937,26753,27153,31918,31921,31975,33391,35538,36635,37327,20406,20791,21237,21570,24300,24942,25150,26053,27354,28670,31018,34268,34851,38317,39522,39530,40599,40654,21147,26310,27511,28701,31019,36706,38722,24976,25088,25891,28451,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29001,29833,32244,32879,34030,36646,36899,37706,20925,21015,21155,27916,28872,35010,24265,25986,27566,28610,31806,29557,20196,20278,22265,63839,23738,23994,24604,29618,31533,32666,32718,32838,36894,37428,38646,38728,38936,40801,20363,28583,31150,37300,38583,21214,63840,25736,25796,27347,28510,28696,29200,30439,32769,34310,34396,36335,36613,38706,39791,40442,40565,30860,31103,32160,33737,37636,40575,40595,35542,22751,24324,26407,28711,29903,31840,32894,20769,28712,29282,30922,36034,36058,36084,38647,20102,20698,23534,24278,26009,29134,30274,30637,32842,34044,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36988,39719,40845,22744,23105,23650,27155,28122,28431,30267,32047,32311,34078,35128,37860,38475,21129,26066,26611,27060,27969,28316,28687,29705,29792,30041,30244,30827,35628,39006,20845,25134,38520,20374,20523,23833,28138,32184,36650,24459,24900,26647,63841,38534,21202,32907,20956,20940,26974,31260,32190,33777,38517,20442,21033,21400,21519,21774,23653,24743,26446,26792,28012,29313,29432,29702,29827,63842,30178,31852,32633,32696,33673,35023,35041,37324,37328,38626,39881,21533,28542,29136,29848,34298,36522,38563,40023,40607,26519,28107,29747,33256,38678,30764,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31435,31520,31890,25705,29802,30194,30908,30952,39340,39764,40635,23518,24149,28448,33180,33707,37e3,19975,21325,23081,24018,24398,24930,25405,26217,26364,28415,28459,28771,30622,33836,34067,34875,36627,39237,39995,21788,25273,26411,27819,33545,35178,38778,20129,22916,24536,24537,26395,32178,32596,33426,33579,33725,36638,37017,22475,22969,23186,23504,26151,26522,26757,27599,29028,32629,36023,36067,36993,39749,33032,35978,38476,39488,40613,23391,27667,29467,30450,30431,33804,20906,35219,20813,20885,21193,26825,27796,30468,30496,32191,32236,38754,40629,28357,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,34065,20901,21517,21629,26126,26269,26919,28319,30399,30609,33559,33986,34719,37225,37528,40180,34946,20398,20882,21215,22982,24125,24917,25720,25721,26286,26576,27169,27597,27611,29279,29281,29761,30520,30683,32791,33468,33541,35584,35624,35980,26408,27792,29287,30446,30566,31302,40361,27519,27794,22818,26406,33945,21359,22675,22937,24287,25551,26164,26483,28218,29483,31447,33495,37672,21209,24043,25006,25035,25098,25287,25771,26080,26969,27494,27595,28961,29687,30045,32326,33310,33538,34154,35491,36031,38695,40289,22696,40664,20497,21006,21563,21839,25991,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27766,32010,32011,32862,34442,38272,38639,21247,27797,29289,21619,23194,23614,23883,24396,24494,26410,26806,26979,28220,28228,30473,31859,32654,34183,35598,36855,38753,40692,23735,24758,24845,25003,25935,26107,26108,27665,27887,29599,29641,32225,38292,23494,34588,35600,21085,21338,25293,25615,25778,26420,27192,27850,29632,29854,31636,31893,32283,33162,33334,34180,36843,38649,39361,20276,21322,21453,21467,25292,25644,25856,26001,27075,27886,28504,29677,30036,30242,30436,30460,30928,30971,31020,32070,33324,34784,36820,38930,39151,21187,25300,25765,28196,28497,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30332,36299,37297,37474,39662,39747,20515,20621,22346,22952,23592,24135,24439,25151,25918,26041,26049,26121,26507,27036,28354,30917,32033,32938,33152,33323,33459,33953,34444,35370,35607,37030,38450,40848,20493,20467,63843,22521,24472,25308,25490,26479,28227,28953,30403,32972,32986,35060,35061,35097,36064,36649,37197,38506,20271,20336,24091,26575,26658,30333,30334,39748,24161,27146,29033,29140,30058,63844,32321,34115,34281,39132,20240,31567,32624,38309,20961,24070,26805,27710,27726,27867,29359,31684,33539,27861,29754,20731,21128,22721,25816,27287,29863,30294,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,30887,34327,38370,38713,63845,21342,24321,35722,36776,36783,37002,21029,30629,40009,40712,19993,20482,20853,23643,24183,26142,26170,26564,26821,28851,29953,30149,31177,31453,36647,39200,39432,20445,22561,22577,23542,26222,27493,27921,28282,28541,29668,29995,33769,35036,35091,35676,36628,20239,20693,21264,21340,23443,24489,26381,31119,33145,33583,34068,35079,35206,36665,36667,39333,39954,26412,20086,20472,22857,23553,23791,23792,25447,26834,28925,29090,29739,32299,34028,34562,36898,37586,40179,19981,20184,20463,20613,21078,21103,21542,21648,22496,22827,23142,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23386,23413,23500,24220,63846,25206,25975,26023,28014,28325,29238,31526,31807,32566,33104,33105,33178,33344,33433,33705,35331,36e3,36070,36091,36212,36282,37096,37340,38428,38468,39385,40167,21271,20998,21545,22132,22707,22868,22894,24575,24996,25198,26128,27774,28954,30406,31881,31966,32027,33452,36033,38640,63847,20315,24343,24447,25282,23849,26379,26842,30844,32323,40300,19989,20633,21269,21290,21329,22915,23138,24199,24754,24970,25161,25209,26e3,26503,27047,27604,27606,27607,27608,27832,63848,29749,30202,30738,30865,31189,31192,31875,32203,32737,32933,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,33086,33218,33778,34586,35048,35513,35692,36027,37145,38750,39131,40763,22188,23338,24428,25996,27315,27567,27996,28657,28693,29277,29613,36007,36051,38971,24977,27703,32856,39425,20045,20107,20123,20181,20282,20284,20351,20447,20735,21490,21496,21766,21987,22235,22763,22882,23057,23531,23546,23556,24051,24107,24473,24605,25448,26012,26031,26614,26619,26797,27515,27801,27863,28195,28681,29509,30722,31038,31040,31072,31169,31721,32023,32114,32902,33293,33678,34001,34503,35039,35408,35422,35613,36060,36198,36781,37034,39164,39391,40605,21066,63849,26388,63850,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20632,21034,23665,25955,27733,29642,29987,30109,31639,33948,37240,38704,20087,25746,27578,29022,34217,19977,63851,26441,26862,28183,33439,34072,34923,25591,28545,37394,39087,19978,20663,20687,20767,21830,21930,22039,23360,23577,23776,24120,24202,24224,24258,24819,26705,27233,28248,29245,29248,29376,30456,31077,31665,32724,35059,35316,35443,35937,36062,38684,22622,29885,36093,21959,63852,31329,32034,33394,29298,29983,29989,63853,31513,22661,22779,23996,24207,24246,24464,24661,25234,25471,25933,26257,26329,26360,26646,26866,29312,29790,31598,32110,32214,32626,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32997,33298,34223,35199,35475,36893,37604,40653,40736,22805,22893,24109,24796,26132,26227,26512,27728,28101,28511,30707,30889,33990,37323,37675,20185,20682,20808,21892,23307,23459,25159,25982,26059,28210,29053,29697,29764,29831,29887,30316,31146,32218,32341,32680,33146,33203,33337,34330,34796,35445,36323,36984,37521,37925,39245,39854,21352,23633,26964,27844,27945,28203,33292,34203,35131,35373,35498,38634,40807,21089,26297,27570,32406,34814,36109,38275,38493,25885,28041,29166,63854,22478,22995,23468,24615,24826,25104,26143,26207,29481,29689,30427,30465,31596,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32854,32882,33125,35488,37266,19990,21218,27506,27927,31237,31545,32048,63855,36016,21484,22063,22609,23477,23567,23569,24034,25152,25475,25620,26157,26803,27836,28040,28335,28703,28836,29138,29990,30095,30094,30233,31505,31712,31787,32032,32057,34092,34157,34311,35380,36877,36961,37045,37559,38902,39479,20439,23660,26463,28049,31903,32396,35606,36118,36895,23403,24061,25613,33984,36956,39137,29575,23435,24730,26494,28126,35359,35494,36865,38924,21047,63856,28753,30862,37782,34928,37335,20462,21463,22013,22234,22402,22781,23234,23432,23723,23744,24101,24833,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,25101,25163,25480,25628,25910,25976,27193,27530,27700,27929,28465,29159,29417,29560,29703,29874,30246,30561,31168,31319,31466,31929,32143,32172,32353,32670,33065,33585,33936,34010,34282,34966,35504,35728,36664,36930,36995,37228,37526,37561,38539,38567,38568,38614,38656,38920,39318,39635,39706,21460,22654,22809,23408,23487,28113,28506,29087,29729,29881,32901,33789,24033,24455,24490,24642,26092,26642,26991,27219,27529,27957,28147,29667,30462,30636,31565,32020,33059,33308,33600,34036,34147,35426,35524,37255,37662,38918,39348,25100,34899,36848,37477,23815,23847,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,23913,29791,33181,34664,28629,25342,32722,35126,35186,19998,20056,20711,21213,21319,25215,26119,32361,34821,38494,20365,21273,22070,22987,23204,23608,23630,23629,24066,24337,24643,26045,26159,26178,26558,26612,29468,30690,31034,32709,33940,33997,35222,35430,35433,35553,35925,35962,22516,23508,24335,24687,25325,26893,27542,28252,29060,31698,34645,35672,36606,39135,39166,20280,20353,20449,21627,23072,23480,24892,26032,26216,29180,30003,31070,32051,33102,33251,33688,34218,34254,34563,35338,36523,36763,63857,36805,22833,23460,23526,24713,23529,23563,24515,27777,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63858,28145,28683,29978,33455,35574,20160,21313,63859,38617,27663,20126,20420,20818,21854,23077,23784,25105,29273,33469,33706,34558,34905,35357,38463,38597,39187,40201,40285,22538,23731,23997,24132,24801,24853,25569,27138,28197,37122,37716,38990,39952,40823,23433,23736,25353,26191,26696,30524,38593,38797,38996,39839,26017,35585,36555,38332,21813,23721,24022,24245,26263,30284,33780,38343,22739,25276,29390,40232,20208,22830,24591,26171,27523,31207,40230,21395,21696,22467,23830,24859,26326,28079,30861,33406,38552,38724,21380,25212,25494,28082,32266,33099,38989,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,27387,32588,40367,40474,20063,20539,20918,22812,24825,25590,26928,29242,32822,63860,37326,24369,63861,63862,32004,33509,33903,33979,34277,36493,63863,20335,63864,63865,22756,23363,24665,25562,25880,25965,26264,63866,26954,27171,27915,28673,29036,30162,30221,31155,31344,63867,32650,63868,35140,63869,35731,37312,38525,63870,39178,22276,24481,26044,28417,30208,31142,35486,39341,39770,40812,20740,25014,25233,27277,33222,20547,22576,24422,28937,35328,35578,23420,34326,20474,20796,22196,22852,25513,28153,23978,26989,20870,20104,20313,63871,63872,63873,22914,63874,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63875,27487,27741,63876,29877,30998,63877,33287,33349,33593,36671,36701,63878,39192,63879,63880,63881,20134,63882,22495,24441,26131,63883,63884,30123,32377,35695,63885,36870,39515,22181,22567,23032,23071,23476,63886,24310,63887,63888,25424,25403,63889,26941,27783,27839,28046,28051,28149,28436,63890,28895,28982,29017,63891,29123,29141,63892,30799,30831,63893,31605,32227,63894,32303,63895,34893,36575,63896,63897,63898,37467,63899,40182,63900,63901,63902,24709,28037,63903,29105,63904,63905,38321,21421,63906,63907,63908,26579,63909,28814,28976,29744,33398,33490,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63910,38331,39653,40573,26308,63911,29121,33865,63912,63913,22603,63914,63915,23992,24433,63916,26144,26254,27001,27054,27704,27891,28214,28481,28634,28699,28719,29008,29151,29552,63917,29787,63918,29908,30408,31310,32403,63919,63920,33521,35424,36814,63921,37704,63922,38681,63923,63924,20034,20522,63925,21e3,21473,26355,27757,28618,29450,30591,31330,33454,34269,34306,63926,35028,35427,35709,35947,63927,37555,63928,38675,38928,20116,20237,20425,20658,21320,21566,21555,21978,22626,22714,22887,23067,23524,24735,63929,25034,25942,26111,26212,26791,27738,28595,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28879,29100,29522,31613,34568,35492,39986,40711,23627,27779,29508,29577,37434,28331,29797,30239,31337,32277,34314,20800,22725,25793,29934,29973,30320,32705,37013,38605,39252,28198,29926,31401,31402,33253,34521,34680,35355,23113,23436,23451,26785,26880,28003,29609,29715,29740,30871,32233,32747,33048,33109,33694,35916,38446,38929,26352,24448,26106,26505,27754,29579,20525,23043,27498,30702,22806,23916,24013,29477,30031,63930,63931,20709,20985,22575,22829,22934,23002,23525,63932,63933,23970,25303,25622,25747,25854,63934,26332,63935,27208,63936,29183,29796,63937,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31368,31407,32327,32350,32768,33136,63938,34799,35201,35616,36953,63939,36992,39250,24958,27442,28020,32287,35109,36785,20433,20653,20887,21191,22471,22665,23481,24248,24898,27029,28044,28263,28342,29076,29794,29992,29996,32883,33592,33993,36362,37780,37854,63940,20110,20305,20598,20778,21448,21451,21491,23431,23507,23588,24858,24962,26100,29275,29591,29760,30402,31056,31121,31161,32006,32701,33419,34261,34398,36802,36935,37109,37354,38533,38632,38633,21206,24423,26093,26161,26671,29020,31286,37057,38922,20113,63941,27218,27550,28560,29065,32792,33464,34131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36939,38549,38642,38907,34074,39729,20112,29066,38596,20803,21407,21729,22291,22290,22435,23195,23236,23491,24616,24895,25588,27781,27961,28274,28304,29232,29503,29783,33489,34945,36677,36960,63942,38498,39e3,40219,26376,36234,37470,20301,20553,20702,21361,22285,22996,23041,23561,24944,26256,28205,29234,29771,32239,32963,33806,33894,34111,34655,34907,35096,35586,36949,38859,39759,20083,20369,20754,20842,63943,21807,21929,23418,23461,24188,24189,24254,24736,24799,24840,24841,25540,25912,26377,63944,26580,26586,63945,26977,26978,27833,27943,63946,28216,63947,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,28641,29494,29495,63948,29788,30001,63949,30290,63950,63951,32173,33278,33848,35029,35480,35547,35565,36400,36418,36938,36926,36986,37193,37321,37742,63952,63953,22537,63954,27603,32905,32946,63955,63956,20801,22891,23609,63957,63958,28516,29607,32996,36103,63959,37399,38287,63960,63961,63962,63963,32895,25102,28700,32104,34701,63964,22432,24681,24903,27575,35518,37504,38577,20057,21535,28139,34093,38512,38899,39150,25558,27875,37009,20957,25033,33210,40441,20381,20506,20736,23452,24847,25087,25836,26885,27589,30097,30691,32681,33380,34191,34811,34915,35516,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,35696,37291,20108,20197,20234,63965,63966,22839,23016,63967,24050,24347,24411,24609,63968,63969,63970,63971,29246,29669,63972,30064,30157,63973,31227,63974,32780,32819,32900,33505,33617,63975,63976,36029,36019,36999,63977,63978,39156,39180,63979,63980,28727,30410,32714,32716,32764,35610,20154,20161,20995,21360,63981,21693,22240,23035,23493,24341,24525,28270,63982,63983,32106,33589,63984,34451,35469,63985,38765,38775,63986,63987,19968,20314,20350,22777,26085,28322,36920,37808,39353,20219,22764,22922,23001,24641,63988,63989,31252,63990,33615,36035,20837,21316,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,63991,63992,63993,20173,21097,23381,33471,20180,21050,21672,22985,23039,23376,23383,23388,24675,24904,28363,28825,29038,29574,29943,30133,30913,32043,32773,33258,33576,34071,34249,35566,36039,38604,20316,21242,22204,26027,26152,28796,28856,29237,32189,33421,37196,38592,40306,23409,26855,27544,28538,30430,23697,26283,28507,31668,31786,34870,38620,19976,20183,21280,22580,22715,22767,22892,23559,24115,24196,24373,25484,26290,26454,27167,27299,27404,28479,29254,63994,29520,29835,31456,31911,33144,33247,33255,33674,33900,34083,34196,34255,35037,36115,37292,38263,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38556,20877,21705,22312,23472,25165,26448,26685,26771,28221,28371,28797,32289,35009,36001,36617,40779,40782,29229,31631,35533,37658,20295,20302,20786,21632,22992,24213,25269,26485,26990,27159,27822,28186,29401,29482,30141,31672,32053,33511,33785,33879,34295,35419,36015,36487,36889,37048,38606,40799,21219,21514,23265,23490,25688,25973,28404,29380,63995,30340,31309,31515,31821,32318,32735,33659,35627,36042,36196,36321,36447,36842,36857,36969,37841,20291,20346,20659,20840,20856,21069,21098,22625,22652,22880,23560,23637,24283,24731,25136,26643,27583,27656,28593,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29006,29728,3e4,30008,30033,30322,31564,31627,31661,31686,32399,35438,36670,36681,37439,37523,37666,37931,38651,39002,39019,39198,20999,25130,25240,27993,30308,31434,31680,32118,21344,23742,24215,28472,28857,31896,38673,39822,40670,25509,25722,34678,19969,20117,20141,20572,20597,21576,22979,23450,24128,24237,24311,24449,24773,25402,25919,25972,26060,26230,26232,26622,26984,27273,27491,27712,28096,28136,28191,28254,28702,28833,29582,29693,30010,30555,30855,31118,31243,31357,31934,32142,33351,35330,35562,35998,37165,37194,37336,37478,37580,37664,38662,38742,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38748,38914,40718,21046,21137,21884,22564,24093,24351,24716,25552,26799,28639,31085,31532,33229,34234,35069,35576,36420,37261,38500,38555,38717,38988,40778,20430,20806,20939,21161,22066,24340,24427,25514,25805,26089,26177,26362,26361,26397,26781,26839,27133,28437,28526,29031,29157,29226,29866,30522,31062,31066,31199,31264,31381,31895,31967,32068,32368,32903,34299,34468,35412,35519,36249,36481,36896,36973,37347,38459,38613,40165,26063,31751,36275,37827,23384,23562,21330,25305,29469,20519,23447,24478,24752,24939,26837,28121,29742,31278,32066,32156,32305,33131,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36394,36405,37758,37912,20304,22352,24038,24231,25387,32618,20027,20303,20367,20570,23005,32964,21610,21608,22014,22863,23449,24030,24282,26205,26417,26609,26666,27880,27954,28234,28557,28855,29664,30087,31820,32002,32044,32162,33311,34523,35387,35461,36208,36490,36659,36913,37198,37202,37956,39376,31481,31909,20426,20737,20934,22472,23535,23803,26201,27197,27994,28310,28652,28940,30063,31459,34850,36897,36981,38603,39423,33537,20013,20210,34886,37325,21373,27355,26987,27713,33914,22686,24974,26366,25327,28893,29969,30151,32338,33976,35657,36104,20043,21482,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21675,22320,22336,24535,25345,25351,25711,25903,26088,26234,26525,26547,27490,27744,27802,28460,30693,30757,31049,31063,32025,32930,33026,33267,33437,33463,34584,35468,63996,36100,36286,36978,30452,31257,31287,32340,32887,21767,21972,22645,25391,25634,26185,26187,26733,27035,27524,27941,28337,29645,29800,29857,30043,30137,30433,30494,30603,31206,32265,32285,33275,34095,34967,35386,36049,36587,36784,36914,37805,38499,38515,38663,20356,21489,23018,23241,24089,26702,29894,30142,31209,31378,33187,34541,36074,36300,36845,26015,26389,63997,22519,28503,32221,36655,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37878,38598,24501,25074,28548,19988,20376,20511,21449,21983,23919,24046,27425,27492,30923,31642,63998,36425,36554,36974,25417,25662,30528,31364,37679,38015,40810,25776,28591,29158,29864,29914,31428,31762,32386,31922,32408,35738,36106,38013,39184,39244,21049,23519,25830,26413,32046,20717,21443,22649,24920,24921,25082,26028,31449,35730,35734,20489,20513,21109,21809,23100,24288,24432,24884,25950,26124,26166,26274,27085,28356,28466,29462,30241,31379,33081,33369,33750,33980,20661,22512,23488,23528,24425,25505,30758,32181,33756,34081,37319,37365,20874,26613,31574,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36012,20932,22971,24765,34389,20508,63999,21076,23610,24957,25114,25299,25842,26021,28364,30240,33034,36448,38495,38587,20191,21315,21912,22825,24029,25797,27849,28154,29588,31359,33307,34214,36068,36368,36983,37351,38369,38433,38854,20984,21746,21894,24505,25764,28552,32180,36639,36685,37941,20681,23574,27838,28155,29979,30651,31805,31844,35449,35522,22558,22974,24086,25463,29266,30090,30571,35548,36028,36626,24307,26228,28152,32893,33729,35531,38737,39894,64e3,21059,26367,28053,28399,32224,35558,36910,36958,39636,21021,21119,21736,24980,25220,25307,26786,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,26898,26970,27189,28818,28966,30813,30977,30990,31186,31245,32918,33400,33493,33609,34121,35970,36229,37218,37259,37294,20419,22225,29165,30679,34560,35320,23544,24534,26449,37032,21474,22618,23541,24740,24961,25696,32317,32880,34085,37507,25774,20652,23828,26368,22684,25277,25512,26894,27e3,27166,28267,30394,31179,33467,33833,35535,36264,36861,37138,37195,37276,37648,37656,37786,38619,39478,39949,19985,30044,31069,31482,31569,31689,32302,33988,36441,36468,36600,36880,26149,26943,29763,20986,26414,40668,20805,24544,27798,34802,34909,34935,24756,33205,33795,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,36101,21462,21561,22068,23094,23601,28810,32736,32858,33030,33261,36259,37257,39519,40434,20596,20164,21408,24827,28204,23652,20360,20516,21988,23769,24159,24677,26772,27835,28100,29118,30164,30196,30305,31258,31305,32199,32251,32622,33268,34473,36636,38601,39347,40786,21063,21189,39149,35242,19971,26578,28422,20405,23522,26517,27784,28024,29723,30759,37341,37756,34756,31204,31281,24555,20182,21668,21822,22702,22949,24816,25171,25302,26422,26965,33333,38464,39345,39389,20524,21331,21828,22396,64001,25176,64002,25826,26219,26589,28609,28655,29730,29752,35351,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,37944,21585,22022,22374,24392,24986,27470,28760,28845,32187,35477,22890,33067,25506,30472,32829,36010,22612,25645,27067,23445,24081,28271,64003,34153,20812,21488,22826,24608,24907,27526,27760,27888,31518,32974,33492,36294,37040,39089,64004,25799,28580,25745,25860,20814,21520,22303,35342,24927,26742,64005,30171,31570,32113,36890,22534,27084,33151,35114,36864,38969,20600,22871,22956,25237,36879,39722,24925,29305,38358,22369,23110,24052,25226,25773,25850,26487,27874,27966,29228,29750,30772,32631,33453,36315,38935,21028,22338,26495,29256,29923,36009,36774,37393,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,38442,20843,21485,25420,20329,21764,24726,25943,27803,28031,29260,29437,31255,35207,35997,24429,28558,28921,33192,24846,20415,20559,25153,29255,31687,32232,32745,36941,38829,39449,36022,22378,24179,26544,33805,35413,21536,23318,24163,24290,24330,25987,32954,34109,38281,38491,20296,21253,21261,21263,21638,21754,22275,24067,24598,25243,25265,25429,64006,27873,28006,30129,30770,32990,33071,33502,33889,33970,34957,35090,36875,37610,39165,39825,24133,26292,26333,28689,29190,64007,20469,21117,24426,24915,26451,27161,28418,29922,31080,34920,35961,39111,39108,39491,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,21697,31263,26963,35575,35914,39080,39342,24444,25259,30130,30382,34987,36991,38466,21305,24380,24517,27852,29644,30050,30091,31558,33534,39325,20047,36924,19979,20309,21414,22799,24264,26160,27827,29781,33655,34662,36032,36944,38686,39957,22737,23416,34384,35604,40372,23506,24680,24717,26097,27735,28450,28579,28698,32597,32752,38289,38290,38480,38867,21106,36676,20989,21547,21688,21859,21898,27323,28085,32216,33382,37532,38519,40569,21512,21704,30418,34532,38308,38356,38492,20130,20233,23022,23270,24055,24658,25239,26477,26689,27782,28207,32568,32923,33322,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,64008,64009,38917,20133,20565,21683,22419,22874,23401,23475,25032,26999,28023,28707,34809,35299,35442,35559,36994,39405,39608,21182,26680,20502,24184,26447,33607,34892,20139,21521,22190,29670,37141,38911,39177,39255,39321,22099,22687,34395,35377,25010,27382,29563,36562,27463,38570,39511,22869,29184,36203,38761,20436,23796,24358,25080,26203,27883,28843,29572,29625,29694,30505,30541,32067,32098,32291,33335,34898,64010,36066,37449,39023,23377,31348,34880,38913,23244,20448,21332,22846,23805,25406,28025,29433,33029,33031,33698,37583,38960,20136,20804,21009,22411,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24418,27842,28366,28677,28752,28847,29074,29673,29801,33610,34722,34913,36872,37026,37795,39336,20846,24407,24800,24935,26291,34137,36426,37295,38795,20046,20114,21628,22741,22778,22909,23733,24359,25142,25160,26122,26215,27627,28009,28111,28246,28408,28564,28640,28649,28765,29392,29733,29786,29920,30355,31068,31946,32286,32993,33446,33899,33983,34382,34399,34676,35703,35946,37804,38912,39013,24785,25110,37239,23130,26127,28151,28222,29759,39746,24573,24794,31503,21700,24344,27742,27859,27946,28888,32005,34425,35340,40251,21270,21644,23301,27194,28779,30069,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,31117,31166,33457,33775,35441,35649,36008,38772,64011,25844,25899,30906,30907,31339,20024,21914,22864,23462,24187,24739,25563,27489,26213,26707,28185,29029,29872,32008,36996,39529,39973,27963,28369,29502,35905,38346,20976,24140,24488,24653,24822,24880,24908,26179,26180,27045,27841,28255,28361,28514,29004,29852,30343,31681,31783,33618,34647,36945,38541,40643,21295,22238,24315,24458,24674,24724,25079,26214,26371,27292,28142,28590,28784,29546,32362,33214,33588,34516,35496,36036,21123,29554,23446,27243,37892,21742,22150,23389,25928,25989,26313,26783,28045,28102,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,29243,32948,37237,39501,20399,20505,21402,21518,21564,21897,21957,24127,24460,26429,29030,29661,36869,21211,21235,22628,22734,28932,29071,29179,34224,35347,26248,34216,21927,26244,29002,33841,21321,21913,27585,24409,24509,25582,26249,28999,35569,36637,40638,20241,25658,28875,30054,34407,24676,35662,40440,20807,20982,21256,27958,33016,40657,26133,27427,28824,30165,21507,23673,32007,35350,27424,27453,27462,21560,24688,27965,32725,33288,20694,20958,21916,22123,22221,23020,23305,24076,24985,24984,25137,26206,26342,29081,29113,29114,29351,31143,31232,32690,35440,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],gb18030:[19970,19972,19973,19974,19983,19986,19991,19999,2e4,20001,20003,20006,20009,20014,20015,20017,20019,20021,20023,20028,20032,20033,20034,20036,20038,20042,20049,20053,20055,20058,20059,20066,20067,20068,20069,20071,20072,20074,20075,20076,20077,20078,20079,20082,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20095,20096,20097,20098,20099,20100,20101,20103,20106,20112,20118,20119,20121,20124,20125,20126,20131,20138,20143,20144,20145,20148,20150,20151,20152,20153,20156,20157,20158,20168,20172,20175,20176,20178,20186,20187,20188,20192,20194,20198,20199,20201,20205,20206,20207,20209,20212,20216,20217,20218,20220,20222,20224,20226,20227,20228,20229,20230,20231,20232,20235,20236,20242,20243,20244,20245,20246,20252,20253,20257,20259,20264,20265,20268,20269,20270,20273,20275,20277,20279,20281,20283,20286,20287,20288,20289,20290,20292,20293,20295,20296,20297,20298,20299,20300,20306,20308,20310,20321,20322,20326,20328,20330,20331,20333,20334,20337,20338,20341,20343,20344,20345,20346,20349,20352,20353,20354,20357,20358,20359,20362,20364,20366,20368,20370,20371,20373,20374,20376,20377,20378,20380,20382,20383,20385,20386,20388,20395,20397,20400,20401,20402,20403,20404,20406,20407,20408,20409,20410,20411,20412,20413,20414,20416,20417,20418,20422,20423,20424,20425,20427,20428,20429,20434,20435,20436,20437,20438,20441,20443,20448,20450,20452,20453,20455,20459,20460,20464,20466,20468,20469,20470,20471,20473,20475,20476,20477,20479,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20494,20496,20497,20499,20501,20502,20503,20507,20509,20510,20512,20514,20515,20516,20519,20523,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20539,20541,20543,20544,20545,20546,20548,20549,20550,20553,20554,20555,20557,20560,20561,20562,20563,20564,20566,20567,20568,20569,20571,20573,20574,20575,20576,20577,20578,20579,20580,20582,20583,20584,20585,20586,20587,20589,20590,20591,20592,20593,20594,20595,20596,20597,20600,20601,20602,20604,20605,20609,20610,20611,20612,20614,20615,20617,20618,20619,20620,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20644,20646,20650,20651,20653,20654,20655,20656,20657,20659,20660,20661,20662,20663,20664,20665,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20688,20689,20690,20691,20692,20693,20695,20696,20697,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20712,20713,20714,20715,20719,20720,20721,20722,20724,20726,20727,20728,20729,20730,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20744,20745,20746,20748,20749,20750,20751,20752,20753,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20802,20807,20810,20812,20814,20815,20816,20818,20819,20823,20824,20825,20827,20829,20830,20831,20832,20833,20835,20836,20838,20839,20841,20842,20847,20850,20858,20862,20863,20867,20868,20870,20871,20874,20875,20878,20879,20880,20881,20883,20884,20888,20890,20893,20894,20895,20897,20899,20902,20903,20904,20905,20906,20909,20910,20916,20920,20921,20922,20926,20927,20929,20930,20931,20933,20936,20938,20941,20942,20944,20946,20947,20948,20949,20950,20951,20952,20953,20954,20956,20958,20959,20962,20963,20965,20966,20967,20968,20969,20970,20972,20974,20977,20978,20980,20983,20990,20996,20997,21001,21003,21004,21007,21008,21011,21012,21013,21020,21022,21023,21025,21026,21027,21029,21030,21031,21034,21036,21039,21041,21042,21044,21045,21052,21054,21060,21061,21062,21063,21064,21065,21067,21070,21071,21074,21075,21077,21079,21080,21081,21082,21083,21085,21087,21088,21090,21091,21092,21094,21096,21099,21100,21101,21102,21104,21105,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21118,21120,21123,21124,21125,21126,21127,21129,21130,21131,21132,21133,21134,21135,21137,21138,21140,21141,21142,21143,21144,21145,21146,21148,21156,21157,21158,21159,21166,21167,21168,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21184,21185,21186,21188,21189,21190,21192,21194,21196,21197,21198,21199,21201,21203,21204,21205,21207,21209,21210,21211,21212,21213,21214,21216,21217,21218,21219,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21233,21234,21235,21236,21237,21238,21239,21240,21243,21244,21245,21249,21250,21251,21252,21255,21257,21258,21259,21260,21262,21265,21266,21267,21268,21272,21275,21276,21278,21279,21282,21284,21285,21287,21288,21289,21291,21292,21293,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21308,21309,21312,21314,21316,21318,21323,21324,21325,21328,21332,21336,21337,21339,21341,21349,21352,21354,21356,21357,21362,21366,21369,21371,21372,21373,21374,21376,21377,21379,21383,21384,21386,21390,21391,21392,21393,21394,21395,21396,21398,21399,21401,21403,21404,21406,21408,21409,21412,21415,21418,21419,21420,21421,21423,21424,21425,21426,21427,21428,21429,21431,21432,21433,21434,21436,21437,21438,21440,21443,21444,21445,21446,21447,21454,21455,21456,21458,21459,21461,21466,21468,21469,21470,21473,21474,21479,21492,21498,21502,21503,21504,21506,21509,21511,21515,21524,21528,21529,21530,21532,21538,21540,21541,21546,21552,21555,21558,21559,21562,21565,21567,21569,21570,21572,21573,21575,21577,21580,21581,21582,21583,21585,21594,21597,21598,21599,21600,21601,21603,21605,21607,21609,21610,21611,21612,21613,21614,21615,21616,21620,21625,21626,21630,21631,21633,21635,21637,21639,21640,21641,21642,21645,21649,21651,21655,21656,21660,21662,21663,21664,21665,21666,21669,21678,21680,21682,21685,21686,21687,21689,21690,21692,21694,21699,21701,21706,21707,21718,21720,21723,21728,21729,21730,21731,21732,21739,21740,21743,21744,21745,21748,21749,21750,21751,21752,21753,21755,21758,21760,21762,21763,21764,21765,21768,21770,21771,21772,21773,21774,21778,21779,21781,21782,21783,21784,21785,21786,21788,21789,21790,21791,21793,21797,21798,21800,21801,21803,21805,21810,21812,21813,21814,21816,21817,21818,21819,21821,21824,21826,21829,21831,21832,21835,21836,21837,21838,21839,21841,21842,21843,21844,21847,21848,21849,21850,21851,21853,21854,21855,21856,21858,21859,21864,21865,21867,21871,21872,21873,21874,21875,21876,21881,21882,21885,21887,21893,21894,21900,21901,21902,21904,21906,21907,21909,21910,21911,21914,21915,21918,21920,21921,21922,21923,21924,21925,21926,21928,21929,21930,21931,21932,21933,21934,21935,21936,21938,21940,21942,21944,21946,21948,21951,21952,21953,21954,21955,21958,21959,21960,21962,21963,21966,21967,21968,21973,21975,21976,21977,21978,21979,21982,21984,21986,21991,21993,21997,21998,22e3,22001,22004,22006,22008,22009,22010,22011,22012,22015,22018,22019,22020,22021,22022,22023,22026,22027,22029,22032,22033,22034,22035,22036,22037,22038,22039,22041,22042,22044,22045,22048,22049,22050,22053,22054,22056,22057,22058,22059,22062,22063,22064,22067,22069,22071,22072,22074,22076,22077,22078,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22095,22096,22097,22098,22099,22101,22102,22106,22107,22109,22110,22111,22112,22113,22115,22117,22118,22119,22125,22126,22127,22128,22130,22131,22132,22133,22135,22136,22137,22138,22141,22142,22143,22144,22145,22146,22147,22148,22151,22152,22153,22154,22155,22156,22157,22160,22161,22162,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22192,22193,22194,22195,22196,22197,22198,22200,22201,22202,22203,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22219,22220,22221,22222,22223,22224,22225,22226,22227,22229,22230,22232,22233,22236,22243,22245,22246,22247,22248,22249,22250,22252,22254,22255,22258,22259,22262,22263,22264,22267,22268,22272,22273,22274,22277,22279,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22301,22302,22304,22305,22306,22308,22309,22310,22311,22315,22321,22322,22324,22325,22326,22327,22328,22332,22333,22335,22337,22339,22340,22341,22342,22344,22345,22347,22354,22355,22356,22357,22358,22360,22361,22370,22371,22373,22375,22380,22382,22384,22385,22386,22388,22389,22392,22393,22394,22397,22398,22399,22400,22401,22407,22408,22409,22410,22413,22414,22415,22416,22417,22420,22421,22422,22423,22424,22425,22426,22428,22429,22430,22431,22437,22440,22442,22444,22447,22448,22449,22451,22453,22454,22455,22457,22458,22459,22460,22461,22462,22463,22464,22465,22468,22469,22470,22471,22472,22473,22474,22476,22477,22480,22481,22483,22486,22487,22491,22492,22494,22497,22498,22499,22501,22502,22503,22504,22505,22506,22507,22508,22510,22512,22513,22514,22515,22517,22518,22519,22523,22524,22526,22527,22529,22531,22532,22533,22536,22537,22538,22540,22542,22543,22544,22546,22547,22548,22550,22551,22552,22554,22555,22556,22557,22559,22562,22563,22565,22566,22567,22568,22569,22571,22572,22573,22574,22575,22577,22578,22579,22580,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22597,22598,22599,22600,22601,22602,22603,22606,22607,22608,22610,22611,22613,22614,22615,22617,22618,22619,22620,22621,22623,22624,22625,22626,22627,22628,22630,22631,22632,22633,22634,22637,22638,22639,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22655,22658,22660,22662,22663,22664,22666,22667,22668,22669,22670,22671,22672,22673,22676,22677,22678,22679,22680,22683,22684,22685,22688,22689,22690,22691,22692,22693,22694,22695,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22717,22718,22719,22720,22722,22723,22724,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22738,22739,22740,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22757,22758,22759,22760,22761,22762,22765,22767,22769,22770,22772,22773,22775,22776,22778,22779,22780,22781,22782,22783,22784,22785,22787,22789,22790,22792,22793,22794,22795,22796,22798,22800,22801,22802,22803,22807,22808,22811,22813,22814,22816,22817,22818,22819,22822,22824,22828,22832,22834,22835,22837,22838,22843,22845,22846,22847,22848,22851,22853,22854,22858,22860,22861,22864,22866,22867,22873,22875,22876,22877,22878,22879,22881,22883,22884,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22901,22903,22906,22907,22908,22910,22911,22912,22917,22921,22923,22924,22926,22927,22928,22929,22932,22933,22936,22938,22939,22940,22941,22943,22944,22945,22946,22950,22951,22956,22957,22960,22961,22963,22964,22965,22966,22967,22968,22970,22972,22973,22975,22976,22977,22978,22979,22980,22981,22983,22984,22985,22988,22989,22990,22991,22997,22998,23001,23003,23006,23007,23008,23009,23010,23012,23014,23015,23017,23018,23019,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23034,23036,23037,23038,23040,23042,23050,23051,23053,23054,23055,23056,23058,23060,23061,23062,23063,23065,23066,23067,23069,23070,23073,23074,23076,23078,23079,23080,23082,23083,23084,23085,23086,23087,23088,23091,23093,23095,23096,23097,23098,23099,23101,23102,23103,23105,23106,23107,23108,23109,23111,23112,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23126,23127,23128,23129,23131,23132,23133,23134,23135,23136,23137,23139,23140,23141,23142,23144,23145,23147,23148,23149,23150,23151,23152,23153,23154,23155,23160,23161,23163,23164,23165,23166,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23187,23188,23189,23190,23191,23192,23193,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23211,23212,23213,23214,23215,23216,23217,23220,23222,23223,23225,23226,23227,23228,23229,23231,23232,23235,23236,23237,23238,23239,23240,23242,23243,23245,23246,23247,23248,23249,23251,23253,23255,23257,23258,23259,23261,23262,23263,23266,23268,23269,23271,23272,23274,23276,23277,23278,23279,23280,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23304,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23347,23349,23350,23352,23353,23354,23355,23356,23357,23358,23359,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23378,23382,23390,23392,23393,23399,23400,23403,23405,23406,23407,23410,23412,23414,23415,23416,23417,23419,23420,23422,23423,23426,23430,23434,23437,23438,23440,23441,23442,23444,23446,23455,23463,23464,23465,23468,23469,23470,23471,23473,23474,23479,23482,23483,23484,23488,23489,23491,23496,23497,23498,23499,23501,23502,23503,23505,23508,23509,23510,23511,23512,23513,23514,23515,23516,23520,23522,23523,23526,23527,23529,23530,23531,23532,23533,23535,23537,23538,23539,23540,23541,23542,23543,23549,23550,23552,23554,23555,23557,23559,23560,23563,23564,23565,23566,23568,23570,23571,23575,23577,23579,23582,23583,23584,23585,23587,23590,23592,23593,23594,23595,23597,23598,23599,23600,23602,23603,23605,23606,23607,23619,23620,23622,23623,23628,23629,23634,23635,23636,23638,23639,23640,23642,23643,23644,23645,23647,23650,23652,23655,23656,23657,23658,23659,23660,23661,23664,23666,23667,23668,23669,23670,23671,23672,23675,23676,23677,23678,23680,23683,23684,23685,23686,23687,23689,23690,23691,23694,23695,23698,23699,23701,23709,23710,23711,23712,23713,23716,23717,23718,23719,23720,23722,23726,23727,23728,23730,23732,23734,23737,23738,23739,23740,23742,23744,23746,23747,23749,23750,23751,23752,23753,23754,23756,23757,23758,23759,23760,23761,23763,23764,23765,23766,23767,23768,23770,23771,23772,23773,23774,23775,23776,23778,23779,23783,23785,23787,23788,23790,23791,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802,23804,23805,23806,23807,23808,23809,23812,23813,23816,23817,23818,23819,23820,23821,23823,23824,23825,23826,23827,23829,23831,23832,23833,23834,23836,23837,23839,23840,23841,23842,23843,23845,23848,23850,23851,23852,23855,23856,23857,23858,23859,23861,23862,23863,23864,23865,23866,23867,23868,23871,23872,23873,23874,23875,23876,23877,23878,23880,23881,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23897,23898,23900,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23914,23917,23918,23920,23921,23922,23923,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23962,23963,23964,23966,23967,23968,23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23992,23993,23994,23995,23996,23997,23998,23999,24e3,24001,24002,24003,24004,24006,24007,24008,24009,24010,24011,24012,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24028,24031,24032,24035,24036,24042,24044,24045,24048,24053,24054,24056,24057,24058,24059,24060,24063,24064,24068,24071,24073,24074,24075,24077,24078,24082,24083,24087,24094,24095,24096,24097,24098,24099,24100,24101,24104,24105,24106,24107,24108,24111,24112,24114,24115,24116,24117,24118,24121,24122,24126,24127,24128,24129,24131,24134,24135,24136,24137,24138,24139,24141,24142,24143,24144,24145,24146,24147,24150,24151,24152,24153,24154,24156,24157,24159,24160,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24181,24183,24185,24190,24193,24194,24195,24197,24200,24201,24204,24205,24206,24210,24216,24219,24221,24225,24226,24227,24228,24232,24233,24234,24235,24236,24238,24239,24240,24241,24242,24244,24250,24251,24252,24253,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24267,24268,24269,24270,24271,24272,24276,24277,24279,24280,24281,24282,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24297,24299,24300,24301,24302,24303,24304,24305,24306,24307,24309,24312,24313,24315,24316,24317,24325,24326,24327,24329,24332,24333,24334,24336,24338,24340,24342,24345,24346,24348,24349,24350,24353,24354,24355,24356,24360,24363,24364,24366,24368,24370,24371,24372,24373,24374,24375,24376,24379,24381,24382,24383,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24401,24404,24409,24410,24411,24412,24414,24415,24416,24419,24421,24423,24424,24427,24430,24431,24434,24436,24437,24438,24440,24442,24445,24446,24447,24451,24454,24461,24462,24463,24465,24467,24468,24470,24474,24475,24477,24478,24479,24480,24482,24483,24484,24485,24486,24487,24489,24491,24492,24495,24496,24497,24498,24499,24500,24502,24504,24505,24506,24507,24510,24511,24512,24513,24514,24519,24520,24522,24523,24526,24531,24532,24533,24538,24539,24540,24542,24543,24546,24547,24549,24550,24552,24553,24556,24559,24560,24562,24563,24564,24566,24567,24569,24570,24572,24583,24584,24585,24587,24588,24592,24593,24595,24599,24600,24602,24606,24607,24610,24611,24612,24620,24621,24622,24624,24625,24626,24627,24628,24630,24631,24632,24633,24634,24637,24638,24640,24644,24645,24646,24647,24648,24649,24650,24652,24654,24655,24657,24659,24660,24662,24663,24664,24667,24668,24670,24671,24672,24673,24677,24678,24686,24689,24690,24692,24693,24695,24702,24704,24705,24706,24709,24710,24711,24712,24714,24715,24718,24719,24720,24721,24723,24725,24727,24728,24729,24732,24734,24737,24738,24740,24741,24743,24745,24746,24750,24752,24755,24757,24758,24759,24761,24762,24765,24766,24767,24768,24769,24770,24771,24772,24775,24776,24777,24780,24781,24782,24783,24784,24786,24787,24788,24790,24791,24793,24795,24798,24801,24802,24803,24804,24805,24810,24817,24818,24821,24823,24824,24827,24828,24829,24830,24831,24834,24835,24836,24837,24839,24842,24843,24844,24848,24849,24850,24851,24852,24854,24855,24856,24857,24859,24860,24861,24862,24865,24866,24869,24872,24873,24874,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24896,24897,24898,24899,24900,24901,24902,24903,24905,24907,24909,24911,24912,24914,24915,24916,24918,24919,24920,24921,24922,24923,24924,24926,24927,24928,24929,24931,24932,24933,24934,24937,24938,24939,24940,24941,24942,24943,24945,24946,24947,24948,24950,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,24972,24973,24975,24976,24977,24978,24979,24981,24982,24983,24984,24985,24986,24987,24988,24990,24991,24992,24993,24994,24995,24996,24997,24998,25002,25003,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25016,25017,25018,25019,25020,25021,25023,25024,25025,25027,25028,25029,25030,25031,25033,25036,25037,25038,25039,25040,25043,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25078,25079,25080,25081,25082,25083,25084,25085,25086,25088,25089,25090,25091,25092,25093,25095,25097,25107,25108,25113,25116,25117,25118,25120,25123,25126,25127,25128,25129,25131,25133,25135,25136,25137,25138,25141,25142,25144,25145,25146,25147,25148,25154,25156,25157,25158,25162,25167,25168,25173,25174,25175,25177,25178,25180,25181,25182,25183,25184,25185,25186,25188,25189,25192,25201,25202,25204,25205,25207,25208,25210,25211,25213,25217,25218,25219,25221,25222,25223,25224,25227,25228,25229,25230,25231,25232,25236,25241,25244,25245,25246,25251,25254,25255,25257,25258,25261,25262,25263,25264,25266,25267,25268,25270,25271,25272,25274,25278,25280,25281,25283,25291,25295,25297,25301,25309,25310,25312,25313,25316,25322,25323,25328,25330,25333,25336,25337,25338,25339,25344,25347,25348,25349,25350,25354,25355,25356,25357,25359,25360,25362,25363,25364,25365,25367,25368,25369,25372,25382,25383,25385,25388,25389,25390,25392,25393,25395,25396,25397,25398,25399,25400,25403,25404,25406,25407,25408,25409,25412,25415,25416,25418,25425,25426,25427,25428,25430,25431,25432,25433,25434,25435,25436,25437,25440,25444,25445,25446,25448,25450,25451,25452,25455,25456,25458,25459,25460,25461,25464,25465,25468,25469,25470,25471,25473,25475,25476,25477,25478,25483,25485,25489,25491,25492,25493,25495,25497,25498,25499,25500,25501,25502,25503,25505,25508,25510,25515,25519,25521,25522,25525,25526,25529,25531,25533,25535,25536,25537,25538,25539,25541,25543,25544,25546,25547,25548,25553,25555,25556,25557,25559,25560,25561,25562,25563,25564,25565,25567,25570,25572,25573,25574,25575,25576,25579,25580,25582,25583,25584,25585,25587,25589,25591,25593,25594,25595,25596,25598,25603,25604,25606,25607,25608,25609,25610,25613,25614,25617,25618,25621,25622,25623,25624,25625,25626,25629,25631,25634,25635,25636,25637,25639,25640,25641,25643,25646,25647,25648,25649,25650,25651,25653,25654,25655,25656,25657,25659,25660,25662,25664,25666,25667,25673,25675,25676,25677,25678,25679,25680,25681,25683,25685,25686,25687,25689,25690,25691,25692,25693,25695,25696,25697,25698,25699,25700,25701,25702,25704,25706,25707,25708,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25723,25724,25725,25726,25727,25728,25729,25731,25734,25736,25737,25738,25739,25740,25741,25742,25743,25744,25747,25748,25751,25752,25754,25755,25756,25757,25759,25760,25761,25762,25763,25765,25766,25767,25768,25770,25771,25775,25777,25778,25779,25780,25782,25785,25787,25789,25790,25791,25793,25795,25796,25798,25799,25800,25801,25802,25803,25804,25807,25809,25811,25812,25813,25814,25817,25818,25819,25820,25821,25823,25824,25825,25827,25829,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25857,25858,25859,25860,25861,25862,25863,25864,25866,25867,25868,25869,25870,25871,25872,25873,25875,25876,25877,25878,25879,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25894,25895,25896,25897,25898,25900,25901,25904,25905,25906,25907,25911,25914,25916,25917,25920,25921,25922,25923,25924,25926,25927,25930,25931,25933,25934,25936,25938,25939,25940,25943,25944,25946,25948,25951,25952,25953,25956,25957,25959,25960,25961,25962,25965,25966,25967,25969,25971,25973,25974,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25992,25993,25994,25997,25998,25999,26002,26004,26005,26006,26008,26010,26013,26014,26016,26018,26019,26022,26024,26026,26028,26030,26033,26034,26035,26036,26037,26038,26039,26040,26042,26043,26046,26047,26048,26050,26055,26056,26057,26058,26061,26064,26065,26067,26068,26069,26072,26073,26074,26075,26076,26077,26078,26079,26081,26083,26084,26090,26091,26098,26099,26100,26101,26104,26105,26107,26108,26109,26110,26111,26113,26116,26117,26119,26120,26121,26123,26125,26128,26129,26130,26134,26135,26136,26138,26139,26140,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26162,26163,26167,26168,26169,26170,26171,26173,26175,26176,26178,26180,26181,26182,26183,26184,26185,26186,26189,26190,26192,26193,26200,26201,26203,26204,26205,26206,26208,26210,26211,26213,26215,26217,26218,26219,26220,26221,26225,26226,26227,26229,26232,26233,26235,26236,26237,26239,26240,26241,26243,26245,26246,26248,26249,26250,26251,26253,26254,26255,26256,26258,26259,26260,26261,26264,26265,26266,26267,26268,26270,26271,26272,26273,26274,26275,26276,26277,26278,26281,26282,26283,26284,26285,26287,26288,26289,26290,26291,26293,26294,26295,26296,26298,26299,26300,26301,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26330,26334,26335,26336,26337,26338,26339,26340,26341,26343,26344,26346,26347,26348,26349,26350,26351,26353,26357,26358,26360,26362,26363,26365,26369,26370,26371,26372,26373,26374,26375,26380,26382,26383,26385,26386,26387,26390,26392,26393,26394,26396,26398,26400,26401,26402,26403,26404,26405,26407,26409,26414,26416,26418,26419,26422,26423,26424,26425,26427,26428,26430,26431,26433,26436,26437,26439,26442,26443,26445,26450,26452,26453,26455,26456,26457,26458,26459,26461,26466,26467,26468,26470,26471,26475,26476,26478,26481,26484,26486,26488,26489,26490,26491,26493,26496,26498,26499,26501,26502,26504,26506,26508,26509,26510,26511,26513,26514,26515,26516,26518,26521,26523,26527,26528,26529,26532,26534,26537,26540,26542,26545,26546,26548,26553,26554,26555,26556,26557,26558,26559,26560,26562,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26581,26582,26583,26587,26591,26593,26595,26596,26598,26599,26600,26602,26603,26605,26606,26610,26613,26614,26615,26616,26617,26618,26619,26620,26622,26625,26626,26627,26628,26630,26637,26640,26642,26644,26645,26648,26649,26650,26651,26652,26654,26655,26656,26658,26659,26660,26661,26662,26663,26664,26667,26668,26669,26670,26671,26672,26673,26676,26677,26678,26682,26683,26687,26695,26699,26701,26703,26706,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26730,26732,26733,26734,26735,26736,26737,26738,26739,26741,26744,26745,26746,26747,26748,26749,26750,26751,26752,26754,26756,26759,26760,26761,26762,26763,26764,26765,26766,26768,26769,26770,26772,26773,26774,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26787,26788,26789,26793,26794,26795,26796,26798,26801,26802,26804,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26817,26819,26820,26821,26822,26823,26824,26826,26828,26830,26831,26832,26833,26835,26836,26838,26839,26841,26843,26844,26845,26846,26847,26849,26850,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26863,26866,26867,26868,26870,26871,26872,26875,26877,26878,26879,26880,26882,26883,26884,26886,26887,26888,26889,26890,26892,26895,26897,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26913,26914,26915,26917,26918,26919,26920,26921,26922,26923,26924,26926,26927,26929,26930,26931,26933,26934,26935,26936,26938,26939,26940,26942,26944,26945,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,26963,26965,26966,26968,26969,26971,26972,26975,26977,26978,26980,26981,26983,26984,26985,26986,26988,26989,26991,26992,26994,26995,26996,26997,26998,27002,27003,27005,27006,27007,27009,27011,27013,27018,27019,27020,27022,27023,27024,27025,27026,27027,27030,27031,27033,27034,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27049,27050,27052,27054,27055,27056,27058,27059,27061,27062,27064,27065,27066,27068,27069,27070,27071,27072,27074,27075,27076,27077,27078,27079,27080,27081,27083,27085,27087,27089,27090,27091,27093,27094,27095,27096,27097,27098,27100,27101,27102,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27118,27119,27120,27121,27123,27124,27125,27126,27127,27128,27129,27130,27131,27132,27134,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27161,27162,27163,27164,27165,27166,27168,27170,27171,27172,27173,27174,27175,27177,27179,27180,27181,27182,27184,27186,27187,27188,27190,27191,27192,27193,27194,27195,27196,27199,27200,27201,27202,27203,27205,27206,27208,27209,27210,27211,27212,27213,27214,27215,27217,27218,27219,27220,27221,27222,27223,27226,27228,27229,27230,27231,27232,27234,27235,27236,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27250,27251,27252,27253,27254,27255,27256,27258,27259,27261,27262,27263,27265,27266,27267,27269,27270,27271,27272,27273,27274,27275,27276,27277,27279,27282,27283,27284,27285,27286,27288,27289,27290,27291,27292,27293,27294,27295,27297,27298,27299,27300,27301,27302,27303,27304,27306,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27429,27430,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27443,27444,27445,27446,27448,27451,27452,27453,27455,27456,27457,27458,27460,27461,27464,27466,27467,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27482,27483,27484,27485,27486,27487,27488,27489,27496,27497,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27514,27517,27518,27519,27520,27525,27528,27532,27534,27535,27536,27537,27540,27541,27543,27544,27545,27548,27549,27550,27551,27552,27554,27555,27556,27557,27558,27559,27560,27561,27563,27564,27565,27566,27567,27568,27569,27570,27574,27576,27577,27578,27579,27580,27581,27582,27584,27587,27588,27590,27591,27592,27593,27594,27596,27598,27600,27601,27608,27610,27612,27613,27614,27615,27616,27618,27619,27620,27621,27622,27623,27624,27625,27628,27629,27630,27632,27633,27634,27636,27638,27639,27640,27642,27643,27644,27646,27647,27648,27649,27650,27651,27652,27656,27657,27658,27659,27660,27662,27666,27671,27676,27677,27678,27680,27683,27685,27691,27692,27693,27697,27699,27702,27703,27705,27706,27707,27708,27710,27711,27715,27716,27717,27720,27723,27724,27725,27726,27727,27729,27730,27731,27734,27736,27737,27738,27746,27747,27749,27750,27751,27755,27756,27757,27758,27759,27761,27763,27765,27767,27768,27770,27771,27772,27775,27776,27780,27783,27786,27787,27789,27790,27793,27794,27797,27798,27799,27800,27802,27804,27805,27806,27808,27810,27816,27820,27823,27824,27828,27829,27830,27831,27834,27840,27841,27842,27843,27846,27847,27848,27851,27853,27854,27855,27857,27858,27864,27865,27866,27868,27869,27871,27876,27878,27879,27881,27884,27885,27890,27892,27897,27903,27904,27906,27907,27909,27910,27912,27913,27914,27917,27919,27920,27921,27923,27924,27925,27926,27928,27932,27933,27935,27936,27937,27938,27939,27940,27942,27944,27945,27948,27949,27951,27952,27956,27958,27959,27960,27962,27967,27968,27970,27972,27977,27980,27984,27989,27990,27991,27992,27995,27997,27999,28001,28002,28004,28005,28007,28008,28011,28012,28013,28016,28017,28018,28019,28021,28022,28025,28026,28027,28029,28030,28031,28032,28033,28035,28036,28038,28039,28042,28043,28045,28047,28048,28050,28054,28055,28056,28057,28058,28060,28066,28069,28076,28077,28080,28081,28083,28084,28086,28087,28089,28090,28091,28092,28093,28094,28097,28098,28099,28104,28105,28106,28109,28110,28111,28112,28114,28115,28116,28117,28119,28122,28123,28124,28127,28130,28131,28133,28135,28136,28137,28138,28141,28143,28144,28146,28148,28149,28150,28152,28154,28157,28158,28159,28160,28161,28162,28163,28164,28166,28167,28168,28169,28171,28175,28178,28179,28181,28184,28185,28187,28188,28190,28191,28194,28198,28199,28200,28202,28204,28206,28208,28209,28211,28213,28214,28215,28217,28219,28220,28221,28222,28223,28224,28225,28226,28229,28230,28231,28232,28233,28234,28235,28236,28239,28240,28241,28242,28245,28247,28249,28250,28252,28253,28254,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28268,28269,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28288,28289,28290,28292,28295,28296,28298,28299,28300,28301,28302,28305,28306,28307,28308,28309,28310,28311,28313,28314,28315,28317,28318,28320,28321,28323,28324,28326,28328,28329,28331,28332,28333,28334,28336,28339,28341,28344,28345,28348,28350,28351,28352,28355,28356,28357,28358,28360,28361,28362,28364,28365,28366,28368,28370,28374,28376,28377,28379,28380,28381,28387,28391,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28405,28406,28407,28408,28410,28411,28412,28413,28414,28415,28416,28417,28419,28420,28421,28423,28424,28426,28427,28428,28429,28430,28432,28433,28434,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28449,28450,28451,28453,28454,28455,28456,28460,28462,28464,28466,28468,28469,28471,28472,28473,28474,28475,28476,28477,28479,28480,28481,28482,28483,28484,28485,28488,28489,28490,28492,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28505,28506,28507,28509,28511,28512,28513,28515,28516,28517,28519,28520,28521,28522,28523,28524,28527,28528,28529,28531,28533,28534,28535,28537,28539,28541,28542,28543,28544,28545,28546,28547,28549,28550,28551,28554,28555,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28573,28574,28575,28576,28578,28579,28580,28581,28582,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28596,28597,28599,28600,28602,28603,28604,28605,28606,28607,28609,28611,28612,28613,28614,28615,28616,28618,28619,28620,28621,28622,28623,28624,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28639,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28690,28691,28692,28693,28694,28695,28696,28697,28700,28701,28702,28703,28704,28705,28706,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28726,28727,28728,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28749,28750,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28782,28785,28786,28787,28788,28791,28793,28794,28795,28797,28801,28802,28803,28804,28806,28807,28808,28811,28812,28813,28815,28816,28817,28819,28823,28824,28826,28827,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28848,28850,28852,28853,28854,28858,28862,28863,28868,28869,28870,28871,28873,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28890,28892,28893,28894,28896,28897,28898,28899,28901,28906,28910,28912,28913,28914,28915,28916,28917,28918,28920,28922,28923,28924,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28939,28940,28941,28942,28943,28945,28946,28948,28951,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28967,28968,28969,28970,28971,28972,28973,28974,28978,28979,28980,28981,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28998,28999,29e3,29001,29003,29005,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29021,29023,29024,29025,29026,29027,29029,29033,29034,29035,29036,29037,29039,29040,29041,29044,29045,29046,29047,29049,29051,29052,29054,29055,29056,29057,29058,29059,29061,29062,29063,29064,29065,29067,29068,29069,29070,29072,29073,29074,29075,29077,29078,29079,29082,29083,29084,29085,29086,29089,29090,29091,29092,29093,29094,29095,29097,29098,29099,29101,29102,29103,29104,29105,29106,29108,29110,29111,29112,29114,29115,29116,29117,29118,29119,29120,29121,29122,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29135,29136,29137,29138,29139,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29153,29154,29155,29156,29158,29160,29161,29162,29163,29164,29165,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29225,29227,29229,29230,29231,29234,29235,29236,29242,29244,29246,29248,29249,29250,29251,29252,29253,29254,29257,29258,29259,29262,29263,29264,29265,29267,29268,29269,29271,29272,29274,29276,29278,29280,29283,29284,29285,29288,29290,29291,29292,29293,29296,29297,29299,29300,29302,29303,29304,29307,29308,29309,29314,29315,29317,29318,29319,29320,29321,29324,29326,29328,29329,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29358,29361,29362,29363,29365,29370,29371,29372,29373,29374,29375,29376,29381,29382,29383,29385,29386,29387,29388,29391,29393,29395,29396,29397,29398,29400,29402,29403,58566,58567,58568,58569,58570,58571,58572,58573,58574,58575,58576,58577,58578,58579,58580,58581,58582,58583,58584,58585,58586,58587,58588,58589,58590,58591,58592,58593,58594,58595,58596,58597,58598,58599,58600,58601,58602,58603,58604,58605,58606,58607,58608,58609,58610,58611,58612,58613,58614,58615,58616,58617,58618,58619,58620,58621,58622,58623,58624,58625,58626,58627,58628,58629,58630,58631,58632,58633,58634,58635,58636,58637,58638,58639,58640,58641,58642,58643,58644,58645,58646,58647,58648,58649,58650,58651,58652,58653,58654,58655,58656,58657,58658,58659,58660,58661,12288,12289,12290,183,713,711,168,12291,12293,8212,65374,8214,8230,8216,8217,8220,8221,12308,12309,12296,12297,12298,12299,12300,12301,12302,12303,12310,12311,12304,12305,177,215,247,8758,8743,8744,8721,8719,8746,8745,8712,8759,8730,8869,8741,8736,8978,8857,8747,8750,8801,8780,8776,8765,8733,8800,8814,8815,8804,8805,8734,8757,8756,9794,9792,176,8242,8243,8451,65284,164,65504,65505,8240,167,8470,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,8251,8594,8592,8593,8595,12307,58662,58663,58664,58665,58666,58667,58668,58669,58670,58671,58672,58673,58674,58675,58676,58677,58678,58679,58680,58681,58682,58683,58684,58685,58686,58687,58688,58689,58690,58691,58692,58693,58694,58695,58696,58697,58698,58699,58700,58701,58702,58703,58704,58705,58706,58707,58708,58709,58710,58711,58712,58713,58714,58715,58716,58717,58718,58719,58720,58721,58722,58723,58724,58725,58726,58727,58728,58729,58730,58731,58732,58733,58734,58735,58736,58737,58738,58739,58740,58741,58742,58743,58744,58745,58746,58747,58748,58749,58750,58751,58752,58753,58754,58755,58756,58757,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,59238,59239,59240,59241,59242,59243,9352,9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9370,9371,9332,9333,9334,9335,9336,9337,9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,8364,59245,12832,12833,12834,12835,12836,12837,12838,12839,12840,12841,59246,59247,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,59248,59249,58758,58759,58760,58761,58762,58763,58764,58765,58766,58767,58768,58769,58770,58771,58772,58773,58774,58775,58776,58777,58778,58779,58780,58781,58782,58783,58784,58785,58786,58787,58788,58789,58790,58791,58792,58793,58794,58795,58796,58797,58798,58799,58800,58801,58802,58803,58804,58805,58806,58807,58808,58809,58810,58811,58812,58813,58814,58815,58816,58817,58818,58819,58820,58821,58822,58823,58824,58825,58826,58827,58828,58829,58830,58831,58832,58833,58834,58835,58836,58837,58838,58839,58840,58841,58842,58843,58844,58845,58846,58847,58848,58849,58850,58851,58852,12288,65281,65282,65283,65509,65285,65286,65287,65288,65289,65290,65291,65292,65293,65294,65295,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,65306,65307,65308,65309,65310,65311,65312,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,65339,65340,65341,65342,65343,65344,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65371,65372,65373,65507,58854,58855,58856,58857,58858,58859,58860,58861,58862,58863,58864,58865,58866,58867,58868,58869,58870,58871,58872,58873,58874,58875,58876,58877,58878,58879,58880,58881,58882,58883,58884,58885,58886,58887,58888,58889,58890,58891,58892,58893,58894,58895,58896,58897,58898,58899,58900,58901,58902,58903,58904,58905,58906,58907,58908,58909,58910,58911,58912,58913,58914,58915,58916,58917,58918,58919,58920,58921,58922,58923,58924,58925,58926,58927,58928,58929,58930,58931,58932,58933,58934,58935,58936,58937,58938,58939,58940,58941,58942,58943,58944,58945,58946,58947,58948,58949,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,59250,59251,59252,59253,59254,59255,59256,59257,59258,59259,59260,58950,58951,58952,58953,58954,58955,58956,58957,58958,58959,58960,58961,58962,58963,58964,58965,58966,58967,58968,58969,58970,58971,58972,58973,58974,58975,58976,58977,58978,58979,58980,58981,58982,58983,58984,58985,58986,58987,58988,58989,58990,58991,58992,58993,58994,58995,58996,58997,58998,58999,59e3,59001,59002,59003,59004,59005,59006,59007,59008,59009,59010,59011,59012,59013,59014,59015,59016,59017,59018,59019,59020,59021,59022,59023,59024,59025,59026,59027,59028,59029,59030,59031,59032,59033,59034,59035,59036,59037,59038,59039,59040,59041,59042,59043,59044,59045,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,59261,59262,59263,59264,59265,59266,59267,59268,59046,59047,59048,59049,59050,59051,59052,59053,59054,59055,59056,59057,59058,59059,59060,59061,59062,59063,59064,59065,59066,59067,59068,59069,59070,59071,59072,59073,59074,59075,59076,59077,59078,59079,59080,59081,59082,59083,59084,59085,59086,59087,59088,59089,59090,59091,59092,59093,59094,59095,59096,59097,59098,59099,59100,59101,59102,59103,59104,59105,59106,59107,59108,59109,59110,59111,59112,59113,59114,59115,59116,59117,59118,59119,59120,59121,59122,59123,59124,59125,59126,59127,59128,59129,59130,59131,59132,59133,59134,59135,59136,59137,59138,59139,59140,59141,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,59269,59270,59271,59272,59273,59274,59275,59276,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,59277,59278,59279,59280,59281,59282,59283,65077,65078,65081,65082,65087,65088,65085,65086,65089,65090,65091,65092,59284,59285,65083,65084,65079,65080,65073,59286,65075,65076,59287,59288,59289,59290,59291,59292,59293,59294,59295,59142,59143,59144,59145,59146,59147,59148,59149,59150,59151,59152,59153,59154,59155,59156,59157,59158,59159,59160,59161,59162,59163,59164,59165,59166,59167,59168,59169,59170,59171,59172,59173,59174,59175,59176,59177,59178,59179,59180,59181,59182,59183,59184,59185,59186,59187,59188,59189,59190,59191,59192,59193,59194,59195,59196,59197,59198,59199,59200,59201,59202,59203,59204,59205,59206,59207,59208,59209,59210,59211,59212,59213,59214,59215,59216,59217,59218,59219,59220,59221,59222,59223,59224,59225,59226,59227,59228,59229,59230,59231,59232,59233,59234,59235,59236,59237,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,59296,59297,59298,59299,59300,59301,59302,59303,59304,59305,59306,59307,59308,59309,59310,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,59311,59312,59313,59314,59315,59316,59317,59318,59319,59320,59321,59322,59323,714,715,729,8211,8213,8229,8245,8453,8457,8598,8599,8600,8601,8725,8735,8739,8786,8806,8807,8895,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9601,9602,9603,9604,9605,9606,9607,9608,9609,9610,9611,9612,9613,9614,9615,9619,9620,9621,9660,9661,9698,9699,9700,9701,9737,8853,12306,12317,12318,59324,59325,59326,59327,59328,59329,59330,59331,59332,59333,59334,257,225,462,224,275,233,283,232,299,237,464,236,333,243,466,242,363,250,468,249,470,472,474,476,252,234,593,7743,324,328,505,609,59337,59338,59339,59340,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,59341,59342,59343,59344,59345,59346,59347,59348,59349,59350,59351,59352,59353,59354,59355,59356,59357,59358,59359,59360,59361,12321,12322,12323,12324,12325,12326,12327,12328,12329,12963,13198,13199,13212,13213,13214,13217,13252,13262,13265,13266,13269,65072,65506,65508,59362,8481,12849,59363,8208,59364,59365,59366,12540,12443,12444,12541,12542,12294,12445,12446,65097,65098,65099,65100,65101,65102,65103,65104,65105,65106,65108,65109,65110,65111,65113,65114,65115,65116,65117,65118,65119,65120,65121,65122,65123,65124,65125,65126,65128,65129,65130,65131,12350,12272,12273,12274,12275,12276,12277,12278,12279,12280,12281,12282,12283,12295,59380,59381,59382,59383,59384,59385,59386,59387,59388,59389,59390,59391,59392,9472,9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,59393,59394,59395,59396,59397,59398,59399,59400,59401,59402,59403,59404,59405,59406,59407,29404,29405,29407,29410,29411,29412,29413,29414,29415,29418,29419,29429,29430,29433,29437,29438,29439,29440,29442,29444,29445,29446,29447,29448,29449,29451,29452,29453,29455,29456,29457,29458,29460,29464,29465,29466,29471,29472,29475,29476,29478,29479,29480,29485,29487,29488,29490,29491,29493,29494,29498,29499,29500,29501,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29518,29519,29521,29523,29524,29525,29526,29528,29529,29530,29531,29532,29533,29534,29535,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29550,29552,29553,57344,57345,57346,57347,57348,57349,57350,57351,57352,57353,57354,57355,57356,57357,57358,57359,57360,57361,57362,57363,57364,57365,57366,57367,57368,57369,57370,57371,57372,57373,57374,57375,57376,57377,57378,57379,57380,57381,57382,57383,57384,57385,57386,57387,57388,57389,57390,57391,57392,57393,57394,57395,57396,57397,57398,57399,57400,57401,57402,57403,57404,57405,57406,57407,57408,57409,57410,57411,57412,57413,57414,57415,57416,57417,57418,57419,57420,57421,57422,57423,57424,57425,57426,57427,57428,57429,57430,57431,57432,57433,57434,57435,57436,57437,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29567,29568,29569,29570,29571,29573,29574,29576,29578,29580,29581,29583,29584,29586,29587,29588,29589,29591,29592,29593,29594,29596,29597,29598,29600,29601,29603,29604,29605,29606,29607,29608,29610,29612,29613,29617,29620,29621,29622,29624,29625,29628,29629,29630,29631,29633,29635,29636,29637,29638,29639,29643,29644,29646,29650,29651,29652,29653,29654,29655,29656,29658,29659,29660,29661,29663,29665,29666,29667,29668,29670,29672,29674,29675,29676,29678,29679,29680,29681,29683,29684,29685,29686,29687,57438,57439,57440,57441,57442,57443,57444,57445,57446,57447,57448,57449,57450,57451,57452,57453,57454,57455,57456,57457,57458,57459,57460,57461,57462,57463,57464,57465,57466,57467,57468,57469,57470,57471,57472,57473,57474,57475,57476,57477,57478,57479,57480,57481,57482,57483,57484,57485,57486,57487,57488,57489,57490,57491,57492,57493,57494,57495,57496,57497,57498,57499,57500,57501,57502,57503,57504,57505,57506,57507,57508,57509,57510,57511,57512,57513,57514,57515,57516,57517,57518,57519,57520,57521,57522,57523,57524,57525,57526,57527,57528,57529,57530,57531,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29700,29703,29704,29707,29708,29709,29710,29713,29714,29715,29716,29717,29718,29719,29720,29721,29724,29725,29726,29727,29728,29729,29731,29732,29735,29737,29739,29741,29743,29745,29746,29751,29752,29753,29754,29755,29757,29758,29759,29760,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29782,29784,29789,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29806,29807,29809,29810,29811,29812,29813,29816,29817,29818,57532,57533,57534,57535,57536,57537,57538,57539,57540,57541,57542,57543,57544,57545,57546,57547,57548,57549,57550,57551,57552,57553,57554,57555,57556,57557,57558,57559,57560,57561,57562,57563,57564,57565,57566,57567,57568,57569,57570,57571,57572,57573,57574,57575,57576,57577,57578,57579,57580,57581,57582,57583,57584,57585,57586,57587,57588,57589,57590,57591,57592,57593,57594,57595,57596,57597,57598,57599,57600,57601,57602,57603,57604,57605,57606,57607,57608,57609,57610,57611,57612,57613,57614,57615,57616,57617,57618,57619,57620,57621,57622,57623,57624,57625,29819,29820,29821,29823,29826,29828,29829,29830,29832,29833,29834,29836,29837,29839,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29853,29855,29856,29857,29858,29859,29860,29861,29862,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29907,29908,29909,29910,29911,29912,29913,29914,29915,29917,29919,29921,29925,29927,29928,29929,29930,29931,29932,29933,29936,29937,29938,57626,57627,57628,57629,57630,57631,57632,57633,57634,57635,57636,57637,57638,57639,57640,57641,57642,57643,57644,57645,57646,57647,57648,57649,57650,57651,57652,57653,57654,57655,57656,57657,57658,57659,57660,57661,57662,57663,57664,57665,57666,57667,57668,57669,57670,57671,57672,57673,57674,57675,57676,57677,57678,57679,57680,57681,57682,57683,57684,57685,57686,57687,57688,57689,57690,57691,57692,57693,57694,57695,57696,57697,57698,57699,57700,57701,57702,57703,57704,57705,57706,57707,57708,57709,57710,57711,57712,57713,57714,57715,57716,57717,57718,57719,29939,29941,29944,29945,29946,29947,29948,29949,29950,29952,29953,29954,29955,29957,29958,29959,29960,29961,29962,29963,29964,29966,29968,29970,29972,29973,29974,29975,29979,29981,29982,29984,29985,29986,29987,29988,29990,29991,29994,29998,30004,30006,30009,30012,30013,30015,30017,30018,30019,30020,30022,30023,30025,30026,30029,30032,30033,30034,30035,30037,30038,30039,30040,30045,30046,30047,30048,30049,30050,30051,30052,30055,30056,30057,30059,30060,30061,30062,30063,30064,30065,30067,30069,30070,30071,30074,30075,30076,30077,30078,30080,30081,30082,30084,30085,30087,57720,57721,57722,57723,57724,57725,57726,57727,57728,57729,57730,57731,57732,57733,57734,57735,57736,57737,57738,57739,57740,57741,57742,57743,57744,57745,57746,57747,57748,57749,57750,57751,57752,57753,57754,57755,57756,57757,57758,57759,57760,57761,57762,57763,57764,57765,57766,57767,57768,57769,57770,57771,57772,57773,57774,57775,57776,57777,57778,57779,57780,57781,57782,57783,57784,57785,57786,57787,57788,57789,57790,57791,57792,57793,57794,57795,57796,57797,57798,57799,57800,57801,57802,57803,57804,57805,57806,57807,57808,57809,57810,57811,57812,57813,30088,30089,30090,30092,30093,30094,30096,30099,30101,30104,30107,30108,30110,30114,30118,30119,30120,30121,30122,30125,30134,30135,30138,30139,30143,30144,30145,30150,30155,30156,30158,30159,30160,30161,30163,30167,30169,30170,30172,30173,30175,30176,30177,30181,30185,30188,30189,30190,30191,30194,30195,30197,30198,30199,30200,30202,30203,30205,30206,30210,30212,30214,30215,30216,30217,30219,30221,30222,30223,30225,30226,30227,30228,30230,30234,30236,30237,30238,30241,30243,30247,30248,30252,30254,30255,30257,30258,30262,30263,30265,30266,30267,30269,30273,30274,30276,57814,57815,57816,57817,57818,57819,57820,57821,57822,57823,57824,57825,57826,57827,57828,57829,57830,57831,57832,57833,57834,57835,57836,57837,57838,57839,57840,57841,57842,57843,57844,57845,57846,57847,57848,57849,57850,57851,57852,57853,57854,57855,57856,57857,57858,57859,57860,57861,57862,57863,57864,57865,57866,57867,57868,57869,57870,57871,57872,57873,57874,57875,57876,57877,57878,57879,57880,57881,57882,57883,57884,57885,57886,57887,57888,57889,57890,57891,57892,57893,57894,57895,57896,57897,57898,57899,57900,57901,57902,57903,57904,57905,57906,57907,30277,30278,30279,30280,30281,30282,30283,30286,30287,30288,30289,30290,30291,30293,30295,30296,30297,30298,30299,30301,30303,30304,30305,30306,30308,30309,30310,30311,30312,30313,30314,30316,30317,30318,30320,30321,30322,30323,30324,30325,30326,30327,30329,30330,30332,30335,30336,30337,30339,30341,30345,30346,30348,30349,30351,30352,30354,30356,30357,30359,30360,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30373,30374,30375,30376,30377,30378,30379,30380,30381,30383,30384,30387,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30400,30401,30403,21834,38463,22467,25384,21710,21769,21696,30353,30284,34108,30702,33406,30861,29233,38552,38797,27688,23433,20474,25353,26263,23736,33018,26696,32942,26114,30414,20985,25942,29100,32753,34948,20658,22885,25034,28595,33453,25420,25170,21485,21543,31494,20843,30116,24052,25300,36299,38774,25226,32793,22365,38712,32610,29240,30333,26575,30334,25670,20336,36133,25308,31255,26001,29677,25644,25203,33324,39041,26495,29256,25198,25292,20276,29923,21322,21150,32458,37030,24110,26758,27036,33152,32465,26834,30917,34444,38225,20621,35876,33502,32990,21253,35090,21093,30404,30407,30409,30411,30412,30419,30421,30425,30426,30428,30429,30430,30432,30433,30434,30435,30436,30438,30439,30440,30441,30442,30443,30444,30445,30448,30451,30453,30454,30455,30458,30459,30461,30463,30464,30466,30467,30469,30470,30474,30476,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30491,30492,30493,30494,30497,30499,30500,30501,30503,30506,30507,30508,30510,30512,30513,30514,30515,30516,30521,30523,30525,30526,30527,30530,30532,30533,30534,30536,30537,30538,30539,30540,30541,30542,30543,30546,30547,30548,30549,30550,30551,30552,30553,30556,34180,38649,20445,22561,39281,23453,25265,25253,26292,35961,40077,29190,26479,30865,24754,21329,21271,36744,32972,36125,38049,20493,29384,22791,24811,28953,34987,22868,33519,26412,31528,23849,32503,29997,27893,36454,36856,36924,40763,27604,37145,31508,24444,30887,34006,34109,27605,27609,27606,24065,24199,30201,38381,25949,24330,24517,36767,22721,33218,36991,38491,38829,36793,32534,36140,25153,20415,21464,21342,36776,36777,36779,36941,26631,24426,33176,34920,40150,24971,21035,30250,24428,25996,28626,28392,23486,25672,20853,20912,26564,19993,31177,39292,28851,30557,30558,30559,30560,30564,30567,30569,30570,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30586,30587,30588,30593,30594,30595,30598,30599,30600,30601,30602,30603,30607,30608,30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,30625,30627,30628,30630,30632,30635,30637,30638,30639,30641,30642,30644,30646,30647,30648,30649,30650,30652,30654,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30670,30671,30672,30673,30674,30675,30676,30677,30678,30680,30681,30682,30685,30686,30687,30688,30689,30692,30149,24182,29627,33760,25773,25320,38069,27874,21338,21187,25615,38082,31636,20271,24091,33334,33046,33162,28196,27850,39539,25429,21340,21754,34917,22496,19981,24067,27493,31807,37096,24598,25830,29468,35009,26448,25165,36130,30572,36393,37319,24425,33756,34081,39184,21442,34453,27531,24813,24808,28799,33485,33329,20179,27815,34255,25805,31961,27133,26361,33609,21397,31574,20391,20876,27979,23618,36461,25554,21449,33580,33590,26597,30900,25661,23519,23700,24046,35815,25286,26612,35962,25600,25530,34633,39307,35863,32544,38130,20135,38416,39076,26124,29462,30694,30696,30698,30703,30704,30705,30706,30708,30709,30711,30713,30714,30715,30716,30723,30724,30725,30726,30727,30728,30730,30731,30734,30735,30736,30739,30741,30745,30747,30750,30752,30753,30754,30756,30760,30762,30763,30766,30767,30769,30770,30771,30773,30774,30781,30783,30785,30786,30787,30788,30790,30792,30793,30794,30795,30797,30799,30801,30803,30804,30808,30809,30810,30811,30812,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30831,30832,30833,30834,30835,30836,30837,30838,30840,30841,30842,30843,30845,30846,30847,30848,30849,30850,30851,22330,23581,24120,38271,20607,32928,21378,25950,30021,21809,20513,36229,25220,38046,26397,22066,28526,24034,21557,28818,36710,25199,25764,25507,24443,28552,37108,33251,36784,23576,26216,24561,27785,38472,36225,34924,25745,31216,22478,27225,25104,21576,20056,31243,24809,28548,35802,25215,36894,39563,31204,21507,30196,25345,21273,27744,36831,24347,39536,32827,40831,20360,23610,36196,32709,26021,28861,20805,20914,34411,23815,23456,25277,37228,30068,36364,31264,24833,31609,20167,32504,30597,19985,33261,21021,20986,27249,21416,36487,38148,38607,28353,38500,26970,30852,30853,30854,30856,30858,30859,30863,30864,30866,30868,30869,30870,30873,30877,30878,30880,30882,30884,30886,30888,30889,30890,30891,30892,30893,30894,30895,30901,30902,30903,30904,30906,30907,30908,30909,30911,30912,30914,30915,30916,30918,30919,30920,30924,30925,30926,30927,30929,30930,30931,30934,30935,30936,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,30948,30949,30950,30951,30953,30954,30955,30957,30958,30959,30960,30961,30963,30965,30966,30968,30969,30971,30972,30973,30974,30975,30976,30978,30979,30980,30982,30983,30984,30985,30986,30987,30988,30784,20648,30679,25616,35302,22788,25571,24029,31359,26941,20256,33337,21912,20018,30126,31383,24162,24202,38383,21019,21561,28810,25462,38180,22402,26149,26943,37255,21767,28147,32431,34850,25139,32496,30133,33576,30913,38604,36766,24904,29943,35789,27492,21050,36176,27425,32874,33905,22257,21254,20174,19995,20945,31895,37259,31751,20419,36479,31713,31388,25703,23828,20652,33030,30209,31929,28140,32736,26449,23384,23544,30923,25774,25619,25514,25387,38169,25645,36798,31572,30249,25171,22823,21574,27513,20643,25140,24102,27526,20195,36151,34955,24453,36910,30989,30990,30991,30992,30993,30994,30996,30997,30998,30999,31e3,31001,31002,31003,31004,31005,31007,31008,31009,31010,31011,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31029,31030,31031,31032,31033,31037,31039,31042,31043,31044,31045,31047,31050,31051,31052,31053,31054,31055,31056,31057,31058,31060,31061,31064,31065,31073,31075,31076,31078,31081,31082,31083,31084,31086,31088,31089,31090,31091,31092,31093,31094,31097,31099,31100,31101,31102,31103,31106,31107,31110,31111,31112,31113,31115,31116,31117,31118,31120,31121,31122,24608,32829,25285,20025,21333,37112,25528,32966,26086,27694,20294,24814,28129,35806,24377,34507,24403,25377,20826,33633,26723,20992,25443,36424,20498,23707,31095,23548,21040,31291,24764,36947,30423,24503,24471,30340,36460,28783,30331,31561,30634,20979,37011,22564,20302,28404,36842,25932,31515,29380,28068,32735,23265,25269,24213,22320,33922,31532,24093,24351,36882,32532,39072,25474,28359,30872,28857,20856,38747,22443,30005,20291,30008,24215,24806,22880,28096,27583,30857,21500,38613,20939,20993,25481,21514,38035,35843,36300,29241,30879,34678,36845,35853,21472,31123,31124,31125,31126,31127,31128,31129,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31156,31157,31158,31159,31160,31164,31167,31170,31172,31173,31175,31176,31178,31180,31182,31183,31184,31187,31188,31190,31191,31193,31194,31195,31196,31197,31198,31200,31201,31202,31205,31208,31210,31212,31214,31217,31218,31219,31220,31221,31222,31223,31225,31226,31228,31230,31231,31233,31236,31237,31239,31240,31241,31242,31244,31247,31248,31249,31250,31251,31253,31254,31256,31257,31259,31260,19969,30447,21486,38025,39030,40718,38189,23450,35746,20002,19996,20908,33891,25026,21160,26635,20375,24683,20923,27934,20828,25238,26007,38497,35910,36887,30168,37117,30563,27602,29322,29420,35835,22581,30585,36172,26460,38208,32922,24230,28193,22930,31471,30701,38203,27573,26029,32526,22534,20817,38431,23545,22697,21544,36466,25958,39039,22244,38045,30462,36929,25479,21702,22810,22842,22427,36530,26421,36346,33333,21057,24816,22549,34558,23784,40517,20420,39069,35769,23077,24694,21380,25212,36943,37122,39295,24681,32780,20799,32819,23572,39285,27953,20108,31261,31263,31265,31266,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,31284,31285,31286,31288,31290,31294,31296,31297,31298,31299,31300,31301,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31314,31315,31316,31317,31318,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31345,31346,31347,31349,31355,31356,31357,31358,31362,31365,31367,31369,31370,31371,31372,31374,31375,31376,31379,31380,31385,31386,31387,31390,31393,31394,36144,21457,32602,31567,20240,20047,38400,27861,29648,34281,24070,30058,32763,27146,30718,38034,32321,20961,28902,21453,36820,33539,36137,29359,39277,27867,22346,33459,26041,32938,25151,38450,22952,20223,35775,32442,25918,33778,38750,21857,39134,32933,21290,35837,21536,32954,24223,27832,36153,33452,37210,21545,27675,20998,32439,22367,28954,27774,31881,22859,20221,24575,24868,31914,20016,23553,26539,34562,23792,38155,39118,30127,28925,36898,20911,32541,35773,22857,20964,20315,21542,22827,25975,32932,23413,25206,25282,36752,24133,27679,31526,20239,20440,26381,31395,31396,31399,31401,31402,31403,31406,31407,31408,31409,31410,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,31447,31448,31450,31451,31452,31453,31457,31458,31460,31463,31464,31465,31466,31467,31468,31470,31472,31473,31474,31475,31476,31477,31478,31479,31480,31483,31484,31486,31488,31489,31490,31493,31495,31497,31500,31501,31502,31504,31506,31507,31510,31511,31512,31514,31516,31517,31519,31521,31522,31523,31527,31529,31533,28014,28074,31119,34993,24343,29995,25242,36741,20463,37340,26023,33071,33105,24220,33104,36212,21103,35206,36171,22797,20613,20184,38428,29238,33145,36127,23500,35747,38468,22919,32538,21648,22134,22030,35813,25913,27010,38041,30422,28297,24178,29976,26438,26577,31487,32925,36214,24863,31174,25954,36195,20872,21018,38050,32568,32923,32434,23703,28207,26464,31705,30347,39640,33167,32660,31957,25630,38224,31295,21578,21733,27468,25601,25096,40509,33011,30105,21106,38761,33883,26684,34532,38401,38548,38124,20010,21508,32473,26681,36319,32789,26356,24218,32697,31535,31536,31538,31540,31541,31542,31543,31545,31547,31549,31551,31552,31553,31554,31555,31556,31558,31560,31562,31565,31566,31571,31573,31575,31577,31580,31582,31583,31585,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31599,31600,31603,31604,31606,31608,31610,31612,31613,31615,31617,31618,31619,31620,31622,31623,31624,31625,31626,31627,31628,31630,31631,31633,31634,31635,31638,31640,31641,31642,31643,31646,31647,31648,31651,31652,31653,31662,31663,31664,31666,31667,31669,31670,31671,31673,31674,31675,31676,31677,31678,31679,31680,31682,31683,31684,22466,32831,26775,24037,25915,21151,24685,40858,20379,36524,20844,23467,24339,24041,27742,25329,36129,20849,38057,21246,27807,33503,29399,22434,26500,36141,22815,36764,33735,21653,31629,20272,27837,23396,22993,40723,21476,34506,39592,35895,32929,25925,39038,22266,38599,21038,29916,21072,23521,25346,35074,20054,25296,24618,26874,20851,23448,20896,35266,31649,39302,32592,24815,28748,36143,20809,24191,36891,29808,35268,22317,30789,24402,40863,38394,36712,39740,35809,30328,26690,26588,36330,36149,21053,36746,28378,26829,38149,37101,22269,26524,35065,36807,21704,31685,31688,31689,31690,31691,31693,31694,31695,31696,31698,31700,31701,31702,31703,31704,31707,31708,31710,31711,31712,31714,31715,31716,31719,31720,31721,31723,31724,31725,31727,31728,31730,31731,31732,31733,31734,31736,31737,31738,31739,31741,31743,31744,31745,31746,31747,31748,31749,31750,31752,31753,31754,31757,31758,31760,31761,31762,31763,31764,31765,31767,31768,31769,31770,31771,31772,31773,31774,31776,31777,31778,31779,31780,31781,31784,31785,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31801,31802,31803,31804,31805,31806,31810,39608,23401,28023,27686,20133,23475,39559,37219,25e3,37039,38889,21547,28085,23506,20989,21898,32597,32752,25788,25421,26097,25022,24717,28938,27735,27721,22831,26477,33322,22741,22158,35946,27627,37085,22909,32791,21495,28009,21621,21917,33655,33743,26680,31166,21644,20309,21512,30418,35977,38402,27827,28088,36203,35088,40548,36154,22079,40657,30165,24456,29408,24680,21756,20136,27178,34913,24658,36720,21700,28888,34425,40511,27946,23439,24344,32418,21897,20399,29492,21564,21402,20505,21518,21628,20046,24573,29786,22774,33899,32993,34676,29392,31946,28246,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31861,31862,31863,31864,31865,31866,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31882,31883,31884,31885,31886,31887,31888,31891,31892,31894,31897,31898,31899,31904,31905,31907,31910,31911,31912,31913,31915,31916,31917,31919,31920,31924,31925,31926,31927,31928,31930,31931,24359,34382,21804,25252,20114,27818,25143,33457,21719,21326,29502,28369,30011,21010,21270,35805,27088,24458,24576,28142,22351,27426,29615,26707,36824,32531,25442,24739,21796,30186,35938,28949,28067,23462,24187,33618,24908,40644,30970,34647,31783,30343,20976,24822,29004,26179,24140,24653,35854,28784,25381,36745,24509,24674,34516,22238,27585,24724,24935,21321,24800,26214,36159,31229,20250,28905,27719,35763,35826,32472,33636,26127,23130,39746,27985,28151,35905,27963,20249,28779,33719,25110,24785,38669,36135,31096,20987,22334,22522,26426,30072,31293,31215,31637,31935,31936,31938,31939,31940,31942,31945,31947,31950,31951,31952,31953,31954,31955,31956,31960,31962,31963,31965,31966,31969,31970,31971,31972,31973,31974,31975,31977,31978,31979,31980,31981,31982,31984,31985,31986,31987,31988,31989,31990,31991,31993,31994,31996,31997,31998,31999,32e3,32001,32002,32003,32004,32005,32006,32007,32008,32009,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32033,32035,32036,32037,32038,32040,32041,32042,32044,32045,32046,32048,32049,32050,32051,32052,32053,32054,32908,39269,36857,28608,35749,40481,23020,32489,32521,21513,26497,26840,36753,31821,38598,21450,24613,30142,27762,21363,23241,32423,25380,20960,33034,24049,34015,25216,20864,23395,20238,31085,21058,24760,27982,23492,23490,35745,35760,26082,24524,38469,22931,32487,32426,22025,26551,22841,20339,23478,21152,33626,39050,36158,30002,38078,20551,31292,20215,26550,39550,23233,27516,30417,22362,23574,31546,38388,29006,20860,32937,33392,22904,32516,33575,26816,26604,30897,30839,25315,25441,31616,20461,21098,20943,33616,27099,37492,36341,36145,35265,38190,31661,20214,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32111,32112,32113,32114,32115,32116,32117,32118,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,20581,33328,21073,39279,28176,28293,28071,24314,20725,23004,23558,27974,27743,30086,33931,26728,22870,35762,21280,37233,38477,34121,26898,30977,28966,33014,20132,37066,27975,39556,23047,22204,25605,38128,30699,20389,33050,29409,35282,39290,32564,32478,21119,25945,37237,36735,36739,21483,31382,25581,25509,30342,31224,34903,38454,25130,21163,33410,26708,26480,25463,30571,31469,27905,32467,35299,22992,25106,34249,33445,30028,20511,20171,30117,35819,23626,24062,31563,26020,37329,20170,27941,35167,32039,38182,20165,35880,36827,38771,26187,31105,36817,28908,28024,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32167,32168,32169,32170,32171,32172,32173,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,23613,21170,33606,20834,33550,30555,26230,40120,20140,24778,31934,31923,32463,20117,35686,26223,39048,38745,22659,25964,38236,24452,30153,38742,31455,31454,20928,28847,31384,25578,31350,32416,29590,38893,20037,28792,20061,37202,21417,25937,26087,33276,33285,21646,23601,30106,38816,25304,29401,30141,23621,39545,33738,23616,21632,30697,20030,27822,32858,25298,25454,24040,20855,36317,36382,38191,20465,21477,24807,28844,21095,25424,40515,23071,20518,30519,21367,32482,25733,25899,25225,25496,20500,29237,35273,20915,35776,32477,22343,33740,38055,20891,21531,23803,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32316,32317,32318,32319,32320,32322,32323,32324,32325,32326,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,20426,31459,27994,37089,39567,21888,21654,21345,21679,24320,25577,26999,20975,24936,21002,22570,21208,22350,30733,30475,24247,24951,31968,25179,25239,20130,28821,32771,25335,28900,38752,22391,33499,26607,26869,30933,39063,31185,22771,21683,21487,28212,20811,21051,23458,35838,32943,21827,22438,24691,22353,21549,31354,24656,23380,25511,25248,21475,25187,23495,26543,21741,31391,33510,37239,24211,35044,22840,22446,25358,36328,33007,22359,31607,20393,24555,23485,27454,21281,31568,29378,26694,30719,30518,26103,20917,20111,30420,23743,31397,33909,22862,39745,20608,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32412,32413,32414,32430,32436,32443,32444,32470,32484,32492,32505,32522,32528,32542,32567,32569,32571,32572,32573,32574,32575,32576,32577,32579,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32594,32595,39304,24871,28291,22372,26118,25414,22256,25324,25193,24275,38420,22403,25289,21895,34593,33098,36771,21862,33713,26469,36182,34013,23146,26639,25318,31726,38417,20848,28572,35888,25597,35272,25042,32518,28866,28389,29701,27028,29436,24266,37070,26391,28010,25438,21171,29282,32769,20332,23013,37226,28889,28061,21202,20048,38647,38253,34174,30922,32047,20769,22418,25794,32907,31867,27882,26865,26974,20919,21400,26792,29313,40654,31729,29432,31163,28435,29702,26446,37324,40100,31036,33673,33620,21519,26647,20029,21385,21169,30782,21382,21033,20616,20363,20432,32598,32601,32603,32604,32605,32606,32608,32611,32612,32613,32614,32615,32619,32620,32621,32623,32624,32627,32629,32630,32631,32632,32634,32635,32636,32637,32639,32640,32642,32643,32644,32645,32646,32647,32648,32649,32651,32653,32655,32656,32657,32658,32659,32661,32662,32663,32664,32665,32667,32668,32672,32674,32675,32677,32678,32680,32681,32682,32683,32684,32685,32686,32689,32691,32692,32693,32694,32695,32698,32699,32702,32704,32706,32707,32708,32710,32711,32712,32713,32715,32717,32719,32720,32721,32722,32723,32726,32727,32729,32730,32731,32732,32733,32734,32738,32739,30178,31435,31890,27813,38582,21147,29827,21737,20457,32852,33714,36830,38256,24265,24604,28063,24088,25947,33080,38142,24651,28860,32451,31918,20937,26753,31921,33391,20004,36742,37327,26238,20142,35845,25769,32842,20698,30103,29134,23525,36797,28518,20102,25730,38243,24278,26009,21015,35010,28872,21155,29454,29747,26519,30967,38678,20020,37051,40158,28107,20955,36161,21533,25294,29618,33777,38646,40836,38083,20278,32666,20940,28789,38517,23725,39046,21478,20196,28316,29705,27060,30827,39311,30041,21016,30244,27969,26611,20845,40857,32843,21657,31548,31423,32740,32743,32744,32746,32747,32748,32749,32751,32754,32756,32757,32758,32759,32760,32761,32762,32765,32766,32767,32770,32775,32776,32777,32778,32782,32783,32785,32787,32794,32795,32797,32798,32799,32801,32803,32804,32811,32812,32813,32814,32815,32816,32818,32820,32825,32826,32828,32830,32832,32833,32836,32837,32839,32840,32841,32846,32847,32848,32849,32851,32853,32854,32855,32857,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32875,32876,32877,32878,32879,32880,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,38534,22404,25314,38471,27004,23044,25602,31699,28431,38475,33446,21346,39045,24208,28809,25523,21348,34383,40065,40595,30860,38706,36335,36162,40575,28510,31108,24405,38470,25134,39540,21525,38109,20387,26053,23653,23649,32533,34385,27695,24459,29575,28388,32511,23782,25371,23402,28390,21365,20081,25504,30053,25249,36718,20262,20177,27814,32438,35770,33821,34746,32599,36923,38179,31657,39585,35064,33853,27931,39558,32476,22920,40635,29595,30721,34434,39532,39554,22043,21527,22475,20080,40614,21334,36808,33033,30610,39314,34542,28385,34067,26364,24930,28459,32894,32897,32898,32901,32904,32906,32909,32910,32911,32912,32913,32914,32916,32917,32919,32921,32926,32931,32934,32935,32936,32940,32944,32947,32949,32950,32952,32953,32955,32965,32967,32968,32969,32970,32971,32975,32976,32977,32978,32979,32980,32981,32984,32991,32992,32994,32995,32998,33006,33013,33015,33017,33019,33022,33023,33024,33025,33027,33028,33029,33031,33032,33035,33036,33045,33047,33049,33051,33052,33053,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33069,33070,33072,33075,33076,33077,33079,33081,33082,33083,33084,33085,33087,35881,33426,33579,30450,27667,24537,33725,29483,33541,38170,27611,30683,38086,21359,33538,20882,24125,35980,36152,20040,29611,26522,26757,37238,38665,29028,27809,30473,23186,38209,27599,32654,26151,23504,22969,23194,38376,38391,20204,33804,33945,27308,30431,38192,29467,26790,23391,30511,37274,38753,31964,36855,35868,24357,31859,31192,35269,27852,34588,23494,24130,26825,30496,32501,20885,20813,21193,23081,32517,38754,33495,25551,30596,34256,31186,28218,24217,22937,34065,28781,27665,25279,30399,25935,24751,38397,26126,34719,40483,38125,21517,21629,35884,25720,33088,33089,33090,33091,33092,33093,33095,33097,33101,33102,33103,33106,33110,33111,33112,33115,33116,33117,33118,33119,33121,33122,33123,33124,33126,33128,33130,33131,33132,33135,33138,33139,33141,33142,33143,33144,33153,33155,33156,33157,33158,33159,33161,33163,33164,33165,33166,33168,33170,33171,33172,33173,33174,33175,33177,33178,33182,33183,33184,33185,33186,33188,33189,33191,33193,33195,33196,33197,33198,33199,33200,33201,33202,33204,33205,33206,33207,33208,33209,33212,33213,33214,33215,33220,33221,33223,33224,33225,33227,33229,33230,33231,33232,33233,33234,33235,25721,34321,27169,33180,30952,25705,39764,25273,26411,33707,22696,40664,27819,28448,23518,38476,35851,29279,26576,25287,29281,20137,22982,27597,22675,26286,24149,21215,24917,26408,30446,30566,29287,31302,25343,21738,21584,38048,37027,23068,32435,27670,20035,22902,32784,22856,21335,30007,38590,22218,25376,33041,24700,38393,28118,21602,39297,20869,23273,33021,22958,38675,20522,27877,23612,25311,20320,21311,33147,36870,28346,34091,25288,24180,30910,25781,25467,24565,23064,37247,40479,23615,25423,32834,23421,21870,38218,38221,28037,24744,26592,29406,20957,23425,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33252,33253,33254,33256,33257,33259,33262,33263,33264,33265,33266,33269,33270,33271,33272,33273,33274,33277,33279,33283,33287,33288,33289,33290,33291,33294,33295,33297,33299,33301,33302,33303,33304,33305,33306,33309,33312,33316,33317,33318,33319,33321,33326,33330,33338,33340,33341,33343,33344,33345,33346,33347,33349,33350,33352,33354,33356,33357,33358,33360,33361,33362,33363,33364,33365,33366,33367,33369,33371,33372,33373,33374,33376,33377,33378,33379,33380,33381,33382,33383,33385,25319,27870,29275,25197,38062,32445,33043,27987,20892,24324,22900,21162,24594,22899,26262,34384,30111,25386,25062,31983,35834,21734,27431,40485,27572,34261,21589,20598,27812,21866,36276,29228,24085,24597,29750,25293,25490,29260,24472,28227,27966,25856,28504,30424,30928,30460,30036,21028,21467,20051,24222,26049,32810,32982,25243,21638,21032,28846,34957,36305,27873,21624,32986,22521,35060,36180,38506,37197,20329,27803,21943,30406,30768,25256,28921,28558,24429,34028,26842,30844,31735,33192,26379,40527,25447,30896,22383,30738,38713,25209,25259,21128,29749,27607,33386,33387,33388,33389,33393,33397,33398,33399,33400,33403,33404,33408,33409,33411,33413,33414,33415,33417,33420,33424,33427,33428,33429,33430,33434,33435,33438,33440,33442,33443,33447,33458,33461,33462,33466,33467,33468,33471,33472,33474,33475,33477,33478,33481,33488,33494,33497,33498,33501,33506,33511,33512,33513,33514,33516,33517,33518,33520,33522,33523,33525,33526,33528,33530,33532,33533,33534,33535,33536,33546,33547,33549,33552,33554,33555,33558,33560,33561,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33577,33578,33582,33584,33586,33591,33595,33597,21860,33086,30130,30382,21305,30174,20731,23617,35692,31687,20559,29255,39575,39128,28418,29922,31080,25735,30629,25340,39057,36139,21697,32856,20050,22378,33529,33805,24179,20973,29942,35780,23631,22369,27900,39047,23110,30772,39748,36843,31893,21078,25169,38138,20166,33670,33889,33769,33970,22484,26420,22275,26222,28006,35889,26333,28689,26399,27450,26646,25114,22971,19971,20932,28422,26578,27791,20854,26827,22855,27495,30054,23822,33040,40784,26071,31048,31041,39569,36215,23682,20062,20225,21551,22865,30732,22120,27668,36804,24323,27773,27875,35755,25488,33598,33599,33601,33602,33604,33605,33608,33610,33611,33612,33613,33614,33619,33621,33622,33623,33624,33625,33629,33634,33648,33649,33650,33651,33652,33653,33654,33657,33658,33662,33663,33664,33665,33666,33667,33668,33671,33672,33674,33675,33676,33677,33679,33680,33681,33684,33685,33686,33687,33689,33690,33693,33695,33697,33698,33699,33700,33701,33702,33703,33708,33709,33710,33711,33717,33723,33726,33727,33730,33731,33732,33734,33736,33737,33739,33741,33742,33744,33745,33746,33747,33749,33751,33753,33754,33755,33758,33762,33763,33764,33766,33767,33768,33771,33772,33773,24688,27965,29301,25190,38030,38085,21315,36801,31614,20191,35878,20094,40660,38065,38067,21069,28508,36963,27973,35892,22545,23884,27424,27465,26538,21595,33108,32652,22681,34103,24378,25250,27207,38201,25970,24708,26725,30631,20052,20392,24039,38808,25772,32728,23789,20431,31373,20999,33540,19988,24623,31363,38054,20405,20146,31206,29748,21220,33465,25810,31165,23517,27777,38738,36731,27682,20542,21375,28165,25806,26228,27696,24773,39031,35831,24198,29756,31351,31179,19992,37041,29699,27714,22234,37195,27845,36235,21306,34502,26354,36527,23624,39537,28192,33774,33775,33779,33780,33781,33782,33783,33786,33787,33788,33790,33791,33792,33794,33797,33799,33800,33801,33802,33808,33810,33811,33812,33813,33814,33815,33817,33818,33819,33822,33823,33824,33825,33826,33827,33833,33834,33835,33836,33837,33838,33839,33840,33842,33843,33844,33845,33846,33847,33849,33850,33851,33854,33855,33856,33857,33858,33859,33860,33861,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33874,33875,33876,33877,33878,33880,33885,33886,33887,33888,33890,33892,33893,33894,33895,33896,33898,33902,33903,33904,33906,33908,33911,33913,33915,33916,21462,23094,40843,36259,21435,22280,39079,26435,37275,27849,20840,30154,25331,29356,21048,21149,32570,28820,30264,21364,40522,27063,30830,38592,35033,32676,28982,29123,20873,26579,29924,22756,25880,22199,35753,39286,25200,32469,24825,28909,22764,20161,20154,24525,38887,20219,35748,20995,22922,32427,25172,20173,26085,25102,33592,33993,33635,34701,29076,28342,23481,32466,20887,25545,26580,32905,33593,34837,20754,23418,22914,36785,20083,27741,20837,35109,36719,38446,34122,29790,38160,38384,28070,33509,24369,25746,27922,33832,33134,40131,22622,36187,19977,21441,33917,33918,33919,33920,33921,33923,33924,33925,33926,33930,33933,33935,33936,33937,33938,33939,33940,33941,33942,33944,33946,33947,33949,33950,33951,33952,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33968,33969,33971,33973,33974,33975,33979,33980,33982,33984,33986,33987,33989,33990,33991,33992,33995,33996,33998,33999,34002,34004,34005,34007,34008,34009,34010,34011,34012,34014,34017,34018,34020,34023,34024,34025,34026,34027,34029,34030,34031,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34045,34046,34048,34049,34050,20254,25955,26705,21971,20007,25620,39578,25195,23234,29791,33394,28073,26862,20711,33678,30722,26432,21049,27801,32433,20667,21861,29022,31579,26194,29642,33515,26441,23665,21024,29053,34923,38378,38485,25797,36193,33203,21892,27733,25159,32558,22674,20260,21830,36175,26188,19978,23578,35059,26786,25422,31245,28903,33421,21242,38902,23569,21736,37045,32461,22882,36170,34503,33292,33293,36198,25668,23556,24913,28041,31038,35774,30775,30003,21627,20280,36523,28145,23072,32453,31070,27784,23457,23158,29978,32958,24910,28183,22768,29983,29989,29298,21319,32499,34051,34052,34053,34054,34055,34056,34057,34058,34059,34061,34062,34063,34064,34066,34068,34069,34070,34072,34073,34075,34076,34077,34078,34080,34082,34083,34084,34085,34086,34087,34088,34089,34090,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34110,34111,34112,34113,34114,34116,34117,34118,34119,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34135,34136,34138,34139,34140,34141,34143,34144,34145,34146,34147,34149,34150,34151,34153,34154,34155,34156,34157,34158,34159,34160,34161,34163,34165,34166,34167,34168,34172,34173,34175,34176,34177,30465,30427,21097,32988,22307,24072,22833,29422,26045,28287,35799,23608,34417,21313,30707,25342,26102,20160,39135,34432,23454,35782,21490,30690,20351,23630,39542,22987,24335,31034,22763,19990,26623,20107,25325,35475,36893,21183,26159,21980,22124,36866,20181,20365,37322,39280,27663,24066,24643,23460,35270,35797,25910,25163,39318,23432,23551,25480,21806,21463,30246,20861,34092,26530,26803,27530,25234,36755,21460,33298,28113,30095,20070,36174,23408,29087,34223,26257,26329,32626,34560,40653,40736,23646,26415,36848,26641,26463,25101,31446,22661,24246,25968,28465,34178,34179,34182,34184,34185,34186,34187,34188,34189,34190,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34205,34206,34207,34208,34209,34210,34211,34213,34214,34215,34217,34219,34220,34221,34225,34226,34227,34228,34229,34230,34232,34234,34235,34236,34237,34238,34239,34240,34242,34243,34244,34245,34246,34247,34248,34250,34251,34252,34253,34254,34257,34258,34260,34262,34263,34264,34265,34266,34267,34269,34270,34271,34272,34273,34274,34275,34277,34278,34279,34280,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,24661,21047,32781,25684,34928,29993,24069,26643,25332,38684,21452,29245,35841,27700,30561,31246,21550,30636,39034,33308,35828,30805,26388,28865,26031,25749,22070,24605,31169,21496,19997,27515,32902,23546,21987,22235,20282,20284,39282,24051,26494,32824,24578,39042,36865,23435,35772,35829,25628,33368,25822,22013,33487,37221,20439,32032,36895,31903,20723,22609,28335,23487,35785,32899,37240,33948,31639,34429,38539,38543,32485,39635,30862,23681,31319,36930,38567,31071,23385,25439,31499,34001,26797,21766,32553,29712,32034,38145,25152,22604,20182,23427,22905,22612,34297,34298,34300,34301,34302,34304,34305,34306,34307,34308,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34322,34323,34324,34325,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34344,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34361,34362,34363,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34386,34387,34389,34390,34391,34392,34393,34395,34396,34397,34399,34400,34401,34403,34404,34405,34406,34407,34408,34409,34410,29549,25374,36427,36367,32974,33492,25260,21488,27888,37214,22826,24577,27760,22349,25674,36138,30251,28393,22363,27264,30192,28525,35885,35848,22374,27631,34962,30899,25506,21497,28845,27748,22616,25642,22530,26848,33179,21776,31958,20504,36538,28108,36255,28907,25487,28059,28372,32486,33796,26691,36867,28120,38518,35752,22871,29305,34276,33150,30140,35466,26799,21076,36386,38161,25552,39064,36420,21884,20307,26367,22159,24789,28053,21059,23625,22825,28155,22635,3e4,29980,24684,33300,33094,25361,26465,36834,30522,36339,36148,38081,24086,21381,21548,28867,34413,34415,34416,34418,34419,34420,34421,34422,34423,34424,34435,34436,34437,34438,34439,34440,34441,34446,34447,34448,34449,34450,34452,34454,34455,34456,34457,34458,34459,34462,34463,34464,34465,34466,34469,34470,34475,34477,34478,34482,34483,34487,34488,34489,34491,34492,34493,34494,34495,34497,34498,34499,34501,34504,34508,34509,34514,34515,34517,34518,34519,34522,34524,34525,34528,34529,34530,34531,34533,34534,34535,34536,34538,34539,34540,34543,34549,34550,34551,34554,34555,34556,34557,34559,34561,34564,34565,34566,34571,34572,34574,34575,34576,34577,34580,34582,27712,24311,20572,20141,24237,25402,33351,36890,26704,37230,30643,21516,38108,24420,31461,26742,25413,31570,32479,30171,20599,25237,22836,36879,20984,31171,31361,22270,24466,36884,28034,23648,22303,21520,20820,28237,22242,25512,39059,33151,34581,35114,36864,21534,23663,33216,25302,25176,33073,40501,38464,39534,39548,26925,22949,25299,21822,25366,21703,34521,27964,23043,29926,34972,27498,22806,35916,24367,28286,29609,39037,20024,28919,23436,30871,25405,26202,30358,24779,23451,23113,19975,33109,27754,29579,20129,26505,32593,24448,26106,26395,24536,22916,23041,34585,34587,34589,34591,34592,34596,34598,34599,34600,34602,34603,34604,34605,34607,34608,34610,34611,34613,34614,34616,34617,34618,34620,34621,34624,34625,34626,34627,34628,34629,34630,34634,34635,34637,34639,34640,34641,34642,34644,34645,34646,34648,34650,34651,34652,34653,34654,34655,34657,34658,34662,34663,34664,34665,34666,34667,34668,34669,34671,34673,34674,34675,34677,34679,34680,34681,34682,34687,34688,34689,34692,34694,34695,34697,34698,34700,34702,34703,34704,34705,34706,34708,34709,34710,34712,34713,34714,34715,34716,34717,34718,34720,34721,34722,34723,34724,24013,24494,21361,38886,36829,26693,22260,21807,24799,20026,28493,32500,33479,33806,22996,20255,20266,23614,32428,26410,34074,21619,30031,32963,21890,39759,20301,28205,35859,23561,24944,21355,30239,28201,34442,25991,38395,32441,21563,31283,32010,38382,21985,32705,29934,25373,34583,28065,31389,25105,26017,21351,25569,27779,24043,21596,38056,20044,27745,35820,23627,26080,33436,26791,21566,21556,27595,27494,20116,25410,21320,33310,20237,20398,22366,25098,38654,26212,29289,21247,21153,24735,35823,26132,29081,26512,35199,30802,30717,26224,22075,21560,38177,29306,34725,34726,34727,34729,34730,34734,34736,34737,34738,34740,34742,34743,34744,34745,34747,34748,34750,34751,34753,34754,34755,34756,34757,34759,34760,34761,34764,34765,34766,34767,34768,34772,34773,34774,34775,34776,34777,34778,34780,34781,34782,34783,34785,34786,34787,34788,34790,34791,34792,34793,34795,34796,34797,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34810,34811,34812,34813,34815,34816,34817,34818,34820,34821,34822,34823,34824,34825,34827,34828,34829,34830,34831,34832,34833,34834,34836,34839,34840,34841,34842,34844,34845,34846,34847,34848,34851,31232,24687,24076,24713,33181,22805,24796,29060,28911,28330,27728,29312,27268,34989,24109,20064,23219,21916,38115,27927,31995,38553,25103,32454,30606,34430,21283,38686,36758,26247,23777,20384,29421,19979,21414,22799,21523,25472,38184,20808,20185,40092,32420,21688,36132,34900,33335,38386,28046,24358,23244,26174,38505,29616,29486,21439,33146,39301,32673,23466,38519,38480,32447,30456,21410,38262,39321,31665,35140,28248,20065,32724,31077,35814,24819,21709,20139,39033,24055,27233,20687,21521,35937,33831,30813,38660,21066,21742,22179,38144,28040,23477,28102,26195,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34867,34868,34869,34870,34871,34872,34874,34875,34877,34878,34879,34881,34882,34883,34886,34887,34888,34889,34890,34891,34894,34895,34896,34897,34898,34899,34901,34902,34904,34906,34907,34908,34909,34910,34911,34912,34918,34919,34922,34925,34927,34929,34931,34932,34933,34934,34936,34937,34938,34939,34940,34944,34947,34950,34951,34953,34954,34956,34958,34959,34960,34961,34963,34964,34965,34967,34968,34969,34970,34971,34973,34974,34975,34976,34977,34979,34981,34982,34983,34984,34985,34986,23567,23389,26657,32918,21880,31505,25928,26964,20123,27463,34638,38795,21327,25375,25658,37034,26012,32961,35856,20889,26800,21368,34809,25032,27844,27899,35874,23633,34218,33455,38156,27427,36763,26032,24571,24515,20449,34885,26143,33125,29481,24826,20852,21009,22411,24418,37026,34892,37266,24184,26447,24615,22995,20804,20982,33016,21256,27769,38596,29066,20241,20462,32670,26429,21957,38152,31168,34966,32483,22687,25100,38656,34394,22040,39035,24464,35768,33988,37207,21465,26093,24207,30044,24676,32110,23167,32490,32493,36713,21927,23459,24748,26059,29572,34988,34990,34991,34992,34994,34995,34996,34997,34998,35e3,35001,35002,35003,35005,35006,35007,35008,35011,35012,35015,35016,35018,35019,35020,35021,35023,35024,35025,35027,35030,35031,35034,35035,35036,35037,35038,35040,35041,35046,35047,35049,35050,35051,35052,35053,35054,35055,35058,35061,35062,35063,35066,35067,35069,35071,35072,35073,35075,35076,35077,35078,35079,35080,35081,35083,35084,35085,35086,35087,35089,35092,35093,35094,35095,35096,35100,35101,35102,35103,35104,35106,35107,35108,35110,35111,35112,35113,35116,35117,35118,35119,35121,35122,35123,35125,35127,36873,30307,30505,32474,38772,34203,23398,31348,38634,34880,21195,29071,24490,26092,35810,23547,39535,24033,27529,27739,35757,35759,36874,36805,21387,25276,40486,40493,21568,20011,33469,29273,34460,23830,34905,28079,38597,21713,20122,35766,28937,21693,38409,28895,28153,30416,20005,30740,34578,23721,24310,35328,39068,38414,28814,27839,22852,25513,30524,34893,28436,33395,22576,29141,21388,30746,38593,21761,24422,28976,23476,35866,39564,27523,22830,40495,31207,26472,25196,20335,30113,32650,27915,38451,27687,20208,30162,20859,26679,28478,36992,33136,22934,29814,35128,35129,35130,35131,35132,35133,35134,35135,35136,35138,35139,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35168,35169,35170,35171,35172,35173,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35196,35197,35198,35200,35202,35204,35205,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,25671,23591,36965,31377,35875,23002,21676,33280,33647,35201,32768,26928,22094,32822,29239,37326,20918,20063,39029,25494,19994,21494,26355,33099,22812,28082,19968,22777,21307,25558,38129,20381,20234,34915,39056,22839,36951,31227,20202,33008,30097,27778,23452,23016,24413,26885,34433,20506,24050,20057,30691,20197,33402,25233,26131,37009,23673,20159,24441,33222,36920,32900,30123,20134,35028,24847,27589,24518,20041,30410,28322,35811,35758,35850,35793,24322,32764,32716,32462,33589,33643,22240,27575,38899,38452,23035,21535,38134,28139,23493,39278,23609,24341,38544,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35267,35277,35283,35284,35285,35287,35288,35289,35291,35293,35295,35296,35297,35298,35300,35303,35304,35305,35306,35308,35309,35310,35312,35313,35314,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35329,35330,35331,35332,35333,35334,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,21360,33521,27185,23156,40560,24212,32552,33721,33828,33829,33639,34631,36814,36194,30408,24433,39062,30828,26144,21727,25317,20323,33219,30152,24248,38605,36362,34553,21647,27891,28044,27704,24703,21191,29992,24189,20248,24736,24551,23588,30001,37038,38080,29369,27833,28216,37193,26377,21451,21491,20305,37321,35825,21448,24188,36802,28132,20110,30402,27014,34398,24858,33286,20313,20446,36926,40060,24841,28189,28180,38533,20104,23089,38632,19982,23679,31161,23431,35821,32701,29577,22495,33419,37057,21505,36935,21947,23786,24481,24840,27442,29425,32946,35465,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35391,35392,35393,35394,35395,35396,35397,35398,35399,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,35434,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35450,35451,35452,35453,35454,35455,35456,28020,23507,35029,39044,35947,39533,40499,28170,20900,20803,22435,34945,21407,25588,36757,22253,21592,22278,29503,28304,32536,36828,33489,24895,24616,38498,26352,32422,36234,36291,38053,23731,31908,26376,24742,38405,32792,20113,37095,21248,38504,20801,36816,34164,37213,26197,38901,23381,21277,30776,26434,26685,21705,28798,23472,36733,20877,22312,21681,25874,26242,36190,36163,33039,33900,36973,31967,20991,34299,26531,26089,28577,34468,36481,22122,36896,30338,28790,29157,36131,25321,21017,27901,36156,24590,22686,24974,26366,36192,25166,21939,28195,26413,36711,35457,35458,35459,35460,35461,35462,35463,35464,35467,35468,35469,35470,35471,35472,35473,35474,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,38113,38392,30504,26629,27048,21643,20045,28856,35784,25688,25995,23429,31364,20538,23528,30651,27617,35449,31896,27838,30415,26025,36759,23853,23637,34360,26632,21344,25112,31449,28251,32509,27167,31456,24432,28467,24352,25484,28072,26454,19976,24080,36134,20183,32960,30260,38556,25307,26157,25214,27836,36213,29031,32617,20806,32903,21484,36974,25240,21746,34544,36761,32773,38167,34071,36825,27993,29645,26015,30495,29956,30759,33275,36126,38024,20390,26517,30137,35786,38663,25391,38215,38453,33976,25379,30529,24449,29424,20105,24596,25972,25327,27491,25919,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35592,35593,35594,35595,35596,35597,35598,35599,35600,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,24103,30151,37073,35777,33437,26525,25903,21553,34584,30693,32930,33026,27713,20043,32455,32844,30452,26893,27542,25191,20540,20356,22336,25351,27490,36286,21482,26088,32440,24535,25370,25527,33267,33268,32622,24092,23769,21046,26234,31209,31258,36136,28825,30164,28382,27835,31378,20013,30405,24544,38047,34935,32456,31181,32959,37325,20210,20247,33311,21608,24030,27954,35788,31909,36724,32920,24090,21650,30385,23449,26172,39588,29664,26666,34523,26417,29482,35832,35803,36880,31481,28891,29038,25284,30633,22065,20027,33879,26609,21161,34496,36142,38136,31569,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35687,35688,35689,35690,35691,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35756,35761,35771,35783,35792,35818,35849,35870,20303,27880,31069,39547,25235,29226,25341,19987,30742,36716,25776,36186,31686,26729,24196,35013,22918,25758,22766,29366,26894,38181,36861,36184,22368,32512,35846,20934,25417,25305,21331,26700,29730,33537,37196,21828,30528,28796,27978,20857,21672,36164,23039,28363,28100,23388,32043,20180,31869,28371,23376,33258,28173,23383,39683,26837,36394,23447,32508,24635,32437,37049,36208,22863,25549,31199,36275,21330,26063,31062,35781,38459,32452,38075,32386,22068,37257,26368,32618,23562,36981,26152,24038,20304,26590,20570,20316,22352,24231,59408,59409,59410,59411,59412,35896,35897,35898,35899,35900,35901,35902,35903,35904,35906,35907,35908,35909,35912,35914,35915,35917,35918,35919,35920,35921,35922,35923,35924,35926,35927,35928,35929,35931,35932,35933,35934,35935,35936,35939,35940,35941,35942,35943,35944,35945,35948,35949,35950,35951,35952,35953,35954,35956,35957,35958,35959,35963,35964,35965,35966,35967,35968,35969,35971,35972,35974,35975,35976,35979,35981,35982,35983,35984,35985,35986,35987,35989,35990,35991,35993,35994,35995,35996,35997,35998,35999,36e3,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,20109,19980,20800,19984,24319,21317,19989,20120,19998,39730,23404,22121,20008,31162,20031,21269,20039,22829,29243,21358,27664,22239,32996,39319,27603,30590,40727,20022,20127,40720,20060,20073,20115,33416,23387,21868,22031,20164,21389,21405,21411,21413,21422,38757,36189,21274,21493,21286,21294,21310,36188,21350,21347,20994,21e3,21006,21037,21043,21055,21056,21068,21086,21089,21084,33967,21117,21122,21121,21136,21139,20866,32596,20155,20163,20169,20162,20200,20193,20203,20190,20251,20211,20258,20324,20213,20261,20263,20233,20267,20318,20327,25912,20314,20317,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,36099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,20319,20311,20274,20285,20342,20340,20369,20361,20355,20367,20350,20347,20394,20348,20396,20372,20454,20456,20458,20421,20442,20451,20444,20433,20447,20472,20521,20556,20467,20524,20495,20526,20525,20478,20508,20492,20517,20520,20606,20547,20565,20552,20558,20588,20603,20645,20647,20649,20666,20694,20742,20717,20716,20710,20718,20743,20747,20189,27709,20312,20325,20430,40864,27718,31860,20846,24061,40649,39320,20865,22804,21241,21261,35335,21264,20971,22809,20821,20128,20822,20147,34926,34980,20149,33044,35026,31104,23348,34819,32696,20907,20913,20925,20924,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36128,36177,36178,36183,36191,36197,36200,36201,36202,36204,36206,36207,36209,36210,36216,36217,36218,36219,36220,36221,36222,36223,36224,36226,36227,36230,36231,36232,36233,36236,36237,36238,36239,36240,36242,36243,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36256,36257,36258,36260,36261,36262,36263,36264,36265,36266,36267,36268,36269,36270,36271,36272,36274,36278,36279,36281,36283,36285,36288,36289,36290,36293,36295,36296,36297,36298,36301,36304,36306,36307,36308,20935,20886,20898,20901,35744,35750,35751,35754,35764,35765,35767,35778,35779,35787,35791,35790,35794,35795,35796,35798,35800,35801,35804,35807,35808,35812,35816,35817,35822,35824,35827,35830,35833,35836,35839,35840,35842,35844,35847,35852,35855,35857,35858,35860,35861,35862,35865,35867,35864,35869,35871,35872,35873,35877,35879,35882,35883,35886,35887,35890,35891,35893,35894,21353,21370,38429,38434,38433,38449,38442,38461,38460,38466,38473,38484,38495,38503,38508,38514,38516,38536,38541,38551,38576,37015,37019,37021,37017,37036,37025,37044,37043,37046,37050,36309,36312,36313,36316,36320,36321,36322,36325,36326,36327,36329,36333,36334,36336,36337,36338,36340,36342,36348,36350,36351,36352,36353,36354,36355,36356,36358,36359,36360,36363,36365,36366,36368,36369,36370,36371,36373,36374,36375,36376,36377,36378,36379,36380,36384,36385,36388,36389,36390,36391,36392,36395,36397,36400,36402,36403,36404,36406,36407,36408,36411,36412,36414,36415,36419,36421,36422,36428,36429,36430,36431,36432,36435,36436,36437,36438,36439,36440,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36455,36456,36458,36459,36462,36465,37048,37040,37071,37061,37054,37072,37060,37063,37075,37094,37090,37084,37079,37083,37099,37103,37118,37124,37154,37150,37155,37169,37167,37177,37187,37190,21005,22850,21154,21164,21165,21182,21759,21200,21206,21232,21471,29166,30669,24308,20981,20988,39727,21430,24321,30042,24047,22348,22441,22433,22654,22716,22725,22737,22313,22316,22314,22323,22329,22318,22319,22364,22331,22338,22377,22405,22379,22406,22396,22395,22376,22381,22390,22387,22445,22436,22412,22450,22479,22439,22452,22419,22432,22485,22488,22490,22489,22482,22456,22516,22511,22520,22500,22493,36467,36469,36471,36472,36473,36474,36475,36477,36478,36480,36482,36483,36484,36486,36488,36489,36490,36491,36492,36493,36494,36497,36498,36499,36501,36502,36503,36504,36505,36506,36507,36509,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36525,36526,36528,36529,36531,36532,36533,36534,36535,36536,36537,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,22539,22541,22525,22509,22528,22558,22553,22596,22560,22629,22636,22657,22665,22682,22656,39336,40729,25087,33401,33405,33407,33423,33418,33448,33412,33422,33425,33431,33433,33451,33464,33470,33456,33480,33482,33507,33432,33463,33454,33483,33484,33473,33449,33460,33441,33450,33439,33476,33486,33444,33505,33545,33527,33508,33551,33543,33500,33524,33490,33496,33548,33531,33491,33553,33562,33542,33556,33557,33504,33493,33564,33617,33627,33628,33544,33682,33596,33588,33585,33691,33630,33583,33615,33607,33603,33631,33600,33559,33632,33581,33594,33587,33638,33637,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,36597,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,33640,33563,33641,33644,33642,33645,33646,33712,33656,33715,33716,33696,33706,33683,33692,33669,33660,33718,33705,33661,33720,33659,33688,33694,33704,33722,33724,33729,33793,33765,33752,22535,33816,33803,33757,33789,33750,33820,33848,33809,33798,33748,33759,33807,33795,33784,33785,33770,33733,33728,33830,33776,33761,33884,33873,33882,33881,33907,33927,33928,33914,33929,33912,33852,33862,33897,33910,33932,33934,33841,33901,33985,33997,34e3,34022,33981,34003,33994,33983,33978,34016,33953,33977,33972,33943,34021,34019,34060,29965,34104,34032,34105,34079,34106,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36714,36736,36748,36754,36765,36768,36769,36770,36772,36773,36774,36775,36778,36780,36781,36782,36783,36786,36787,36788,36789,36791,36792,36794,36795,36796,36799,36800,36803,36806,36809,36810,36811,36812,36813,36815,36818,36822,36823,36826,36832,36833,36835,36839,36844,36847,36849,36850,36852,36853,36854,36858,36859,36860,36862,36863,36871,36872,36876,36878,36883,36885,36888,34134,34107,34047,34044,34137,34120,34152,34148,34142,34170,30626,34115,34162,34171,34212,34216,34183,34191,34169,34222,34204,34181,34233,34231,34224,34259,34241,34268,34303,34343,34309,34345,34326,34364,24318,24328,22844,22849,32823,22869,22874,22872,21263,23586,23589,23596,23604,25164,25194,25247,25275,25290,25306,25303,25326,25378,25334,25401,25419,25411,25517,25590,25457,25466,25486,25524,25453,25516,25482,25449,25518,25532,25586,25592,25568,25599,25540,25566,25550,25682,25542,25534,25669,25665,25611,25627,25632,25612,25638,25633,25694,25732,25709,25750,36889,36892,36899,36900,36901,36903,36904,36905,36906,36907,36908,36912,36913,36914,36915,36916,36919,36921,36922,36925,36927,36928,36931,36933,36934,36936,36937,36938,36939,36940,36942,36948,36949,36950,36953,36954,36956,36957,36958,36959,36960,36961,36964,36966,36967,36969,36970,36971,36972,36975,36976,36977,36978,36979,36982,36983,36984,36985,36986,36987,36988,36990,36993,36996,36997,36998,36999,37001,37002,37004,37005,37006,37007,37008,37010,37012,37014,37016,37018,37020,37022,37023,37024,37028,37029,37031,37032,37033,37035,37037,37042,37047,37052,37053,37055,37056,25722,25783,25784,25753,25786,25792,25808,25815,25828,25826,25865,25893,25902,24331,24530,29977,24337,21343,21489,21501,21481,21480,21499,21522,21526,21510,21579,21586,21587,21588,21590,21571,21537,21591,21593,21539,21554,21634,21652,21623,21617,21604,21658,21659,21636,21622,21606,21661,21712,21677,21698,21684,21714,21671,21670,21715,21716,21618,21667,21717,21691,21695,21708,21721,21722,21724,21673,21674,21668,21725,21711,21726,21787,21735,21792,21757,21780,21747,21794,21795,21775,21777,21799,21802,21863,21903,21941,21833,21869,21825,21845,21823,21840,21820,37058,37059,37062,37064,37065,37067,37068,37069,37074,37076,37077,37078,37080,37081,37082,37086,37087,37088,37091,37092,37093,37097,37098,37100,37102,37104,37105,37106,37107,37109,37110,37111,37113,37114,37115,37116,37119,37120,37121,37123,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37146,37147,37148,37149,37151,37152,37153,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37168,37170,37171,37172,37173,37174,37175,37176,37178,37179,37180,37181,37182,37183,37184,37185,37186,37188,21815,21846,21877,21878,21879,21811,21808,21852,21899,21970,21891,21937,21945,21896,21889,21919,21886,21974,21905,21883,21983,21949,21950,21908,21913,21994,22007,21961,22047,21969,21995,21996,21972,21990,21981,21956,21999,21989,22002,22003,21964,21965,21992,22005,21988,36756,22046,22024,22028,22017,22052,22051,22014,22016,22055,22061,22104,22073,22103,22060,22093,22114,22105,22108,22092,22100,22150,22116,22129,22123,22139,22140,22149,22163,22191,22228,22231,22237,22241,22261,22251,22265,22271,22276,22282,22281,22300,24079,24089,24084,24081,24113,24123,24124,37189,37191,37192,37201,37203,37204,37205,37206,37208,37209,37211,37212,37215,37216,37222,37223,37224,37227,37229,37235,37242,37243,37244,37248,37249,37250,37251,37252,37254,37256,37258,37262,37263,37267,37268,37269,37270,37271,37272,37273,37276,37277,37278,37279,37280,37281,37284,37285,37286,37287,37288,37289,37291,37292,37296,37297,37298,37299,37302,37303,37304,37305,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37320,37323,37328,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37341,37342,37343,37344,37345,37346,37347,37348,37349,24119,24132,24148,24155,24158,24161,23692,23674,23693,23696,23702,23688,23704,23705,23697,23706,23708,23733,23714,23741,23724,23723,23729,23715,23745,23735,23748,23762,23780,23755,23781,23810,23811,23847,23846,23854,23844,23838,23814,23835,23896,23870,23860,23869,23916,23899,23919,23901,23915,23883,23882,23913,23924,23938,23961,23965,35955,23991,24005,24435,24439,24450,24455,24457,24460,24469,24473,24476,24488,24493,24501,24508,34914,24417,29357,29360,29364,29367,29368,29379,29377,29390,29389,29394,29416,29423,29417,29426,29428,29431,29441,29427,29443,29434,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,37428,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,29435,29463,29459,29473,29450,29470,29469,29461,29474,29497,29477,29484,29496,29489,29520,29517,29527,29536,29548,29551,29566,33307,22821,39143,22820,22786,39267,39271,39272,39273,39274,39275,39276,39284,39287,39293,39296,39300,39303,39306,39309,39312,39313,39315,39316,39317,24192,24209,24203,24214,24229,24224,24249,24245,24254,24243,36179,24274,24273,24283,24296,24298,33210,24516,24521,24534,24527,24579,24558,24580,24545,24548,24574,24581,24582,24554,24557,24568,24601,24629,24614,24603,24591,24589,24617,24619,24586,24639,24609,24696,24697,24699,24698,24642,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,24682,24701,24726,24730,24749,24733,24707,24722,24716,24731,24812,24763,24753,24797,24792,24774,24794,24756,24864,24870,24853,24867,24820,24832,24846,24875,24906,24949,25004,24980,24999,25015,25044,25077,24541,38579,38377,38379,38385,38387,38389,38390,38396,38398,38403,38404,38406,38408,38410,38411,38412,38413,38415,38418,38421,38422,38423,38425,38426,20012,29247,25109,27701,27732,27740,27722,27811,27781,27792,27796,27788,27752,27753,27764,27766,27782,27817,27856,27860,27821,27895,27896,27889,27863,27826,27872,27862,27898,27883,27886,27825,27859,27887,27902,37544,37545,37546,37547,37548,37549,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,37594,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,27961,27943,27916,27971,27976,27911,27908,27929,27918,27947,27981,27950,27957,27930,27983,27986,27988,27955,28049,28015,28062,28064,27998,28051,28052,27996,28e3,28028,28003,28186,28103,28101,28126,28174,28095,28128,28177,28134,28125,28121,28182,28075,28172,28078,28203,28270,28238,28267,28338,28255,28294,28243,28244,28210,28197,28228,28383,28337,28312,28384,28461,28386,28325,28327,28349,28347,28343,28375,28340,28367,28303,28354,28319,28514,28486,28487,28452,28437,28409,28463,28470,28491,28532,28458,28425,28457,28553,28557,28556,28536,28530,28540,28538,28625,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37739,28617,28583,28601,28598,28610,28641,28654,28638,28640,28655,28698,28707,28699,28729,28725,28751,28766,23424,23428,23445,23443,23461,23480,29999,39582,25652,23524,23534,35120,23536,36423,35591,36790,36819,36821,36837,36846,36836,36841,36838,36851,36840,36869,36868,36875,36902,36881,36877,36886,36897,36917,36918,36909,36911,36932,36945,36946,36944,36968,36952,36962,36955,26297,36980,36989,36994,37e3,36995,37003,24400,24407,24406,24408,23611,21675,23632,23641,23409,23651,23654,32700,24362,24361,24365,33396,24380,39739,23662,22913,22915,22925,22953,22954,22947,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37835,37836,37837,22935,22986,22955,22942,22948,22994,22962,22959,22999,22974,23045,23046,23005,23048,23011,23e3,23033,23052,23049,23090,23092,23057,23075,23059,23104,23143,23114,23125,23100,23138,23157,33004,23210,23195,23159,23162,23230,23275,23218,23250,23252,23224,23264,23267,23281,23254,23270,23256,23260,23305,23319,23318,23346,23351,23360,23573,23580,23386,23397,23411,23377,23379,23394,39541,39543,39544,39546,39551,39549,39552,39553,39557,39560,39562,39568,39570,39571,39574,39576,39579,39580,39581,39583,39584,39586,39587,39589,39591,32415,32417,32419,32421,32424,32425,37838,37839,37840,37841,37842,37843,37844,37845,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,37927,37928,37929,37930,37931,37932,37933,37934,32429,32432,32446,32448,32449,32450,32457,32459,32460,32464,32468,32471,32475,32480,32481,32488,32491,32494,32495,32497,32498,32525,32502,32506,32507,32510,32513,32514,32515,32519,32520,32523,32524,32527,32529,32530,32535,32537,32540,32539,32543,32545,32546,32547,32548,32549,32550,32551,32554,32555,32556,32557,32559,32560,32561,32562,32563,32565,24186,30079,24027,30014,37013,29582,29585,29614,29602,29599,29647,29634,29649,29623,29619,29632,29641,29640,29669,29657,39036,29706,29673,29671,29662,29626,29682,29711,29738,29787,29734,29733,29736,29744,29742,29740,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37996,37997,37998,37999,38e3,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38033,38038,38040,38087,38095,38099,38100,38106,38118,38139,38172,38176,29723,29722,29761,29788,29783,29781,29785,29815,29805,29822,29852,29838,29824,29825,29831,29835,29854,29864,29865,29840,29863,29906,29882,38890,38891,38892,26444,26451,26462,26440,26473,26533,26503,26474,26483,26520,26535,26485,26536,26526,26541,26507,26487,26492,26608,26633,26584,26634,26601,26544,26636,26585,26549,26586,26547,26589,26624,26563,26552,26594,26638,26561,26621,26674,26675,26720,26721,26702,26722,26692,26724,26755,26653,26709,26726,26689,26727,26688,26686,26698,26697,26665,26805,26767,26740,26743,26771,26731,26818,26990,26876,26911,26912,26873,38183,38195,38205,38211,38216,38219,38229,38234,38240,38254,38260,38261,38263,38264,38265,38266,38267,38268,38269,38270,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,26916,26864,26891,26881,26967,26851,26896,26993,26937,26976,26946,26973,27012,26987,27008,27032,27e3,26932,27084,27015,27016,27086,27017,26982,26979,27001,27035,27047,27067,27051,27053,27092,27057,27073,27082,27103,27029,27104,27021,27135,27183,27117,27159,27160,27237,27122,27204,27198,27296,27216,27227,27189,27278,27257,27197,27176,27224,27260,27281,27280,27305,27287,27307,29495,29522,27521,27522,27527,27524,27538,27539,27533,27546,27547,27553,27562,36715,36717,36721,36722,36723,36725,36726,36728,36727,36729,36730,36732,36734,36737,36738,36740,36743,36747,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38380,38399,38407,38419,38424,38427,38430,38432,38435,38436,38437,38438,38439,38440,38441,38443,38444,38445,38447,38448,38455,38456,38457,38458,38462,38465,38467,38474,38478,38479,38481,38482,38483,38486,38487,38488,38489,38490,38492,38493,38494,38496,38499,38501,38502,38507,38509,38510,38511,38512,38513,38515,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38535,38537,38538,36749,36750,36751,36760,36762,36558,25099,25111,25115,25119,25122,25121,25125,25124,25132,33255,29935,29940,29951,29967,29969,29971,25908,26094,26095,26096,26122,26137,26482,26115,26133,26112,28805,26359,26141,26164,26161,26166,26165,32774,26207,26196,26177,26191,26198,26209,26199,26231,26244,26252,26279,26269,26302,26331,26332,26342,26345,36146,36147,36150,36155,36157,36160,36165,36166,36168,36169,36167,36173,36181,36185,35271,35274,35275,35276,35278,35279,35280,35281,29294,29343,29277,29286,29295,29310,29311,29316,29323,29325,29327,29330,25352,25394,25520,38540,38542,38545,38546,38547,38549,38550,38554,38555,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38568,38569,38570,38571,38572,38573,38574,38575,38577,38578,38580,38581,38583,38584,38586,38587,38591,38594,38595,38600,38602,38603,38608,38609,38611,38612,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38625,38626,38627,38628,38629,38630,38631,38635,38636,38637,38638,38640,38641,38642,38644,38645,38648,38650,38651,38652,38653,38655,38658,38659,38661,38666,38667,38668,38672,38673,38674,38676,38677,38679,38680,38681,38682,38683,38685,38687,38688,25663,25816,32772,27626,27635,27645,27637,27641,27653,27655,27654,27661,27669,27672,27673,27674,27681,27689,27684,27690,27698,25909,25941,25963,29261,29266,29270,29232,34402,21014,32927,32924,32915,32956,26378,32957,32945,32939,32941,32948,32951,32999,33e3,33001,33002,32987,32962,32964,32985,32973,32983,26384,32989,33003,33009,33012,33005,33037,33038,33010,33020,26389,33042,35930,33078,33054,33068,33048,33074,33096,33100,33107,33140,33113,33114,33137,33120,33129,33148,33149,33133,33127,22605,23221,33160,33154,33169,28373,33187,33194,33228,26406,33226,33211,38689,38690,38691,38692,38693,38694,38695,38696,38697,38699,38700,38702,38703,38705,38707,38708,38709,38710,38711,38714,38715,38716,38717,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38740,38741,38743,38744,38746,38748,38749,38751,38755,38756,38758,38759,38760,38762,38763,38764,38765,38766,38767,38768,38769,38770,38773,38775,38776,38777,38778,38779,38781,38782,38783,38784,38785,38786,38787,38788,38790,38791,38792,38793,38794,38796,38798,38799,38800,38803,38805,38806,38807,38809,38810,38811,38812,38813,33217,33190,27428,27447,27449,27459,27462,27481,39121,39122,39123,39125,39129,39130,27571,24384,27586,35315,26e3,40785,26003,26044,26054,26052,26051,26060,26062,26066,26070,28800,28828,28822,28829,28859,28864,28855,28843,28849,28904,28874,28944,28947,28950,28975,28977,29043,29020,29032,28997,29042,29002,29048,29050,29080,29107,29109,29096,29088,29152,29140,29159,29177,29213,29224,28780,28952,29030,29113,25150,25149,25155,25160,25161,31035,31040,31046,31049,31067,31068,31059,31066,31074,31063,31072,31087,31079,31098,31109,31114,31130,31143,31155,24529,24528,38814,38815,38817,38818,38820,38821,38822,38823,38824,38825,38826,38828,38830,38832,38833,38835,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38888,38894,38895,38896,38897,38898,38900,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,38924,38925,38926,24636,24669,24666,24679,24641,24665,24675,24747,24838,24845,24925,25001,24989,25035,25041,25094,32896,32895,27795,27894,28156,30710,30712,30720,30729,30743,30744,30737,26027,30765,30748,30749,30777,30778,30779,30751,30780,30757,30764,30755,30761,30798,30829,30806,30807,30758,30800,30791,30796,30826,30875,30867,30874,30855,30876,30881,30883,30898,30905,30885,30932,30937,30921,30956,30962,30981,30964,30995,31012,31006,31028,40859,40697,40699,40700,30449,30468,30477,30457,30471,30472,30490,30498,30489,30509,30502,30517,30520,30544,30545,30535,30531,30554,30568,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39e3,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,30562,30565,30591,30605,30589,30592,30604,30609,30623,30624,30640,30645,30653,30010,30016,30030,30027,30024,30043,30066,30073,30083,32600,32609,32607,35400,32616,32628,32625,32633,32641,32638,30413,30437,34866,38021,38022,38023,38027,38026,38028,38029,38031,38032,38036,38039,38037,38042,38043,38044,38051,38052,38059,38058,38061,38060,38063,38064,38066,38068,38070,38071,38072,38073,38074,38076,38077,38079,38084,38088,38089,38090,38091,38092,38093,38094,38096,38097,38098,38101,38102,38103,38105,38104,38107,38110,38111,38112,38114,38116,38117,38119,38120,38122,39023,39024,39025,39026,39027,39028,39051,39054,39058,39061,39065,39075,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,39090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39119,39120,39124,39126,39127,39131,39132,39133,39136,39137,39138,39139,39140,39141,39142,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,38121,38123,38126,38127,38131,38132,38133,38135,38137,38140,38141,38143,38147,38146,38150,38151,38153,38154,38157,38158,38159,38162,38163,38164,38165,38166,38168,38171,38173,38174,38175,38178,38186,38187,38185,38188,38193,38194,38196,38198,38199,38200,38204,38206,38207,38210,38197,38212,38213,38214,38217,38220,38222,38223,38226,38227,38228,38230,38231,38232,38233,38235,38238,38239,38237,38241,38242,38244,38245,38246,38247,38248,38249,38250,38251,38252,38255,38257,38258,38259,38202,30695,30700,38601,31189,31213,31203,31211,31238,23879,31235,31234,31262,31252,39176,39177,39178,39179,39180,39182,39183,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39254,39255,39256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39268,39270,39283,39288,39289,39291,39294,39298,39299,39305,31289,31287,31313,40655,39333,31344,30344,30350,30355,30361,30372,29918,29920,29996,40480,40482,40488,40489,40490,40491,40492,40498,40497,40502,40504,40503,40505,40506,40510,40513,40514,40516,40518,40519,40520,40521,40523,40524,40526,40529,40533,40535,40538,40539,40540,40542,40547,40550,40551,40552,40553,40554,40555,40556,40561,40557,40563,30098,30100,30102,30112,30109,30124,30115,30131,30132,30136,30148,30129,30128,30147,30146,30166,30157,30179,30184,30182,30180,30187,30183,30211,30193,30204,30207,30224,30208,30213,30220,30231,30218,30245,30232,30229,30233,39308,39310,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39334,39335,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,30235,30268,30242,30240,30272,30253,30256,30271,30261,30275,30270,30259,30285,30302,30292,30300,30294,30315,30319,32714,31462,31352,31353,31360,31366,31368,31381,31398,31392,31404,31400,31405,31411,34916,34921,34930,34941,34943,34946,34978,35014,34999,35004,35017,35042,35022,35043,35045,35057,35098,35068,35048,35070,35056,35105,35097,35091,35099,35082,35124,35115,35126,35137,35174,35195,30091,32997,30386,30388,30684,32786,32788,32790,32796,32800,32802,32805,32806,32807,32809,32808,32817,32779,32821,32835,32838,32845,32850,32873,32881,35203,39032,39040,39043,39418,39419,39420,39421,39422,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39049,39052,39053,39055,39060,39066,39067,39070,39071,39073,39074,39077,39078,34381,34388,34412,34414,34431,34426,34428,34427,34472,34445,34443,34476,34461,34471,34467,34474,34451,34473,34486,34500,34485,34510,34480,34490,34481,34479,34505,34511,34484,34537,34545,34546,34541,34547,34512,34579,34526,34548,34527,34520,34513,34563,34567,34552,34568,34570,34573,34569,34595,34619,34590,34597,34606,34586,34622,34632,34612,34609,34601,34615,34623,34690,34594,34685,34686,34683,34656,34672,34636,34670,34699,34643,34659,34684,34660,34649,34661,34707,34735,34728,34770,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39538,39555,39561,39565,39566,39572,39573,39577,39590,39593,39594,39595,39596,39597,39598,39599,39602,39603,39604,39605,39609,39611,39613,39614,39615,39619,39620,39622,39623,39624,39625,39626,39629,39630,39631,39632,39634,39636,39637,39638,39639,39641,39642,39643,39644,39645,39646,39648,39650,39651,39652,39653,39655,39656,39657,39658,39660,39662,39664,39665,39666,39667,39668,39669,39670,39671,39672,39674,39676,39677,39678,39679,39680,39681,39682,39684,39685,39686,34758,34696,34693,34733,34711,34691,34731,34789,34732,34741,34739,34763,34771,34749,34769,34752,34762,34779,34794,34784,34798,34838,34835,34814,34826,34843,34849,34873,34876,32566,32578,32580,32581,33296,31482,31485,31496,31491,31492,31509,31498,31531,31503,31559,31544,31530,31513,31534,31537,31520,31525,31524,31539,31550,31518,31576,31578,31557,31605,31564,31581,31584,31598,31611,31586,31602,31601,31632,31654,31655,31672,31660,31645,31656,31621,31658,31644,31650,31659,31668,31697,31681,31692,31709,31706,31717,31718,31722,31756,31742,31740,31759,31766,31755,39687,39689,39690,39691,39692,39693,39694,39696,39697,39698,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39712,39713,39714,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39728,39729,39731,39732,39733,39734,39735,39736,39737,39738,39741,39742,39743,39744,39750,39754,39755,39756,39758,39760,39762,39763,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,31775,31786,31782,31800,31809,31808,33278,33281,33282,33284,33260,34884,33313,33314,33315,33325,33327,33320,33323,33336,33339,33331,33332,33342,33348,33353,33355,33359,33370,33375,33384,34942,34949,34952,35032,35039,35166,32669,32671,32679,32687,32688,32690,31868,25929,31889,31901,31900,31902,31906,31922,31932,31933,31937,31943,31948,31949,31944,31941,31959,31976,33390,26280,32703,32718,32725,32741,32737,32742,32745,32750,32755,31992,32119,32166,32174,32327,32411,40632,40628,36211,36228,36244,36241,36273,36199,36205,35911,35913,37194,37200,37198,37199,37220,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,37218,37217,37232,37225,37231,37245,37246,37234,37236,37241,37260,37253,37264,37261,37265,37282,37283,37290,37293,37294,37295,37301,37300,37306,35925,40574,36280,36331,36357,36441,36457,36277,36287,36284,36282,36292,36310,36311,36314,36318,36302,36303,36315,36294,36332,36343,36344,36323,36345,36347,36324,36361,36349,36372,36381,36383,36396,36398,36387,36399,36410,36416,36409,36405,36413,36401,36425,36417,36418,36433,36434,36426,36464,36470,36476,36463,36468,36485,36495,36500,36496,36508,36510,35960,35970,35978,35973,35992,35988,26011,35286,35294,35290,35292,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,35301,35307,35311,35390,35622,38739,38633,38643,38639,38662,38657,38664,38671,38670,38698,38701,38704,38718,40832,40835,40837,40838,40839,40840,40841,40842,40844,40702,40715,40717,38585,38588,38589,38606,38610,30655,38624,37518,37550,37576,37694,37738,37834,37775,37950,37995,40063,40066,40069,40070,40071,40072,31267,40075,40078,40080,40081,40082,40084,40085,40090,40091,40094,40095,40096,40097,40098,40099,40101,40102,40103,40104,40105,40107,40109,40110,40112,40113,40114,40115,40116,40117,40118,40119,40122,40123,40124,40125,40132,40133,40134,40135,40138,40139,39996,39997,39998,39999,4e4,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40061,40062,40064,40067,40068,40073,40074,40076,40079,40083,40086,40087,40088,40089,40093,40106,40108,40111,40121,40126,40127,40128,40129,40130,40136,40137,40145,40146,40154,40155,40160,40161,40140,40141,40142,40143,40144,40147,40148,40149,40151,40152,40153,40156,40157,40159,40162,38780,38789,38801,38802,38804,38831,38827,38819,38834,38836,39601,39600,39607,40536,39606,39610,39612,39617,39616,39621,39618,39627,39628,39633,39749,39747,39751,39753,39752,39757,39761,39144,39181,39214,39253,39252,39647,39649,39654,39663,39659,39675,39661,39673,39688,39695,39699,39711,39715,40637,40638,32315,40578,40583,40584,40587,40594,37846,40605,40607,40667,40668,40669,40672,40671,40674,40681,40679,40677,40682,40687,40738,40748,40751,40761,40759,40765,40766,40772,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40253,40254,40255,40256,40257,40258,57908,57909,57910,57911,57912,57913,57914,57915,57916,57917,57918,57919,57920,57921,57922,57923,57924,57925,57926,57927,57928,57929,57930,57931,57932,57933,57934,57935,57936,57937,57938,57939,57940,57941,57942,57943,57944,57945,57946,57947,57948,57949,57950,57951,57952,57953,57954,57955,57956,57957,57958,57959,57960,57961,57962,57963,57964,57965,57966,57967,57968,57969,57970,57971,57972,57973,57974,57975,57976,57977,57978,57979,57980,57981,57982,57983,57984,57985,57986,57987,57988,57989,57990,57991,57992,57993,57994,57995,57996,57997,57998,57999,58e3,58001,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,58002,58003,58004,58005,58006,58007,58008,58009,58010,58011,58012,58013,58014,58015,58016,58017,58018,58019,58020,58021,58022,58023,58024,58025,58026,58027,58028,58029,58030,58031,58032,58033,58034,58035,58036,58037,58038,58039,58040,58041,58042,58043,58044,58045,58046,58047,58048,58049,58050,58051,58052,58053,58054,58055,58056,58057,58058,58059,58060,58061,58062,58063,58064,58065,58066,58067,58068,58069,58070,58071,58072,58073,58074,58075,58076,58077,58078,58079,58080,58081,58082,58083,58084,58085,58086,58087,58088,58089,58090,58091,58092,58093,58094,58095,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,40419,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,58096,58097,58098,58099,58100,58101,58102,58103,58104,58105,58106,58107,58108,58109,58110,58111,58112,58113,58114,58115,58116,58117,58118,58119,58120,58121,58122,58123,58124,58125,58126,58127,58128,58129,58130,58131,58132,58133,58134,58135,58136,58137,58138,58139,58140,58141,58142,58143,58144,58145,58146,58147,58148,58149,58150,58151,58152,58153,58154,58155,58156,58157,58158,58159,58160,58161,58162,58163,58164,58165,58166,58167,58168,58169,58170,58171,58172,58173,58174,58175,58176,58177,58178,58179,58180,58181,58182,58183,58184,58185,58186,58187,58188,58189,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40484,40487,40494,40496,40500,40507,40508,40512,40525,40528,40530,40531,40532,40534,40537,40541,40543,40544,40545,40546,40549,40558,40559,40562,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40576,40577,40579,40580,40581,40582,40585,40586,40588,40589,40590,40591,40592,40593,40596,40597,40598,40599,40600,40601,40602,40603,40604,40606,40608,40609,40610,40611,40612,40613,40615,40616,40617,40618,58190,58191,58192,58193,58194,58195,58196,58197,58198,58199,58200,58201,58202,58203,58204,58205,58206,58207,58208,58209,58210,58211,58212,58213,58214,58215,58216,58217,58218,58219,58220,58221,58222,58223,58224,58225,58226,58227,58228,58229,58230,58231,58232,58233,58234,58235,58236,58237,58238,58239,58240,58241,58242,58243,58244,58245,58246,58247,58248,58249,58250,58251,58252,58253,58254,58255,58256,58257,58258,58259,58260,58261,58262,58263,58264,58265,58266,58267,58268,58269,58270,58271,58272,58273,58274,58275,58276,58277,58278,58279,58280,58281,58282,58283,40619,40620,40621,40622,40623,40624,40625,40626,40627,40629,40630,40631,40633,40634,40636,40639,40640,40641,40642,40643,40645,40646,40647,40648,40650,40651,40652,40656,40658,40659,40661,40662,40663,40665,40666,40670,40673,40675,40676,40678,40680,40683,40684,40685,40686,40688,40689,40690,40691,40692,40693,40694,40695,40696,40698,40701,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40716,40719,40721,40722,40724,40725,40726,40728,40730,40731,40732,40733,40734,40735,40737,40739,40740,40741,40742,40743,40744,40745,40746,40747,40749,40750,40752,40753,58284,58285,58286,58287,58288,58289,58290,58291,58292,58293,58294,58295,58296,58297,58298,58299,58300,58301,58302,58303,58304,58305,58306,58307,58308,58309,58310,58311,58312,58313,58314,58315,58316,58317,58318,58319,58320,58321,58322,58323,58324,58325,58326,58327,58328,58329,58330,58331,58332,58333,58334,58335,58336,58337,58338,58339,58340,58341,58342,58343,58344,58345,58346,58347,58348,58349,58350,58351,58352,58353,58354,58355,58356,58357,58358,58359,58360,58361,58362,58363,58364,58365,58366,58367,58368,58369,58370,58371,58372,58373,58374,58375,58376,58377,40754,40755,40756,40757,40758,40760,40762,40764,40767,40768,40769,40770,40771,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40833,40834,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40860,40861,40862,40865,40866,40867,40868,40869,63788,63865,63893,63975,63985,58378,58379,58380,58381,58382,58383,58384,58385,58386,58387,58388,58389,58390,58391,58392,58393,58394,58395,58396,58397,58398,58399,58400,58401,58402,58403,58404,58405,58406,58407,58408,58409,58410,58411,58412,58413,58414,58415,58416,58417,58418,58419,58420,58421,58422,58423,58424,58425,58426,58427,58428,58429,58430,58431,58432,58433,58434,58435,58436,58437,58438,58439,58440,58441,58442,58443,58444,58445,58446,58447,58448,58449,58450,58451,58452,58453,58454,58455,58456,58457,58458,58459,58460,58461,58462,58463,58464,58465,58466,58467,58468,58469,58470,58471,64012,64013,64014,64015,64017,64019,64020,64024,64031,64032,64033,64035,64036,64039,64040,64041,11905,59414,59415,59416,11908,13427,13383,11912,11915,59422,13726,13850,13838,11916,11927,14702,14616,59430,14799,14815,14963,14800,59435,59436,15182,15470,15584,11943,59441,59442,11946,16470,16735,11950,17207,11955,11958,11959,59451,17329,17324,11963,17373,17622,18017,17996,59459,18211,18217,18300,18317,11978,18759,18810,18813,18818,18819,18821,18822,18847,18843,18871,18870,59476,59477,19619,19615,19616,19617,19575,19618,19731,19732,19733,19734,19735,19736,19737,19886,59492,58472,58473,58474,58475,58476,58477,58478,58479,58480,58481,58482,58483,58484,58485,58486,58487,58488,58489,58490,58491,58492,58493,58494,58495,58496,58497,58498,58499,58500,58501,58502,58503,58504,58505,58506,58507,58508,58509,58510,58511,58512,58513,58514,58515,58516,58517,58518,58519,58520,58521,58522,58523,58524,58525,58526,58527,58528,58529,58530,58531,58532,58533,58534,58535,58536,58537,58538,58539,58540,58541,58542,58543,58544,58545,58546,58547,58548,58549,58550,58551,58552,58553,58554,58555,58556,58557,58558,58559,58560,58561,58562,58563,58564,58565],"gb18030-ranges":[[0,128],[36,165],[38,169],[45,178],[50,184],[81,216],[89,226],[95,235],[96,238],[100,244],[103,248],[104,251],[105,253],[109,258],[126,276],[133,284],[148,300],[172,325],[175,329],[179,334],[208,364],[306,463],[307,465],[308,467],[309,469],[310,471],[311,473],[312,475],[313,477],[341,506],[428,594],[443,610],[544,712],[545,716],[558,730],[741,930],[742,938],[749,962],[750,970],[805,1026],[819,1104],[820,1106],[7922,8209],[7924,8215],[7925,8218],[7927,8222],[7934,8231],[7943,8241],[7944,8244],[7945,8246],[7950,8252],[8062,8365],[8148,8452],[8149,8454],[8152,8458],[8164,8471],[8174,8482],[8236,8556],[8240,8570],[8262,8596],[8264,8602],[8374,8713],[8380,8720],[8381,8722],[8384,8726],[8388,8731],[8390,8737],[8392,8740],[8393,8742],[8394,8748],[8396,8751],[8401,8760],[8406,8766],[8416,8777],[8419,8781],[8424,8787],[8437,8802],[8439,8808],[8445,8816],[8482,8854],[8485,8858],[8496,8870],[8521,8896],[8603,8979],[8936,9322],[8946,9372],[9046,9548],[9050,9588],[9063,9616],[9066,9622],[9076,9634],[9092,9652],[9100,9662],[9108,9672],[9111,9676],[9113,9680],[9131,9702],[9162,9735],[9164,9738],[9218,9793],[9219,9795],[11329,11906],[11331,11909],[11334,11913],[11336,11917],[11346,11928],[11361,11944],[11363,11947],[11366,11951],[11370,11956],[11372,11960],[11375,11964],[11389,11979],[11682,12284],[11686,12292],[11687,12312],[11692,12319],[11694,12330],[11714,12351],[11716,12436],[11723,12447],[11725,12535],[11730,12543],[11736,12586],[11982,12842],[11989,12850],[12102,12964],[12336,13200],[12348,13215],[12350,13218],[12384,13253],[12393,13263],[12395,13267],[12397,13270],[12510,13384],[12553,13428],[12851,13727],[12962,13839],[12973,13851],[13738,14617],[13823,14703],[13919,14801],[13933,14816],[14080,14964],[14298,15183],[14585,15471],[14698,15585],[15583,16471],[15847,16736],[16318,17208],[16434,17325],[16438,17330],[16481,17374],[16729,17623],[17102,17997],[17122,18018],[17315,18212],[17320,18218],[17402,18301],[17418,18318],[17859,18760],[17909,18811],[17911,18814],[17915,18820],[17916,18823],[17936,18844],[17939,18848],[17961,18872],[18664,19576],[18703,19620],[18814,19738],[18962,19887],[19043,40870],[33469,59244],[33470,59336],[33471,59367],[33484,59413],[33485,59417],[33490,59423],[33497,59431],[33501,59437],[33505,59443],[33513,59452],[33520,59460],[33536,59478],[33550,59493],[37845,63789],[37921,63866],[37948,63894],[38029,63976],[38038,63986],[38064,64016],[38065,64018],[38066,64021],[38069,64025],[38075,64034],[38076,64037],[38078,64042],[39108,65074],[39109,65093],[39113,65107],[39114,65112],[39115,65127],[39116,65132],[39265,65375],[39394,65510],[189e3,65536]],jis0208:[12288,12289,12290,65292,65294,12539,65306,65307,65311,65281,12443,12444,180,65344,168,65342,65507,65343,12541,12542,12445,12446,12291,20189,12293,12294,12295,12540,8213,8208,65295,65340,65374,8741,65372,8230,8229,8216,8217,8220,8221,65288,65289,12308,12309,65339,65341,65371,65373,12296,12297,12298,12299,12300,12301,12302,12303,12304,12305,65291,65293,177,215,247,65309,8800,65308,65310,8806,8807,8734,8756,9794,9792,176,8242,8243,8451,65509,65284,65504,65505,65285,65283,65286,65290,65312,167,9734,9733,9675,9679,9678,9671,9670,9633,9632,9651,9650,9661,9660,8251,12306,8594,8592,8593,8595,12307,null,null,null,null,null,null,null,null,null,null,null,8712,8715,8838,8839,8834,8835,8746,8745,null,null,null,null,null,null,null,null,8743,8744,65506,8658,8660,8704,8707,null,null,null,null,null,null,null,null,null,null,null,8736,8869,8978,8706,8711,8801,8786,8810,8811,8730,8765,8733,8757,8747,8748,null,null,null,null,null,null,null,8491,8240,9839,9837,9834,8224,8225,182,null,null,null,null,9711,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,65296,65297,65298,65299,65300,65301,65302,65303,65304,65305,null,null,null,null,null,null,null,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,null,null,null,null,null,null,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,null,null,null,null,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,null,null,null,null,null,null,null,null,null,null,null,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,null,null,null,null,null,null,null,null,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,null,null,null,null,null,null,null,null,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,963,964,965,966,967,968,969,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1040,1041,1042,1043,1044,1045,1025,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1072,1073,1074,1075,1076,1077,1105,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,null,null,null,null,null,null,null,null,null,null,null,null,null,9472,9474,9484,9488,9496,9492,9500,9516,9508,9524,9532,9473,9475,9487,9491,9499,9495,9507,9523,9515,9531,9547,9504,9519,9512,9527,9535,9501,9520,9509,9528,9538,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,9323,9324,9325,9326,9327,9328,9329,9330,9331,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,null,13129,13076,13090,13133,13080,13095,13059,13110,13137,13143,13069,13094,13091,13099,13130,13115,13212,13213,13214,13198,13199,13252,13217,null,null,null,null,null,null,null,null,13179,12317,12319,8470,13261,8481,12964,12965,12966,12967,12968,12849,12850,12857,13182,13181,13180,8786,8801,8747,8750,8721,8730,8869,8736,8735,8895,8757,8745,8746,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,20124,21782,23043,38463,21696,24859,25384,23030,36898,33909,33564,31312,24746,25569,28197,26093,33894,33446,39925,26771,22311,26017,25201,23451,22992,34427,39156,32098,32190,39822,25110,31903,34999,23433,24245,25353,26263,26696,38343,38797,26447,20197,20234,20301,20381,20553,22258,22839,22996,23041,23561,24799,24847,24944,26131,26885,28858,30031,30064,31227,32173,32239,32963,33806,34915,35586,36949,36986,21307,20117,20133,22495,32946,37057,30959,19968,22769,28322,36920,31282,33576,33419,39983,20801,21360,21693,21729,22240,23035,24341,39154,28139,32996,34093,38498,38512,38560,38907,21515,21491,23431,28879,32701,36802,38632,21359,40284,31418,19985,30867,33276,28198,22040,21764,27421,34074,39995,23013,21417,28006,29916,38287,22082,20113,36939,38642,33615,39180,21473,21942,23344,24433,26144,26355,26628,27704,27891,27945,29787,30408,31310,38964,33521,34907,35424,37613,28082,30123,30410,39365,24742,35585,36234,38322,27022,21421,20870,22290,22576,22852,23476,24310,24616,25513,25588,27839,28436,28814,28948,29017,29141,29503,32257,33398,33489,34199,36960,37467,40219,22633,26044,27738,29989,20985,22830,22885,24448,24540,25276,26106,27178,27431,27572,29579,32705,35158,40236,40206,40644,23713,27798,33659,20740,23627,25014,33222,26742,29281,20057,20474,21368,24681,28201,31311,38899,19979,21270,20206,20309,20285,20385,20339,21152,21487,22025,22799,23233,23478,23521,31185,26247,26524,26550,27468,27827,28779,29634,31117,31166,31292,31623,33457,33499,33540,33655,33775,33747,34662,35506,22057,36008,36838,36942,38686,34442,20420,23784,25105,29273,30011,33253,33469,34558,36032,38597,39187,39381,20171,20250,35299,22238,22602,22730,24315,24555,24618,24724,24674,25040,25106,25296,25913,39745,26214,26800,28023,28784,30028,30342,32117,33445,34809,38283,38542,35997,20977,21182,22806,21683,23475,23830,24936,27010,28079,30861,33995,34903,35442,37799,39608,28012,39336,34521,22435,26623,34510,37390,21123,22151,21508,24275,25313,25785,26684,26680,27579,29554,30906,31339,35226,35282,36203,36611,37101,38307,38548,38761,23398,23731,27005,38989,38990,25499,31520,27179,27263,26806,39949,28511,21106,21917,24688,25324,27963,28167,28369,33883,35088,36676,19988,39993,21494,26907,27194,38788,26666,20828,31427,33970,37340,37772,22107,40232,26658,33541,33841,31909,21e3,33477,29926,20094,20355,20896,23506,21002,21208,21223,24059,21914,22570,23014,23436,23448,23515,24178,24185,24739,24863,24931,25022,25563,25954,26577,26707,26874,27454,27475,27735,28450,28567,28485,29872,29976,30435,30475,31487,31649,31777,32233,32566,32752,32925,33382,33694,35251,35532,36011,36996,37969,38291,38289,38306,38501,38867,39208,33304,20024,21547,23736,24012,29609,30284,30524,23721,32747,36107,38593,38929,38996,39e3,20225,20238,21361,21916,22120,22522,22855,23305,23492,23696,24076,24190,24524,25582,26426,26071,26082,26399,26827,26820,27231,24112,27589,27671,27773,30079,31048,23395,31232,32e3,24509,35215,35352,36020,36215,36556,36637,39138,39438,39740,20096,20605,20736,22931,23452,25135,25216,25836,27450,29344,30097,31047,32681,34811,35516,35696,25516,33738,38816,21513,21507,21931,26708,27224,35440,30759,26485,40653,21364,23458,33050,34384,36870,19992,20037,20167,20241,21450,21560,23470,24339,24613,25937,26429,27714,27762,27875,28792,29699,31350,31406,31496,32026,31998,32102,26087,29275,21435,23621,24040,25298,25312,25369,28192,34394,35377,36317,37624,28417,31142,39770,20136,20139,20140,20379,20384,20689,20807,31478,20849,20982,21332,21281,21375,21483,21932,22659,23777,24375,24394,24623,24656,24685,25375,25945,27211,27841,29378,29421,30703,33016,33029,33288,34126,37111,37857,38911,39255,39514,20208,20957,23597,26241,26989,23616,26354,26997,29577,26704,31873,20677,21220,22343,24062,37670,26020,27427,27453,29748,31105,31165,31563,32202,33465,33740,34943,35167,35641,36817,37329,21535,37504,20061,20534,21477,21306,29399,29590,30697,33510,36527,39366,39368,39378,20855,24858,34398,21936,31354,20598,23507,36935,38533,20018,27355,37351,23633,23624,25496,31391,27795,38772,36705,31402,29066,38536,31874,26647,32368,26705,37740,21234,21531,34219,35347,32676,36557,37089,21350,34952,31041,20418,20670,21009,20804,21843,22317,29674,22411,22865,24418,24452,24693,24950,24935,25001,25522,25658,25964,26223,26690,28179,30054,31293,31995,32076,32153,32331,32619,33550,33610,34509,35336,35427,35686,36605,38938,40335,33464,36814,39912,21127,25119,25731,28608,38553,26689,20625,27424,27770,28500,31348,32080,34880,35363,26376,20214,20537,20518,20581,20860,21048,21091,21927,22287,22533,23244,24314,25010,25080,25331,25458,26908,27177,29309,29356,29486,30740,30831,32121,30476,32937,35211,35609,36066,36562,36963,37749,38522,38997,39443,40568,20803,21407,21427,24187,24358,28187,28304,29572,29694,32067,33335,35328,35578,38480,20046,20491,21476,21628,22266,22993,23396,24049,24235,24359,25144,25925,26543,28246,29392,31946,34996,32929,32993,33776,34382,35463,36328,37431,38599,39015,40723,20116,20114,20237,21320,21577,21566,23087,24460,24481,24735,26791,27278,29786,30849,35486,35492,35703,37264,20062,39881,20132,20348,20399,20505,20502,20809,20844,21151,21177,21246,21402,21475,21521,21518,21897,22353,22434,22909,23380,23389,23439,24037,24039,24055,24184,24195,24218,24247,24344,24658,24908,25239,25304,25511,25915,26114,26179,26356,26477,26657,26775,27083,27743,27946,28009,28207,28317,30002,30343,30828,31295,31968,32005,32024,32094,32177,32789,32771,32943,32945,33108,33167,33322,33618,34892,34913,35611,36002,36092,37066,37237,37489,30783,37628,38308,38477,38917,39321,39640,40251,21083,21163,21495,21512,22741,25335,28640,35946,36703,40633,20811,21051,21578,22269,31296,37239,40288,40658,29508,28425,33136,29969,24573,24794,39592,29403,36796,27492,38915,20170,22256,22372,22718,23130,24680,25031,26127,26118,26681,26801,28151,30165,32058,33390,39746,20123,20304,21449,21766,23919,24038,24046,26619,27801,29811,30722,35408,37782,35039,22352,24231,25387,20661,20652,20877,26368,21705,22622,22971,23472,24425,25165,25505,26685,27507,28168,28797,37319,29312,30741,30758,31085,25998,32048,33756,35009,36617,38555,21092,22312,26448,32618,36001,20916,22338,38442,22586,27018,32948,21682,23822,22524,30869,40442,20316,21066,21643,25662,26152,26388,26613,31364,31574,32034,37679,26716,39853,31545,21273,20874,21047,23519,25334,25774,25830,26413,27578,34217,38609,30352,39894,25420,37638,39851,30399,26194,19977,20632,21442,23665,24808,25746,25955,26719,29158,29642,29987,31639,32386,34453,35715,36059,37240,39184,26028,26283,27531,20181,20180,20282,20351,21050,21496,21490,21987,22235,22763,22987,22985,23039,23376,23629,24066,24107,24535,24605,25351,25903,23388,26031,26045,26088,26525,27490,27515,27663,29509,31049,31169,31992,32025,32043,32930,33026,33267,35222,35422,35433,35430,35468,35566,36039,36060,38604,39164,27503,20107,20284,20365,20816,23383,23546,24904,25345,26178,27425,28363,27835,29246,29885,30164,30913,31034,32780,32819,33258,33940,36766,27728,40575,24335,35672,40235,31482,36600,23437,38635,19971,21489,22519,22833,23241,23460,24713,28287,28422,30142,36074,23455,34048,31712,20594,26612,33437,23649,34122,32286,33294,20889,23556,25448,36198,26012,29038,31038,32023,32773,35613,36554,36974,34503,37034,20511,21242,23610,26451,28796,29237,37196,37320,37675,33509,23490,24369,24825,20027,21462,23432,25163,26417,27530,29417,29664,31278,33131,36259,37202,39318,20754,21463,21610,23551,25480,27193,32172,38656,22234,21454,21608,23447,23601,24030,20462,24833,25342,27954,31168,31179,32066,32333,32722,33261,33311,33936,34886,35186,35728,36468,36655,36913,37195,37228,38598,37276,20160,20303,20805,21313,24467,25102,26580,27713,28171,29539,32294,37325,37507,21460,22809,23487,28113,31069,32302,31899,22654,29087,20986,34899,36848,20426,23803,26149,30636,31459,33308,39423,20934,24490,26092,26991,27529,28147,28310,28516,30462,32020,24033,36981,37255,38918,20966,21021,25152,26257,26329,28186,24246,32210,32626,26360,34223,34295,35576,21161,21465,22899,24207,24464,24661,37604,38500,20663,20767,21213,21280,21319,21484,21736,21830,21809,22039,22888,22974,23100,23477,23558,23567,23569,23578,24196,24202,24288,24432,25215,25220,25307,25484,25463,26119,26124,26157,26230,26494,26786,27167,27189,27836,28040,28169,28248,28988,28966,29031,30151,30465,30813,30977,31077,31216,31456,31505,31911,32057,32918,33750,33931,34121,34909,35059,35359,35388,35412,35443,35937,36062,37284,37478,37758,37912,38556,38808,19978,19976,19998,20055,20887,21104,22478,22580,22732,23330,24120,24773,25854,26465,26454,27972,29366,30067,31331,33976,35698,37304,37664,22065,22516,39166,25325,26893,27542,29165,32340,32887,33394,35302,39135,34645,36785,23611,20280,20449,20405,21767,23072,23517,23529,24515,24910,25391,26032,26187,26862,27035,28024,28145,30003,30137,30495,31070,31206,32051,33251,33455,34218,35242,35386,36523,36763,36914,37341,38663,20154,20161,20995,22645,22764,23563,29978,23613,33102,35338,36805,38499,38765,31525,35535,38920,37218,22259,21416,36887,21561,22402,24101,25512,27700,28810,30561,31883,32736,34928,36930,37204,37648,37656,38543,29790,39620,23815,23913,25968,26530,36264,38619,25454,26441,26905,33733,38935,38592,35070,28548,25722,23544,19990,28716,30045,26159,20932,21046,21218,22995,24449,24615,25104,25919,25972,26143,26228,26866,26646,27491,28165,29298,29983,30427,31934,32854,22768,35069,35199,35488,35475,35531,36893,37266,38738,38745,25993,31246,33030,38587,24109,24796,25114,26021,26132,26512,30707,31309,31821,32318,33034,36012,36196,36321,36447,30889,20999,25305,25509,25666,25240,35373,31363,31680,35500,38634,32118,33292,34633,20185,20808,21315,21344,23459,23554,23574,24029,25126,25159,25776,26643,26676,27849,27973,27927,26579,28508,29006,29053,26059,31359,31661,32218,32330,32680,33146,33307,33337,34214,35438,36046,36341,36984,36983,37549,37521,38275,39854,21069,21892,28472,28982,20840,31109,32341,33203,31950,22092,22609,23720,25514,26366,26365,26970,29401,30095,30094,30990,31062,31199,31895,32032,32068,34311,35380,38459,36961,40736,20711,21109,21452,21474,20489,21930,22766,22863,29245,23435,23652,21277,24803,24819,25436,25475,25407,25531,25805,26089,26361,24035,27085,27133,28437,29157,20105,30185,30456,31379,31967,32207,32156,32865,33609,33624,33900,33980,34299,35013,36208,36865,36973,37783,38684,39442,20687,22679,24974,33235,34101,36104,36896,20419,20596,21063,21363,24687,25417,26463,28204,36275,36895,20439,23646,36042,26063,32154,21330,34966,20854,25539,23384,23403,23562,25613,26449,36956,20182,22810,22826,27760,35409,21822,22549,22949,24816,25171,26561,33333,26965,38464,39364,39464,20307,22534,23550,32784,23729,24111,24453,24608,24907,25140,26367,27888,28382,32974,33151,33492,34955,36024,36864,36910,38538,40667,39899,20195,21488,22823,31532,37261,38988,40441,28381,28711,21331,21828,23429,25176,25246,25299,27810,28655,29730,35351,37944,28609,35582,33592,20967,34552,21482,21481,20294,36948,36784,22890,33073,24061,31466,36799,26842,35895,29432,40008,27197,35504,20025,21336,22022,22374,25285,25506,26086,27470,28129,28251,28845,30701,31471,31658,32187,32829,32966,34507,35477,37723,22243,22727,24382,26029,26262,27264,27573,30007,35527,20516,30693,22320,24347,24677,26234,27744,30196,31258,32622,33268,34584,36933,39347,31689,30044,31481,31569,33988,36880,31209,31378,33590,23265,30528,20013,20210,23449,24544,25277,26172,26609,27880,34411,34935,35387,37198,37619,39376,27159,28710,29482,33511,33879,36015,19969,20806,20939,21899,23541,24086,24115,24193,24340,24373,24427,24500,25074,25361,26274,26397,28526,29266,30010,30522,32884,33081,33144,34678,35519,35548,36229,36339,37530,38263,38914,40165,21189,25431,30452,26389,27784,29645,36035,37806,38515,27941,22684,26894,27084,36861,37786,30171,36890,22618,26626,25524,27131,20291,28460,26584,36795,34086,32180,37716,26943,28528,22378,22775,23340,32044,29226,21514,37347,40372,20141,20302,20572,20597,21059,35998,21576,22564,23450,24093,24213,24237,24311,24351,24716,25269,25402,25552,26799,27712,30855,31118,31243,32224,33351,35330,35558,36420,36883,37048,37165,37336,40718,27877,25688,25826,25973,28404,30340,31515,36969,37841,28346,21746,24505,25764,36685,36845,37444,20856,22635,22825,23637,24215,28155,32399,29980,36028,36578,39003,28857,20253,27583,28593,3e4,38651,20814,21520,22581,22615,22956,23648,24466,26007,26460,28193,30331,33759,36077,36884,37117,37709,30757,30778,21162,24230,22303,22900,24594,20498,20826,20908,20941,20992,21776,22612,22616,22871,23445,23798,23947,24764,25237,25645,26481,26691,26812,26847,30423,28120,28271,28059,28783,29128,24403,30168,31095,31561,31572,31570,31958,32113,21040,33891,34153,34276,35342,35588,35910,36367,36867,36879,37913,38518,38957,39472,38360,20685,21205,21516,22530,23566,24999,25758,27934,30643,31461,33012,33796,36947,37509,23776,40199,21311,24471,24499,28060,29305,30563,31167,31716,27602,29420,35501,26627,27233,20984,31361,26932,23626,40182,33515,23493,37193,28702,22136,23663,24775,25958,27788,35930,36929,38931,21585,26311,37389,22856,37027,20869,20045,20970,34201,35598,28760,25466,37707,26978,39348,32260,30071,21335,26976,36575,38627,27741,20108,23612,24336,36841,21250,36049,32905,34425,24319,26085,20083,20837,22914,23615,38894,20219,22922,24525,35469,28641,31152,31074,23527,33905,29483,29105,24180,24565,25467,25754,29123,31896,20035,24316,20043,22492,22178,24745,28611,32013,33021,33075,33215,36786,35223,34468,24052,25226,25773,35207,26487,27874,27966,29750,30772,23110,32629,33453,39340,20467,24259,25309,25490,25943,26479,30403,29260,32972,32954,36649,37197,20493,22521,23186,26757,26995,29028,29437,36023,22770,36064,38506,36889,34687,31204,30695,33833,20271,21093,21338,25293,26575,27850,30333,31636,31893,33334,34180,36843,26333,28448,29190,32283,33707,39361,40614,20989,31665,30834,31672,32903,31560,27368,24161,32908,30033,30048,20843,37474,28300,30330,37271,39658,20240,32624,25244,31567,38309,40169,22138,22617,34532,38588,20276,21028,21322,21453,21467,24070,25644,26001,26495,27710,27726,29256,29359,29677,30036,32321,33324,34281,36009,31684,37318,29033,38930,39151,25405,26217,30058,30436,30928,34115,34542,21290,21329,21542,22915,24199,24444,24754,25161,25209,25259,26e3,27604,27852,30130,30382,30865,31192,32203,32631,32933,34987,35513,36027,36991,38750,39131,27147,31800,20633,23614,24494,26503,27608,29749,30473,32654,40763,26570,31255,21305,30091,39661,24422,33181,33777,32920,24380,24517,30050,31558,36924,26727,23019,23195,32016,30334,35628,20469,24426,27161,27703,28418,29922,31080,34920,35413,35961,24287,25551,30149,31186,33495,37672,37618,33948,34541,39981,21697,24428,25996,27996,28693,36007,36051,38971,25935,29942,19981,20184,22496,22827,23142,23500,20904,24067,24220,24598,25206,25975,26023,26222,28014,29238,31526,33104,33178,33433,35676,36e3,36070,36212,38428,38468,20398,25771,27494,33310,33889,34154,37096,23553,26963,39080,33914,34135,20239,21103,24489,24133,26381,31119,33145,35079,35206,28149,24343,25173,27832,20175,29289,39826,20998,21563,22132,22707,24996,25198,28954,22894,31881,31966,32027,38640,25991,32862,19993,20341,20853,22592,24163,24179,24330,26564,20006,34109,38281,38491,31859,38913,20731,22721,30294,30887,21029,30629,34065,31622,20559,22793,29255,31687,32232,36794,36820,36941,20415,21193,23081,24321,38829,20445,33303,37610,22275,25429,27497,29995,35036,36628,31298,21215,22675,24917,25098,26286,27597,31807,33769,20515,20472,21253,21574,22577,22857,23453,23792,23791,23849,24214,25265,25447,25918,26041,26379,27861,27873,28921,30770,32299,32990,33459,33804,34028,34562,35090,35370,35914,37030,37586,39165,40179,40300,20047,20129,20621,21078,22346,22952,24125,24536,24537,25151,26292,26395,26576,26834,20882,32033,32938,33192,35584,35980,36031,37502,38450,21536,38956,21271,20693,21340,22696,25778,26420,29287,30566,31302,37350,21187,27809,27526,22528,24140,22868,26412,32763,20961,30406,25705,30952,39764,40635,22475,22969,26151,26522,27598,21737,27097,24149,33180,26517,39850,26622,40018,26717,20134,20451,21448,25273,26411,27819,36804,20397,32365,40639,19975,24930,28288,28459,34067,21619,26410,39749,24051,31637,23724,23494,34588,28234,34001,31252,33032,22937,31885,27665,30496,21209,22818,28961,29279,30683,38695,40289,26891,23167,23064,20901,21517,21629,26126,30431,36855,37528,40180,23018,29277,28357,20813,26825,32191,32236,38754,40634,25720,27169,33538,22916,23391,27611,29467,30450,32178,32791,33945,20786,26408,40665,30446,26466,21247,39173,23588,25147,31870,36016,21839,24758,32011,38272,21249,20063,20918,22812,29242,32822,37326,24357,30690,21380,24441,32004,34220,35379,36493,38742,26611,34222,37971,24841,24840,27833,30290,35565,36664,21807,20305,20778,21191,21451,23461,24189,24736,24962,25558,26377,26586,28263,28044,29494,29495,30001,31056,35029,35480,36938,37009,37109,38596,34701,22805,20104,20313,19982,35465,36671,38928,20653,24188,22934,23481,24248,25562,25594,25793,26332,26954,27096,27915,28342,29076,29992,31407,32650,32768,33865,33993,35201,35617,36362,36965,38525,39178,24958,25233,27442,27779,28020,32716,32764,28096,32645,34746,35064,26469,33713,38972,38647,27931,32097,33853,37226,20081,21365,23888,27396,28651,34253,34349,35239,21033,21519,23653,26446,26792,29702,29827,30178,35023,35041,37324,38626,38520,24459,29575,31435,33870,25504,30053,21129,27969,28316,29705,30041,30827,31890,38534,31452,40845,20406,24942,26053,34396,20102,20142,20698,20001,20940,23534,26009,26753,28092,29471,30274,30637,31260,31975,33391,35538,36988,37327,38517,38936,21147,32209,20523,21400,26519,28107,29136,29747,33256,36650,38563,40023,40607,29792,22593,28057,32047,39006,20196,20278,20363,20919,21169,23994,24604,29618,31036,33491,37428,38583,38646,38666,40599,40802,26278,27508,21015,21155,28872,35010,24265,24651,24976,28451,29001,31806,32244,32879,34030,36899,37676,21570,39791,27347,28809,36034,36335,38706,21172,23105,24266,24324,26391,27004,27028,28010,28431,29282,29436,31725,32769,32894,34635,37070,20845,40595,31108,32907,37682,35542,20525,21644,35441,27498,36036,33031,24785,26528,40434,20121,20120,39952,35435,34241,34152,26880,28286,30871,33109,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,24332,19984,19989,20010,20017,20022,20028,20031,20034,20054,20056,20098,20101,35947,20106,33298,24333,20110,20126,20127,20128,20130,20144,20147,20150,20174,20173,20164,20166,20162,20183,20190,20205,20191,20215,20233,20314,20272,20315,20317,20311,20295,20342,20360,20367,20376,20347,20329,20336,20369,20335,20358,20374,20760,20436,20447,20430,20440,20443,20433,20442,20432,20452,20453,20506,20520,20500,20522,20517,20485,20252,20470,20513,20521,20524,20478,20463,20497,20486,20547,20551,26371,20565,20560,20552,20570,20566,20588,20600,20608,20634,20613,20660,20658,20681,20682,20659,20674,20694,20702,20709,20717,20707,20718,20729,20725,20745,20737,20738,20758,20757,20756,20762,20769,20794,20791,20796,20795,20799,20800,20818,20812,20820,20834,31480,20841,20842,20846,20864,20866,22232,20876,20873,20879,20881,20883,20885,20886,20900,20902,20898,20905,20906,20907,20915,20913,20914,20912,20917,20925,20933,20937,20955,20960,34389,20969,20973,20976,20981,20990,20996,21003,21012,21006,21031,21034,21038,21043,21049,21071,21060,21067,21068,21086,21076,21098,21108,21097,21107,21119,21117,21133,21140,21138,21105,21128,21137,36776,36775,21164,21165,21180,21173,21185,21197,21207,21214,21219,21222,39149,21216,21235,21237,21240,21241,21254,21256,30008,21261,21264,21263,21269,21274,21283,21295,21297,21299,21304,21312,21318,21317,19991,21321,21325,20950,21342,21353,21358,22808,21371,21367,21378,21398,21408,21414,21413,21422,21424,21430,21443,31762,38617,21471,26364,29166,21486,21480,21485,21498,21505,21565,21568,21548,21549,21564,21550,21558,21545,21533,21582,21647,21621,21646,21599,21617,21623,21616,21650,21627,21632,21622,21636,21648,21638,21703,21666,21688,21669,21676,21700,21704,21672,21675,21698,21668,21694,21692,21720,21733,21734,21775,21780,21757,21742,21741,21754,21730,21817,21824,21859,21836,21806,21852,21829,21846,21847,21816,21811,21853,21913,21888,21679,21898,21919,21883,21886,21912,21918,21934,21884,21891,21929,21895,21928,21978,21957,21983,21956,21980,21988,21972,22036,22007,22038,22014,22013,22043,22009,22094,22096,29151,22068,22070,22066,22072,22123,22116,22063,22124,22122,22150,22144,22154,22176,22164,22159,22181,22190,22198,22196,22210,22204,22209,22211,22208,22216,22222,22225,22227,22231,22254,22265,22272,22271,22276,22281,22280,22283,22285,22291,22296,22294,21959,22300,22310,22327,22328,22350,22331,22336,22351,22377,22464,22408,22369,22399,22409,22419,22432,22451,22436,22442,22448,22467,22470,22484,22482,22483,22538,22486,22499,22539,22553,22557,22642,22561,22626,22603,22640,27584,22610,22589,22649,22661,22713,22687,22699,22714,22750,22715,22712,22702,22725,22739,22737,22743,22745,22744,22757,22748,22756,22751,22767,22778,22777,22779,22780,22781,22786,22794,22800,22811,26790,22821,22828,22829,22834,22840,22846,31442,22869,22864,22862,22874,22872,22882,22880,22887,22892,22889,22904,22913,22941,20318,20395,22947,22962,22982,23016,23004,22925,23001,23002,23077,23071,23057,23068,23049,23066,23104,23148,23113,23093,23094,23138,23146,23194,23228,23230,23243,23234,23229,23267,23255,23270,23273,23254,23290,23291,23308,23307,23318,23346,23248,23338,23350,23358,23363,23365,23360,23377,23381,23386,23387,23397,23401,23408,23411,23413,23416,25992,23418,23424,23427,23462,23480,23491,23495,23497,23508,23504,23524,23526,23522,23518,23525,23531,23536,23542,23539,23557,23559,23560,23565,23571,23584,23586,23592,23608,23609,23617,23622,23630,23635,23632,23631,23409,23660,23662,20066,23670,23673,23692,23697,23700,22939,23723,23739,23734,23740,23735,23749,23742,23751,23769,23785,23805,23802,23789,23948,23786,23819,23829,23831,23900,23839,23835,23825,23828,23842,23834,23833,23832,23884,23890,23886,23883,23916,23923,23926,23943,23940,23938,23970,23965,23980,23982,23997,23952,23991,23996,24009,24013,24019,24018,24022,24027,24043,24050,24053,24075,24090,24089,24081,24091,24118,24119,24132,24131,24128,24142,24151,24148,24159,24162,24164,24135,24181,24182,24186,40636,24191,24224,24257,24258,24264,24272,24271,24278,24291,24285,24282,24283,24290,24289,24296,24297,24300,24305,24307,24304,24308,24312,24318,24323,24329,24413,24412,24331,24337,24342,24361,24365,24376,24385,24392,24396,24398,24367,24401,24406,24407,24409,24417,24429,24435,24439,24451,24450,24447,24458,24456,24465,24455,24478,24473,24472,24480,24488,24493,24508,24534,24571,24548,24568,24561,24541,24755,24575,24609,24672,24601,24592,24617,24590,24625,24603,24597,24619,24614,24591,24634,24666,24641,24682,24695,24671,24650,24646,24653,24675,24643,24676,24642,24684,24683,24665,24705,24717,24807,24707,24730,24708,24731,24726,24727,24722,24743,24715,24801,24760,24800,24787,24756,24560,24765,24774,24757,24792,24909,24853,24838,24822,24823,24832,24820,24826,24835,24865,24827,24817,24845,24846,24903,24894,24872,24871,24906,24895,24892,24876,24884,24893,24898,24900,24947,24951,24920,24921,24922,24939,24948,24943,24933,24945,24927,24925,24915,24949,24985,24982,24967,25004,24980,24986,24970,24977,25003,25006,25036,25034,25033,25079,25032,25027,25030,25018,25035,32633,25037,25062,25059,25078,25082,25076,25087,25085,25084,25086,25088,25096,25097,25101,25100,25108,25115,25118,25121,25130,25134,25136,25138,25139,25153,25166,25182,25187,25179,25184,25192,25212,25218,25225,25214,25234,25235,25238,25300,25219,25236,25303,25297,25275,25295,25343,25286,25812,25288,25308,25292,25290,25282,25287,25243,25289,25356,25326,25329,25383,25346,25352,25327,25333,25424,25406,25421,25628,25423,25494,25486,25472,25515,25462,25507,25487,25481,25503,25525,25451,25449,25534,25577,25536,25542,25571,25545,25554,25590,25540,25622,25652,25606,25619,25638,25654,25885,25623,25640,25615,25703,25711,25718,25678,25898,25749,25747,25765,25769,25736,25788,25818,25810,25797,25799,25787,25816,25794,25841,25831,33289,25824,25825,25260,25827,25839,25900,25846,25844,25842,25850,25856,25853,25880,25884,25861,25892,25891,25899,25908,25909,25911,25910,25912,30027,25928,25942,25941,25933,25944,25950,25949,25970,25976,25986,25987,35722,26011,26015,26027,26039,26051,26054,26049,26052,26060,26066,26075,26073,26080,26081,26097,26482,26122,26115,26107,26483,26165,26166,26164,26140,26191,26180,26185,26177,26206,26205,26212,26215,26216,26207,26210,26224,26243,26248,26254,26249,26244,26264,26269,26305,26297,26313,26302,26300,26308,26296,26326,26330,26336,26175,26342,26345,26352,26357,26359,26383,26390,26398,26406,26407,38712,26414,26431,26422,26433,26424,26423,26438,26462,26464,26457,26467,26468,26505,26480,26537,26492,26474,26508,26507,26534,26529,26501,26551,26607,26548,26604,26547,26601,26552,26596,26590,26589,26594,26606,26553,26574,26566,26599,27292,26654,26694,26665,26688,26701,26674,26702,26803,26667,26713,26723,26743,26751,26783,26767,26797,26772,26781,26779,26755,27310,26809,26740,26805,26784,26810,26895,26765,26750,26881,26826,26888,26840,26914,26918,26849,26892,26829,26836,26855,26837,26934,26898,26884,26839,26851,26917,26873,26848,26863,26920,26922,26906,26915,26913,26822,27001,26999,26972,27e3,26987,26964,27006,26990,26937,26996,26941,26969,26928,26977,26974,26973,27009,26986,27058,27054,27088,27071,27073,27091,27070,27086,23528,27082,27101,27067,27075,27047,27182,27025,27040,27036,27029,27060,27102,27112,27138,27163,27135,27402,27129,27122,27111,27141,27057,27166,27117,27156,27115,27146,27154,27329,27171,27155,27204,27148,27250,27190,27256,27207,27234,27225,27238,27208,27192,27170,27280,27277,27296,27268,27298,27299,27287,34327,27323,27331,27330,27320,27315,27308,27358,27345,27359,27306,27354,27370,27387,27397,34326,27386,27410,27414,39729,27423,27448,27447,30428,27449,39150,27463,27459,27465,27472,27481,27476,27483,27487,27489,27512,27513,27519,27520,27524,27523,27533,27544,27541,27550,27556,27562,27563,27567,27570,27569,27571,27575,27580,27590,27595,27603,27615,27628,27627,27635,27631,40638,27656,27667,27668,27675,27684,27683,27742,27733,27746,27754,27778,27789,27802,27777,27803,27774,27752,27763,27794,27792,27844,27889,27859,27837,27863,27845,27869,27822,27825,27838,27834,27867,27887,27865,27882,27935,34893,27958,27947,27965,27960,27929,27957,27955,27922,27916,28003,28051,28004,27994,28025,27993,28046,28053,28644,28037,28153,28181,28170,28085,28103,28134,28088,28102,28140,28126,28108,28136,28114,28101,28154,28121,28132,28117,28138,28142,28205,28270,28206,28185,28274,28255,28222,28195,28267,28203,28278,28237,28191,28227,28218,28238,28196,28415,28189,28216,28290,28330,28312,28361,28343,28371,28349,28335,28356,28338,28372,28373,28303,28325,28354,28319,28481,28433,28748,28396,28408,28414,28479,28402,28465,28399,28466,28364,28478,28435,28407,28550,28538,28536,28545,28544,28527,28507,28659,28525,28546,28540,28504,28558,28561,28610,28518,28595,28579,28577,28580,28601,28614,28586,28639,28629,28652,28628,28632,28657,28654,28635,28681,28683,28666,28689,28673,28687,28670,28699,28698,28532,28701,28696,28703,28720,28734,28722,28753,28771,28825,28818,28847,28913,28844,28856,28851,28846,28895,28875,28893,28889,28937,28925,28956,28953,29029,29013,29064,29030,29026,29004,29014,29036,29071,29179,29060,29077,29096,29100,29143,29113,29118,29138,29129,29140,29134,29152,29164,29159,29173,29180,29177,29183,29197,29200,29211,29224,29229,29228,29232,29234,29243,29244,29247,29248,29254,29259,29272,29300,29310,29314,29313,29319,29330,29334,29346,29351,29369,29362,29379,29382,29380,29390,29394,29410,29408,29409,29433,29431,20495,29463,29450,29468,29462,29469,29492,29487,29481,29477,29502,29518,29519,40664,29527,29546,29544,29552,29560,29557,29563,29562,29640,29619,29646,29627,29632,29669,29678,29662,29858,29701,29807,29733,29688,29746,29754,29781,29759,29791,29785,29761,29788,29801,29808,29795,29802,29814,29822,29835,29854,29863,29898,29903,29908,29681,29920,29923,29927,29929,29934,29938,29936,29937,29944,29943,29956,29955,29957,29964,29966,29965,29973,29971,29982,29990,29996,30012,30020,30029,30026,30025,30043,30022,30042,30057,30052,30055,30059,30061,30072,30070,30086,30087,30068,30090,30089,30082,30100,30106,30109,30117,30115,30146,30131,30147,30133,30141,30136,30140,30129,30157,30154,30162,30169,30179,30174,30206,30207,30204,30209,30192,30202,30194,30195,30219,30221,30217,30239,30247,30240,30241,30242,30244,30260,30256,30267,30279,30280,30278,30300,30296,30305,30306,30312,30313,30314,30311,30316,30320,30322,30326,30328,30332,30336,30339,30344,30347,30350,30358,30355,30361,30362,30384,30388,30392,30393,30394,30402,30413,30422,30418,30430,30433,30437,30439,30442,34351,30459,30472,30471,30468,30505,30500,30494,30501,30502,30491,30519,30520,30535,30554,30568,30571,30555,30565,30591,30590,30585,30606,30603,30609,30624,30622,30640,30646,30649,30655,30652,30653,30651,30663,30669,30679,30682,30684,30691,30702,30716,30732,30738,31014,30752,31018,30789,30862,30836,30854,30844,30874,30860,30883,30901,30890,30895,30929,30918,30923,30932,30910,30908,30917,30922,30956,30951,30938,30973,30964,30983,30994,30993,31001,31020,31019,31040,31072,31063,31071,31066,31061,31059,31098,31103,31114,31133,31143,40779,31146,31150,31155,31161,31162,31177,31189,31207,31212,31201,31203,31240,31245,31256,31257,31264,31263,31104,31281,31291,31294,31287,31299,31319,31305,31329,31330,31337,40861,31344,31353,31357,31368,31383,31381,31384,31382,31401,31432,31408,31414,31429,31428,31423,36995,31431,31434,31437,31439,31445,31443,31449,31450,31453,31457,31458,31462,31469,31472,31490,31503,31498,31494,31539,31512,31513,31518,31541,31528,31542,31568,31610,31492,31565,31499,31564,31557,31605,31589,31604,31591,31600,31601,31596,31598,31645,31640,31647,31629,31644,31642,31627,31634,31631,31581,31641,31691,31681,31692,31695,31668,31686,31709,31721,31761,31764,31718,31717,31840,31744,31751,31763,31731,31735,31767,31757,31734,31779,31783,31786,31775,31799,31787,31805,31820,31811,31828,31823,31808,31824,31832,31839,31844,31830,31845,31852,31861,31875,31888,31908,31917,31906,31915,31905,31912,31923,31922,31921,31918,31929,31933,31936,31941,31938,31960,31954,31964,31970,39739,31983,31986,31988,31990,31994,32006,32002,32028,32021,32010,32069,32075,32046,32050,32063,32053,32070,32115,32086,32078,32114,32104,32110,32079,32099,32147,32137,32091,32143,32125,32155,32186,32174,32163,32181,32199,32189,32171,32317,32162,32175,32220,32184,32159,32176,32216,32221,32228,32222,32251,32242,32225,32261,32266,32291,32289,32274,32305,32287,32265,32267,32290,32326,32358,32315,32309,32313,32323,32311,32306,32314,32359,32349,32342,32350,32345,32346,32377,32362,32361,32380,32379,32387,32213,32381,36782,32383,32392,32393,32396,32402,32400,32403,32404,32406,32398,32411,32412,32568,32570,32581,32588,32589,32590,32592,32593,32597,32596,32600,32607,32608,32616,32617,32615,32632,32642,32646,32643,32648,32647,32652,32660,32670,32669,32666,32675,32687,32690,32697,32686,32694,32696,35697,32709,32710,32714,32725,32724,32737,32742,32745,32755,32761,39132,32774,32772,32779,32786,32792,32793,32796,32801,32808,32831,32827,32842,32838,32850,32856,32858,32863,32866,32872,32883,32882,32880,32886,32889,32893,32895,32900,32902,32901,32923,32915,32922,32941,20880,32940,32987,32997,32985,32989,32964,32986,32982,33033,33007,33009,33051,33065,33059,33071,33099,38539,33094,33086,33107,33105,33020,33137,33134,33125,33126,33140,33155,33160,33162,33152,33154,33184,33173,33188,33187,33119,33171,33193,33200,33205,33214,33208,33213,33216,33218,33210,33225,33229,33233,33241,33240,33224,33242,33247,33248,33255,33274,33275,33278,33281,33282,33285,33287,33290,33293,33296,33302,33321,33323,33336,33331,33344,33369,33368,33373,33370,33375,33380,33378,33384,33386,33387,33326,33393,33399,33400,33406,33421,33426,33451,33439,33467,33452,33505,33507,33503,33490,33524,33523,33530,33683,33539,33531,33529,33502,33542,33500,33545,33497,33589,33588,33558,33586,33585,33600,33593,33616,33605,33583,33579,33559,33560,33669,33690,33706,33695,33698,33686,33571,33678,33671,33674,33660,33717,33651,33653,33696,33673,33704,33780,33811,33771,33742,33789,33795,33752,33803,33729,33783,33799,33760,33778,33805,33826,33824,33725,33848,34054,33787,33901,33834,33852,34138,33924,33911,33899,33965,33902,33922,33897,33862,33836,33903,33913,33845,33994,33890,33977,33983,33951,34009,33997,33979,34010,34e3,33985,33990,34006,33953,34081,34047,34036,34071,34072,34092,34079,34069,34068,34044,34112,34147,34136,34120,34113,34306,34123,34133,34176,34212,34184,34193,34186,34216,34157,34196,34203,34282,34183,34204,34167,34174,34192,34249,34234,34255,34233,34256,34261,34269,34277,34268,34297,34314,34323,34315,34302,34298,34310,34338,34330,34352,34367,34381,20053,34388,34399,34407,34417,34451,34467,34473,34474,34443,34444,34486,34479,34500,34502,34480,34505,34851,34475,34516,34526,34537,34540,34527,34523,34543,34578,34566,34568,34560,34563,34555,34577,34569,34573,34553,34570,34612,34623,34615,34619,34597,34601,34586,34656,34655,34680,34636,34638,34676,34647,34664,34670,34649,34643,34659,34666,34821,34722,34719,34690,34735,34763,34749,34752,34768,38614,34731,34756,34739,34759,34758,34747,34799,34802,34784,34831,34829,34814,34806,34807,34830,34770,34833,34838,34837,34850,34849,34865,34870,34873,34855,34875,34884,34882,34898,34905,34910,34914,34923,34945,34942,34974,34933,34941,34997,34930,34946,34967,34962,34990,34969,34978,34957,34980,34992,35007,34993,35011,35012,35028,35032,35033,35037,35065,35074,35068,35060,35048,35058,35076,35084,35082,35091,35139,35102,35109,35114,35115,35137,35140,35131,35126,35128,35148,35101,35168,35166,35174,35172,35181,35178,35183,35188,35191,35198,35203,35208,35210,35219,35224,35233,35241,35238,35244,35247,35250,35258,35261,35263,35264,35290,35292,35293,35303,35316,35320,35331,35350,35344,35340,35355,35357,35365,35382,35393,35419,35410,35398,35400,35452,35437,35436,35426,35461,35458,35460,35496,35489,35473,35493,35494,35482,35491,35524,35533,35522,35546,35563,35571,35559,35556,35569,35604,35552,35554,35575,35550,35547,35596,35591,35610,35553,35606,35600,35607,35616,35635,38827,35622,35627,35646,35624,35649,35660,35663,35662,35657,35670,35675,35674,35691,35679,35692,35695,35700,35709,35712,35724,35726,35730,35731,35734,35737,35738,35898,35905,35903,35912,35916,35918,35920,35925,35938,35948,35960,35962,35970,35977,35973,35978,35981,35982,35988,35964,35992,25117,36013,36010,36029,36018,36019,36014,36022,36040,36033,36068,36067,36058,36093,36090,36091,36100,36101,36106,36103,36111,36109,36112,40782,36115,36045,36116,36118,36199,36205,36209,36211,36225,36249,36290,36286,36282,36303,36314,36310,36300,36315,36299,36330,36331,36319,36323,36348,36360,36361,36351,36381,36382,36368,36383,36418,36405,36400,36404,36426,36423,36425,36428,36432,36424,36441,36452,36448,36394,36451,36437,36470,36466,36476,36481,36487,36485,36484,36491,36490,36499,36497,36500,36505,36522,36513,36524,36528,36550,36529,36542,36549,36552,36555,36571,36579,36604,36603,36587,36606,36618,36613,36629,36626,36633,36627,36636,36639,36635,36620,36646,36659,36667,36665,36677,36674,36670,36684,36681,36678,36686,36695,36700,36706,36707,36708,36764,36767,36771,36781,36783,36791,36826,36837,36834,36842,36847,36999,36852,36869,36857,36858,36881,36885,36897,36877,36894,36886,36875,36903,36918,36917,36921,36856,36943,36944,36945,36946,36878,36937,36926,36950,36952,36958,36968,36975,36982,38568,36978,36994,36989,36993,36992,37002,37001,37007,37032,37039,37041,37045,37090,37092,25160,37083,37122,37138,37145,37170,37168,37194,37206,37208,37219,37221,37225,37235,37234,37259,37257,37250,37282,37291,37295,37290,37301,37300,37306,37312,37313,37321,37323,37328,37334,37343,37345,37339,37372,37365,37366,37406,37375,37396,37420,37397,37393,37470,37463,37445,37449,37476,37448,37525,37439,37451,37456,37532,37526,37523,37531,37466,37583,37561,37559,37609,37647,37626,37700,37678,37657,37666,37658,37667,37690,37685,37691,37724,37728,37756,37742,37718,37808,37804,37805,37780,37817,37846,37847,37864,37861,37848,37827,37853,37840,37832,37860,37914,37908,37907,37891,37895,37904,37942,37931,37941,37921,37946,37953,37970,37956,37979,37984,37986,37982,37994,37417,38e3,38005,38007,38013,37978,38012,38014,38017,38015,38274,38279,38282,38292,38294,38296,38297,38304,38312,38311,38317,38332,38331,38329,38334,38346,28662,38339,38349,38348,38357,38356,38358,38364,38369,38373,38370,38433,38440,38446,38447,38466,38476,38479,38475,38519,38492,38494,38493,38495,38502,38514,38508,38541,38552,38549,38551,38570,38567,38577,38578,38576,38580,38582,38584,38585,38606,38603,38601,38605,35149,38620,38669,38613,38649,38660,38662,38664,38675,38670,38673,38671,38678,38681,38692,38698,38704,38713,38717,38718,38724,38726,38728,38722,38729,38748,38752,38756,38758,38760,21202,38763,38769,38777,38789,38780,38785,38778,38790,38795,38799,38800,38812,38824,38822,38819,38835,38836,38851,38854,38856,38859,38876,38893,40783,38898,31455,38902,38901,38927,38924,38968,38948,38945,38967,38973,38982,38991,38987,39019,39023,39024,39025,39028,39027,39082,39087,39089,39094,39108,39107,39110,39145,39147,39171,39177,39186,39188,39192,39201,39197,39198,39204,39200,39212,39214,39229,39230,39234,39241,39237,39248,39243,39249,39250,39244,39253,39319,39320,39333,39341,39342,39356,39391,39387,39389,39384,39377,39405,39406,39409,39410,39419,39416,39425,39439,39429,39394,39449,39467,39479,39493,39490,39488,39491,39486,39509,39501,39515,39511,39519,39522,39525,39524,39529,39531,39530,39597,39600,39612,39616,39631,39633,39635,39636,39646,39647,39650,39651,39654,39663,39659,39662,39668,39665,39671,39675,39686,39704,39706,39711,39714,39715,39717,39719,39720,39721,39722,39726,39727,39730,39748,39747,39759,39757,39758,39761,39768,39796,39827,39811,39825,39830,39831,39839,39840,39848,39860,39872,39882,39865,39878,39887,39889,39890,39907,39906,39908,39892,39905,39994,39922,39921,39920,39957,39956,39945,39955,39948,39942,39944,39954,39946,39940,39982,39963,39973,39972,39969,39984,40007,39986,40006,39998,40026,40032,40039,40054,40056,40167,40172,40176,40201,40200,40171,40195,40198,40234,40230,40367,40227,40223,40260,40213,40210,40257,40255,40254,40262,40264,40285,40286,40292,40273,40272,40281,40306,40329,40327,40363,40303,40314,40346,40356,40361,40370,40388,40385,40379,40376,40378,40390,40399,40386,40409,40403,40440,40422,40429,40431,40445,40474,40475,40478,40565,40569,40573,40577,40584,40587,40588,40594,40597,40593,40605,40613,40617,40632,40618,40621,38753,40652,40654,40655,40656,40660,40668,40670,40669,40672,40677,40680,40687,40692,40694,40695,40697,40699,40700,40701,40711,40712,30391,40725,40737,40748,40766,40778,40786,40788,40803,40799,40800,40801,40806,40807,40812,40810,40823,40818,40822,40853,40860,40864,22575,27079,36953,29796,20956,29081,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,65506,65508,65287,65282,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,65506,65508,65287,65282,12849,8470,8481,8757,32394,35100,37704,37512,34012,20425,28859,26161,26824,37625,26363,24389,20008,20193,20220,20224,20227,20281,20310,20370,20362,20378,20372,20429,20544,20514,20479,20510,20550,20592,20546,20628,20724,20696,20810,20836,20893,20926,20972,21013,21148,21158,21184,21211,21248,21255,21284,21362,21395,21426,21469,64014,21660,21642,21673,21759,21894,22361,22373,22444,22472,22471,64015,64016,22686,22706,22795,22867,22875,22877,22883,22948,22970,23382,23488,29999,23512,23532,23582,23718,23738,23797,23847,23891,64017,23874,23917,23992,23993,24016,24353,24372,24423,24503,24542,24669,24709,24714,24798,24789,24864,24818,24849,24887,24880,24984,25107,25254,25589,25696,25757,25806,25934,26112,26133,26171,26121,26158,26142,26148,26213,26199,26201,64018,26227,26265,26272,26290,26303,26362,26382,63785,26470,26555,26706,26560,26625,26692,26831,64019,26984,64020,27032,27106,27184,27243,27206,27251,27262,27362,27364,27606,27711,27740,27782,27759,27866,27908,28039,28015,28054,28076,28111,28152,28146,28156,28217,28252,28199,28220,28351,28552,28597,28661,28677,28679,28712,28805,28843,28943,28932,29020,28998,28999,64021,29121,29182,29361,29374,29476,64022,29559,29629,29641,29654,29667,29650,29703,29685,29734,29738,29737,29742,29794,29833,29855,29953,30063,30338,30364,30366,30363,30374,64023,30534,21167,30753,30798,30820,30842,31024,64024,64025,64026,31124,64027,31131,31441,31463,64028,31467,31646,64029,32072,32092,32183,32160,32214,32338,32583,32673,64030,33537,33634,33663,33735,33782,33864,33972,34131,34137,34155,64031,34224,64032,64033,34823,35061,35346,35383,35449,35495,35518,35551,64034,35574,35667,35711,36080,36084,36114,36214,64035,36559,64036,64037,36967,37086,64038,37141,37159,37338,37335,37342,37357,37358,37348,37349,37382,37392,37386,37434,37440,37436,37454,37465,37457,37433,37479,37543,37495,37496,37607,37591,37593,37584,64039,37589,37600,37587,37669,37665,37627,64040,37662,37631,37661,37634,37744,37719,37796,37830,37854,37880,37937,37957,37960,38290,63964,64041,38557,38575,38707,38715,38723,38733,38735,38737,38741,38999,39013,64042,64043,39207,64044,39326,39502,39641,39644,39797,39794,39823,39857,39867,39936,40304,40299,64045,40473,40657,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],jis0212:[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,728,711,184,729,733,175,731,730,65374,900,901,null,null,null,null,null,null,null,null,161,166,191,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,186,170,169,174,8482,164,8470,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,902,904,905,906,938,null,908,null,910,939,null,911,null,null,null,null,940,941,942,943,970,912,972,962,973,971,944,974,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1038,1039,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1118,1119,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,198,272,null,294,null,306,null,321,319,null,330,216,338,null,358,222,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,230,273,240,295,305,307,312,322,320,329,331,248,339,223,359,254,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,193,192,196,194,258,461,256,260,197,195,262,264,268,199,266,270,201,200,203,202,282,278,274,280,null,284,286,290,288,292,205,204,207,206,463,304,298,302,296,308,310,313,317,315,323,327,325,209,211,210,214,212,465,336,332,213,340,344,342,346,348,352,350,356,354,218,217,220,219,364,467,368,362,370,366,360,471,475,473,469,372,221,376,374,377,381,379,null,null,null,null,null,null,null,225,224,228,226,259,462,257,261,229,227,263,265,269,231,267,271,233,232,235,234,283,279,275,281,501,285,287,null,289,293,237,236,239,238,464,null,299,303,297,309,311,314,318,316,324,328,326,241,243,242,246,244,466,337,333,245,341,345,343,347,349,353,351,357,355,250,249,252,251,365,468,369,363,371,367,361,472,476,474,470,373,253,255,375,378,382,380,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,19970,19972,19973,19980,19986,19999,20003,20004,20008,20011,20014,20015,20016,20021,20032,20033,20036,20039,20049,20058,20060,20067,20072,20073,20084,20085,20089,20095,20109,20118,20119,20125,20143,20153,20163,20176,20186,20187,20192,20193,20194,20200,20207,20209,20211,20213,20221,20222,20223,20224,20226,20227,20232,20235,20236,20242,20245,20246,20247,20249,20270,20273,20320,20275,20277,20279,20281,20283,20286,20288,20290,20296,20297,20299,20300,20306,20308,20310,20312,20319,20323,20330,20332,20334,20337,20343,20344,20345,20346,20349,20350,20353,20354,20356,20357,20361,20362,20364,20366,20368,20370,20371,20372,20375,20377,20378,20382,20383,20402,20407,20409,20411,20412,20413,20414,20416,20417,20421,20422,20424,20425,20427,20428,20429,20431,20434,20444,20448,20450,20464,20466,20476,20477,20479,20480,20481,20484,20487,20490,20492,20494,20496,20499,20503,20504,20507,20508,20509,20510,20514,20519,20526,20528,20530,20531,20533,20544,20545,20546,20549,20550,20554,20556,20558,20561,20562,20563,20567,20569,20575,20576,20578,20579,20582,20583,20586,20589,20592,20593,20539,20609,20611,20612,20614,20618,20622,20623,20624,20626,20627,20628,20630,20635,20636,20638,20639,20640,20641,20642,20650,20655,20656,20665,20666,20669,20672,20675,20676,20679,20684,20686,20688,20691,20692,20696,20700,20701,20703,20706,20708,20710,20712,20713,20719,20721,20726,20730,20734,20739,20742,20743,20744,20747,20748,20749,20750,20722,20752,20759,20761,20763,20764,20765,20766,20771,20775,20776,20780,20781,20783,20785,20787,20788,20789,20792,20793,20802,20810,20815,20819,20821,20823,20824,20831,20836,20838,20862,20867,20868,20875,20878,20888,20893,20897,20899,20909,20920,20922,20924,20926,20927,20930,20936,20943,20945,20946,20947,20949,20952,20958,20962,20965,20974,20978,20979,20980,20983,20993,20994,20997,21010,21011,21013,21014,21016,21026,21032,21041,21042,21045,21052,21061,21065,21077,21079,21080,21082,21084,21087,21088,21089,21094,21102,21111,21112,21113,21120,21122,21125,21130,21132,21139,21141,21142,21143,21144,21146,21148,21156,21157,21158,21159,21167,21168,21174,21175,21176,21178,21179,21181,21184,21188,21190,21192,21196,21199,21201,21204,21206,21211,21212,21217,21221,21224,21225,21226,21228,21232,21233,21236,21238,21239,21248,21251,21258,21259,21260,21265,21267,21272,21275,21276,21278,21279,21285,21287,21288,21289,21291,21292,21293,21296,21298,21301,21308,21309,21310,21314,21324,21323,21337,21339,21345,21347,21349,21356,21357,21362,21369,21374,21379,21383,21384,21390,21395,21396,21401,21405,21409,21412,21418,21419,21423,21426,21428,21429,21431,21432,21434,21437,21440,21445,21455,21458,21459,21461,21466,21469,21470,21472,21478,21479,21493,21506,21523,21530,21537,21543,21544,21546,21551,21553,21556,21557,21571,21572,21575,21581,21583,21598,21602,21604,21606,21607,21609,21611,21613,21614,21620,21631,21633,21635,21637,21640,21641,21645,21649,21653,21654,21660,21663,21665,21670,21671,21673,21674,21677,21678,21681,21687,21689,21690,21691,21695,21702,21706,21709,21710,21728,21738,21740,21743,21750,21756,21758,21759,21760,21761,21765,21768,21769,21772,21773,21774,21781,21802,21803,21810,21813,21814,21819,21820,21821,21825,21831,21833,21834,21837,21840,21841,21848,21850,21851,21854,21856,21857,21860,21862,21887,21889,21890,21894,21896,21902,21903,21905,21906,21907,21908,21911,21923,21924,21933,21938,21951,21953,21955,21958,21961,21963,21964,21966,21969,21970,21971,21975,21976,21979,21982,21986,21993,22006,22015,22021,22024,22026,22029,22030,22031,22032,22033,22034,22041,22060,22064,22067,22069,22071,22073,22075,22076,22077,22079,22080,22081,22083,22084,22086,22089,22091,22093,22095,22100,22110,22112,22113,22114,22115,22118,22121,22125,22127,22129,22130,22133,22148,22149,22152,22155,22156,22165,22169,22170,22173,22174,22175,22182,22183,22184,22185,22187,22188,22189,22193,22195,22199,22206,22213,22217,22218,22219,22223,22224,22220,22221,22233,22236,22237,22239,22241,22244,22245,22246,22247,22248,22257,22251,22253,22262,22263,22273,22274,22279,22282,22284,22289,22293,22298,22299,22301,22304,22306,22307,22308,22309,22313,22314,22316,22318,22319,22323,22324,22333,22334,22335,22341,22342,22348,22349,22354,22370,22373,22375,22376,22379,22381,22382,22383,22384,22385,22387,22388,22389,22391,22393,22394,22395,22396,22398,22401,22403,22412,22420,22423,22425,22426,22428,22429,22430,22431,22433,22421,22439,22440,22441,22444,22456,22461,22471,22472,22476,22479,22485,22493,22494,22500,22502,22503,22505,22509,22512,22517,22518,22520,22525,22526,22527,22531,22532,22536,22537,22497,22540,22541,22555,22558,22559,22560,22566,22567,22573,22578,22585,22591,22601,22604,22605,22607,22608,22613,22623,22625,22628,22631,22632,22648,22652,22655,22656,22657,22663,22664,22665,22666,22668,22669,22671,22672,22676,22678,22685,22688,22689,22690,22694,22697,22705,22706,22724,22716,22722,22728,22733,22734,22736,22738,22740,22742,22746,22749,22753,22754,22761,22771,22789,22790,22795,22796,22802,22803,22804,34369,22813,22817,22819,22820,22824,22831,22832,22835,22837,22838,22847,22851,22854,22866,22867,22873,22875,22877,22878,22879,22881,22883,22891,22893,22895,22898,22901,22902,22905,22907,22908,22923,22924,22926,22930,22933,22935,22943,22948,22951,22957,22958,22959,22960,22963,22967,22970,22972,22977,22979,22980,22984,22986,22989,22994,23005,23006,23007,23011,23012,23015,23022,23023,23025,23026,23028,23031,23040,23044,23052,23053,23054,23058,23059,23070,23075,23076,23079,23080,23082,23085,23088,23108,23109,23111,23112,23116,23120,23125,23134,23139,23141,23143,23149,23159,23162,23163,23166,23179,23184,23187,23190,23193,23196,23198,23199,23200,23202,23207,23212,23217,23218,23219,23221,23224,23226,23227,23231,23236,23238,23240,23247,23258,23260,23264,23269,23274,23278,23285,23286,23293,23296,23297,23304,23319,23348,23321,23323,23325,23329,23333,23341,23352,23361,23371,23372,23378,23382,23390,23400,23406,23407,23420,23421,23422,23423,23425,23428,23430,23434,23438,23440,23441,23443,23444,23446,23464,23465,23468,23469,23471,23473,23474,23479,23482,23484,23488,23489,23501,23503,23510,23511,23512,23513,23514,23520,23535,23537,23540,23549,23564,23575,23582,23583,23587,23590,23593,23595,23596,23598,23600,23602,23605,23606,23641,23642,23644,23650,23651,23655,23656,23657,23661,23664,23668,23669,23674,23675,23676,23677,23687,23688,23690,23695,23698,23709,23711,23712,23714,23715,23718,23722,23730,23732,23733,23738,23753,23755,23762,23773,23767,23790,23793,23794,23796,23809,23814,23821,23826,23851,23843,23844,23846,23847,23857,23860,23865,23869,23871,23874,23875,23878,23880,23893,23889,23897,23882,23903,23904,23905,23906,23908,23914,23917,23920,23929,23930,23934,23935,23937,23939,23944,23946,23954,23955,23956,23957,23961,23963,23967,23968,23975,23979,23984,23988,23992,23993,24003,24007,24011,24016,24014,24024,24025,24032,24036,24041,24056,24057,24064,24071,24077,24082,24084,24085,24088,24095,24096,24110,24104,24114,24117,24126,24139,24144,24137,24145,24150,24152,24155,24156,24158,24168,24170,24171,24172,24173,24174,24176,24192,24203,24206,24226,24228,24229,24232,24234,24236,24241,24243,24253,24254,24255,24262,24268,24267,24270,24273,24274,24276,24277,24284,24286,24293,24299,24322,24326,24327,24328,24334,24345,24348,24349,24353,24354,24355,24356,24360,24363,24364,24366,24368,24372,24374,24379,24381,24383,24384,24388,24389,24391,24397,24400,24404,24408,24411,24416,24419,24420,24423,24431,24434,24436,24437,24440,24442,24445,24446,24457,24461,24463,24470,24476,24477,24482,24487,24491,24484,24492,24495,24496,24497,24504,24516,24519,24520,24521,24523,24528,24529,24530,24531,24532,24542,24545,24546,24552,24553,24554,24556,24557,24558,24559,24562,24563,24566,24570,24572,24583,24586,24589,24595,24596,24599,24600,24602,24607,24612,24621,24627,24629,24640,24647,24648,24649,24652,24657,24660,24662,24663,24669,24673,24679,24689,24702,24703,24706,24710,24712,24714,24718,24721,24723,24725,24728,24733,24734,24738,24740,24741,24744,24752,24753,24759,24763,24766,24770,24772,24776,24777,24778,24779,24782,24783,24788,24789,24793,24795,24797,24798,24802,24805,24818,24821,24824,24828,24829,24834,24839,24842,24844,24848,24849,24850,24851,24852,24854,24855,24857,24860,24862,24866,24874,24875,24880,24881,24885,24886,24887,24889,24897,24901,24902,24905,24926,24928,24940,24946,24952,24955,24956,24959,24960,24961,24963,24964,24971,24973,24978,24979,24983,24984,24988,24989,24991,24992,24997,25e3,25002,25005,25016,25017,25020,25024,25025,25026,25038,25039,25045,25052,25053,25054,25055,25057,25058,25063,25065,25061,25068,25069,25071,25089,25091,25092,25095,25107,25109,25116,25120,25122,25123,25127,25129,25131,25145,25149,25154,25155,25156,25158,25164,25168,25169,25170,25172,25174,25178,25180,25188,25197,25199,25203,25210,25213,25229,25230,25231,25232,25254,25256,25267,25270,25271,25274,25278,25279,25284,25294,25301,25302,25306,25322,25330,25332,25340,25341,25347,25348,25354,25355,25357,25360,25363,25366,25368,25385,25386,25389,25397,25398,25401,25404,25409,25410,25411,25412,25414,25418,25419,25422,25426,25427,25428,25432,25435,25445,25446,25452,25453,25457,25460,25461,25464,25468,25469,25471,25474,25476,25479,25482,25488,25492,25493,25497,25498,25502,25508,25510,25517,25518,25519,25533,25537,25541,25544,25550,25553,25555,25556,25557,25564,25568,25573,25578,25580,25586,25587,25589,25592,25593,25609,25610,25616,25618,25620,25624,25630,25632,25634,25636,25637,25641,25642,25647,25648,25653,25661,25663,25675,25679,25681,25682,25683,25684,25690,25691,25692,25693,25695,25696,25697,25699,25709,25715,25716,25723,25725,25733,25735,25743,25744,25745,25752,25753,25755,25757,25759,25761,25763,25766,25768,25772,25779,25789,25790,25791,25796,25801,25802,25803,25804,25806,25808,25809,25813,25815,25828,25829,25833,25834,25837,25840,25845,25847,25851,25855,25857,25860,25864,25865,25866,25871,25875,25876,25878,25881,25883,25886,25887,25890,25894,25897,25902,25905,25914,25916,25917,25923,25927,25929,25936,25938,25940,25951,25952,25959,25963,25978,25981,25985,25989,25994,26002,26005,26008,26013,26016,26019,26022,26030,26034,26035,26036,26047,26050,26056,26057,26062,26064,26068,26070,26072,26079,26096,26098,26100,26101,26105,26110,26111,26112,26116,26120,26121,26125,26129,26130,26133,26134,26141,26142,26145,26146,26147,26148,26150,26153,26154,26155,26156,26158,26160,26161,26163,26169,26167,26176,26181,26182,26186,26188,26193,26190,26199,26200,26201,26203,26204,26208,26209,26363,26218,26219,26220,26238,26227,26229,26239,26231,26232,26233,26235,26240,26236,26251,26252,26253,26256,26258,26265,26266,26267,26268,26271,26272,26276,26285,26289,26290,26293,26299,26303,26304,26306,26307,26312,26316,26318,26319,26324,26331,26335,26344,26347,26348,26350,26362,26373,26375,26382,26387,26393,26396,26400,26402,26419,26430,26437,26439,26440,26444,26452,26453,26461,26470,26476,26478,26484,26486,26491,26497,26500,26510,26511,26513,26515,26518,26520,26521,26523,26544,26545,26546,26549,26555,26556,26557,26617,26560,26562,26563,26565,26568,26569,26578,26583,26585,26588,26593,26598,26608,26610,26614,26615,26706,26644,26649,26653,26655,26664,26663,26668,26669,26671,26672,26673,26675,26683,26687,26692,26693,26698,26700,26709,26711,26712,26715,26731,26734,26735,26736,26737,26738,26741,26745,26746,26747,26748,26754,26756,26758,26760,26774,26776,26778,26780,26785,26787,26789,26793,26794,26798,26802,26811,26821,26824,26828,26831,26832,26833,26835,26838,26841,26844,26845,26853,26856,26858,26859,26860,26861,26864,26865,26869,26870,26875,26876,26877,26886,26889,26890,26896,26897,26899,26902,26903,26929,26931,26933,26936,26939,26946,26949,26953,26958,26967,26971,26979,26980,26981,26982,26984,26985,26988,26992,26993,26994,27002,27003,27007,27008,27021,27026,27030,27032,27041,27045,27046,27048,27051,27053,27055,27063,27064,27066,27068,27077,27080,27089,27094,27095,27106,27109,27118,27119,27121,27123,27125,27134,27136,27137,27139,27151,27153,27157,27162,27165,27168,27172,27176,27184,27186,27188,27191,27195,27198,27199,27205,27206,27209,27210,27214,27216,27217,27218,27221,27222,27227,27236,27239,27242,27249,27251,27262,27265,27267,27270,27271,27273,27275,27281,27291,27293,27294,27295,27301,27307,27311,27312,27313,27316,27325,27326,27327,27334,27337,27336,27340,27344,27348,27349,27350,27356,27357,27364,27367,27372,27376,27377,27378,27388,27389,27394,27395,27398,27399,27401,27407,27408,27409,27415,27419,27422,27428,27432,27435,27436,27439,27445,27446,27451,27455,27462,27466,27469,27474,27478,27480,27485,27488,27495,27499,27502,27504,27509,27517,27518,27522,27525,27543,27547,27551,27552,27554,27555,27560,27561,27564,27565,27566,27568,27576,27577,27581,27582,27587,27588,27593,27596,27606,27610,27617,27619,27622,27623,27630,27633,27639,27641,27647,27650,27652,27653,27657,27661,27662,27664,27666,27673,27679,27686,27687,27688,27692,27694,27699,27701,27702,27706,27707,27711,27722,27723,27725,27727,27730,27732,27737,27739,27740,27755,27757,27759,27764,27766,27768,27769,27771,27781,27782,27783,27785,27796,27797,27799,27800,27804,27807,27824,27826,27828,27842,27846,27853,27855,27856,27857,27858,27860,27862,27866,27868,27872,27879,27881,27883,27884,27886,27890,27892,27908,27911,27914,27918,27919,27921,27923,27930,27942,27943,27944,27751,27950,27951,27953,27961,27964,27967,27991,27998,27999,28001,28005,28007,28015,28016,28028,28034,28039,28049,28050,28052,28054,28055,28056,28074,28076,28084,28087,28089,28093,28095,28100,28104,28106,28110,28111,28118,28123,28125,28127,28128,28130,28133,28137,28143,28144,28148,28150,28156,28160,28164,28190,28194,28199,28210,28214,28217,28219,28220,28228,28229,28232,28233,28235,28239,28241,28242,28243,28244,28247,28252,28253,28254,28258,28259,28264,28275,28283,28285,28301,28307,28313,28320,28327,28333,28334,28337,28339,28347,28351,28352,28353,28355,28359,28360,28362,28365,28366,28367,28395,28397,28398,28409,28411,28413,28420,28424,28426,28428,28429,28438,28440,28442,28443,28454,28457,28458,28463,28464,28467,28470,28475,28476,28461,28495,28497,28498,28499,28503,28505,28506,28509,28510,28513,28514,28520,28524,28541,28542,28547,28551,28552,28555,28556,28557,28560,28562,28563,28564,28566,28570,28575,28576,28581,28582,28583,28584,28590,28591,28592,28597,28598,28604,28613,28615,28616,28618,28634,28638,28648,28649,28656,28661,28665,28668,28669,28672,28677,28678,28679,28685,28695,28704,28707,28719,28724,28727,28729,28732,28739,28740,28744,28745,28746,28747,28756,28757,28765,28766,28750,28772,28773,28780,28782,28789,28790,28798,28801,28805,28806,28820,28821,28822,28823,28824,28827,28836,28843,28848,28849,28852,28855,28874,28881,28883,28884,28885,28886,28888,28892,28900,28922,28931,28932,28933,28934,28935,28939,28940,28943,28958,28960,28971,28973,28975,28976,28977,28984,28993,28997,28998,28999,29002,29003,29008,29010,29015,29018,29020,29022,29024,29032,29049,29056,29061,29063,29068,29074,29082,29083,29088,29090,29103,29104,29106,29107,29114,29119,29120,29121,29124,29131,29132,29139,29142,29145,29146,29148,29176,29182,29184,29191,29192,29193,29203,29207,29210,29213,29215,29220,29227,29231,29236,29240,29241,29249,29250,29251,29253,29262,29263,29264,29267,29269,29270,29274,29276,29278,29280,29283,29288,29291,29294,29295,29297,29303,29304,29307,29308,29311,29316,29321,29325,29326,29331,29339,29352,29357,29358,29361,29364,29374,29377,29383,29385,29388,29397,29398,29400,29407,29413,29427,29428,29434,29435,29438,29442,29444,29445,29447,29451,29453,29458,29459,29464,29465,29470,29474,29476,29479,29480,29484,29489,29490,29493,29498,29499,29501,29507,29517,29520,29522,29526,29528,29533,29534,29535,29536,29542,29543,29545,29547,29548,29550,29551,29553,29559,29561,29564,29568,29569,29571,29573,29574,29582,29584,29587,29589,29591,29592,29596,29598,29599,29600,29602,29605,29606,29610,29611,29613,29621,29623,29625,29628,29629,29631,29637,29638,29641,29643,29644,29647,29650,29651,29654,29657,29661,29665,29667,29670,29671,29673,29684,29685,29687,29689,29690,29691,29693,29695,29696,29697,29700,29703,29706,29713,29722,29723,29732,29734,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29753,29760,29763,29764,29766,29767,29771,29773,29777,29778,29783,29789,29794,29798,29799,29800,29803,29805,29806,29809,29810,29824,29825,29829,29830,29831,29833,29839,29840,29841,29842,29848,29849,29850,29852,29855,29856,29857,29859,29862,29864,29865,29866,29867,29870,29871,29873,29874,29877,29881,29883,29887,29896,29897,29900,29904,29907,29912,29914,29915,29918,29919,29924,29928,29930,29931,29935,29940,29946,29947,29948,29951,29958,29970,29974,29975,29984,29985,29988,29991,29993,29994,29999,30006,30009,30013,30014,30015,30016,30019,30023,30024,30030,30032,30034,30039,30046,30047,30049,30063,30065,30073,30074,30075,30076,30077,30078,30081,30085,30096,30098,30099,30101,30105,30108,30114,30116,30132,30138,30143,30144,30145,30148,30150,30156,30158,30159,30167,30172,30175,30176,30177,30180,30183,30188,30190,30191,30193,30201,30208,30210,30211,30212,30215,30216,30218,30220,30223,30226,30227,30229,30230,30233,30235,30236,30237,30238,30243,30245,30246,30249,30253,30258,30259,30261,30264,30265,30266,30268,30282,30272,30273,30275,30276,30277,30281,30283,30293,30297,30303,30308,30309,30317,30318,30319,30321,30324,30337,30341,30348,30349,30357,30363,30364,30365,30367,30368,30370,30371,30372,30373,30374,30375,30376,30378,30381,30397,30401,30405,30409,30411,30412,30414,30420,30425,30432,30438,30440,30444,30448,30449,30454,30457,30460,30464,30470,30474,30478,30482,30484,30485,30487,30489,30490,30492,30498,30504,30509,30510,30511,30516,30517,30518,30521,30525,30526,30530,30533,30534,30538,30541,30542,30543,30546,30550,30551,30556,30558,30559,30560,30562,30564,30567,30570,30572,30576,30578,30579,30580,30586,30589,30592,30596,30604,30605,30612,30613,30614,30618,30623,30626,30631,30634,30638,30639,30641,30645,30654,30659,30665,30673,30674,30677,30681,30686,30687,30688,30692,30694,30698,30700,30704,30705,30708,30712,30715,30725,30726,30729,30733,30734,30737,30749,30753,30754,30755,30765,30766,30768,30773,30775,30787,30788,30791,30792,30796,30798,30802,30812,30814,30816,30817,30819,30820,30824,30826,30830,30842,30846,30858,30863,30868,30872,30881,30877,30878,30879,30884,30888,30892,30893,30896,30897,30898,30899,30907,30909,30911,30919,30920,30921,30924,30926,30930,30931,30933,30934,30948,30939,30943,30944,30945,30950,30954,30962,30963,30976,30966,30967,30970,30971,30975,30982,30988,30992,31002,31004,31006,31007,31008,31013,31015,31017,31021,31025,31028,31029,31035,31037,31039,31044,31045,31046,31050,31051,31055,31057,31060,31064,31067,31068,31079,31081,31083,31090,31097,31099,31100,31102,31115,31116,31121,31123,31124,31125,31126,31128,31131,31132,31137,31144,31145,31147,31151,31153,31156,31160,31163,31170,31172,31175,31176,31178,31183,31188,31190,31194,31197,31198,31200,31202,31205,31210,31211,31213,31217,31224,31228,31234,31235,31239,31241,31242,31244,31249,31253,31259,31262,31265,31271,31275,31277,31279,31280,31284,31285,31288,31289,31290,31300,31301,31303,31304,31308,31317,31318,31321,31324,31325,31327,31328,31333,31335,31338,31341,31349,31352,31358,31360,31362,31365,31366,31370,31371,31376,31377,31380,31390,31392,31395,31404,31411,31413,31417,31419,31420,31430,31433,31436,31438,31441,31451,31464,31465,31467,31468,31473,31476,31483,31485,31486,31495,31508,31519,31523,31527,31529,31530,31531,31533,31534,31535,31536,31537,31540,31549,31551,31552,31553,31559,31566,31573,31584,31588,31590,31593,31594,31597,31599,31602,31603,31607,31620,31625,31630,31632,31633,31638,31643,31646,31648,31653,31660,31663,31664,31666,31669,31670,31674,31675,31676,31677,31682,31685,31688,31690,31700,31702,31703,31705,31706,31707,31720,31722,31730,31732,31733,31736,31737,31738,31740,31742,31745,31746,31747,31748,31750,31753,31755,31756,31758,31759,31769,31771,31776,31781,31782,31784,31788,31793,31795,31796,31798,31801,31802,31814,31818,31829,31825,31826,31827,31833,31834,31835,31836,31837,31838,31841,31843,31847,31849,31853,31854,31856,31858,31865,31868,31869,31878,31879,31887,31892,31902,31904,31910,31920,31926,31927,31930,31931,31932,31935,31940,31943,31944,31945,31949,31951,31955,31956,31957,31959,31961,31962,31965,31974,31977,31979,31989,32003,32007,32008,32009,32015,32017,32018,32019,32022,32029,32030,32035,32038,32042,32045,32049,32060,32061,32062,32064,32065,32071,32072,32077,32081,32083,32087,32089,32090,32092,32093,32101,32103,32106,32112,32120,32122,32123,32127,32129,32130,32131,32133,32134,32136,32139,32140,32141,32145,32150,32151,32157,32158,32166,32167,32170,32179,32182,32183,32185,32194,32195,32196,32197,32198,32204,32205,32206,32215,32217,32256,32226,32229,32230,32234,32235,32237,32241,32245,32246,32249,32250,32264,32272,32273,32277,32279,32284,32285,32288,32295,32296,32300,32301,32303,32307,32310,32319,32324,32325,32327,32334,32336,32338,32344,32351,32353,32354,32357,32363,32366,32367,32371,32376,32382,32385,32390,32391,32394,32397,32401,32405,32408,32410,32413,32414,32572,32571,32573,32574,32575,32579,32580,32583,32591,32594,32595,32603,32604,32605,32609,32611,32612,32613,32614,32621,32625,32637,32638,32639,32640,32651,32653,32655,32656,32657,32662,32663,32668,32673,32674,32678,32682,32685,32692,32700,32703,32704,32707,32712,32718,32719,32731,32735,32739,32741,32744,32748,32750,32751,32754,32762,32765,32766,32767,32775,32776,32778,32781,32782,32783,32785,32787,32788,32790,32797,32798,32799,32800,32804,32806,32812,32814,32816,32820,32821,32823,32825,32826,32828,32830,32832,32836,32864,32868,32870,32877,32881,32885,32897,32904,32910,32924,32926,32934,32935,32939,32952,32953,32968,32973,32975,32978,32980,32981,32983,32984,32992,33005,33006,33008,33010,33011,33014,33017,33018,33022,33027,33035,33046,33047,33048,33052,33054,33056,33060,33063,33068,33072,33077,33082,33084,33093,33095,33098,33100,33106,33111,33120,33121,33127,33128,33129,33133,33135,33143,33153,33168,33156,33157,33158,33163,33166,33174,33176,33179,33182,33186,33198,33202,33204,33211,33227,33219,33221,33226,33230,33231,33237,33239,33243,33245,33246,33249,33252,33259,33260,33264,33265,33266,33269,33270,33272,33273,33277,33279,33280,33283,33295,33299,33300,33305,33306,33309,33313,33314,33320,33330,33332,33338,33347,33348,33349,33350,33355,33358,33359,33361,33366,33372,33376,33379,33383,33389,33396,33403,33405,33407,33408,33409,33411,33412,33415,33417,33418,33422,33425,33428,33430,33432,33434,33435,33440,33441,33443,33444,33447,33448,33449,33450,33454,33456,33458,33460,33463,33466,33468,33470,33471,33478,33488,33493,33498,33504,33506,33508,33512,33514,33517,33519,33526,33527,33533,33534,33536,33537,33543,33544,33546,33547,33620,33563,33565,33566,33567,33569,33570,33580,33581,33582,33584,33587,33591,33594,33596,33597,33602,33603,33604,33607,33613,33614,33617,33621,33622,33623,33648,33656,33661,33663,33664,33666,33668,33670,33677,33682,33684,33685,33688,33689,33691,33692,33693,33702,33703,33705,33708,33726,33727,33728,33735,33737,33743,33744,33745,33748,33757,33619,33768,33770,33782,33784,33785,33788,33793,33798,33802,33807,33809,33813,33817,33709,33839,33849,33861,33863,33864,33866,33869,33871,33873,33874,33878,33880,33881,33882,33884,33888,33892,33893,33895,33898,33904,33907,33908,33910,33912,33916,33917,33921,33925,33938,33939,33941,33950,33958,33960,33961,33962,33967,33969,33972,33978,33981,33982,33984,33986,33991,33992,33996,33999,34003,34012,34023,34026,34031,34032,34033,34034,34039,34098,34042,34043,34045,34050,34051,34055,34060,34062,34064,34076,34078,34082,34083,34084,34085,34087,34090,34091,34095,34099,34100,34102,34111,34118,34127,34128,34129,34130,34131,34134,34137,34140,34141,34142,34143,34144,34145,34146,34148,34155,34159,34169,34170,34171,34173,34175,34177,34181,34182,34185,34187,34188,34191,34195,34200,34205,34207,34208,34210,34213,34215,34228,34230,34231,34232,34236,34237,34238,34239,34242,34247,34250,34251,34254,34221,34264,34266,34271,34272,34278,34280,34285,34291,34294,34300,34303,34304,34308,34309,34317,34318,34320,34321,34322,34328,34329,34331,34334,34337,34343,34345,34358,34360,34362,34364,34365,34368,34370,34374,34386,34387,34390,34391,34392,34393,34397,34400,34401,34402,34403,34404,34409,34412,34415,34421,34422,34423,34426,34445,34449,34454,34456,34458,34460,34465,34470,34471,34472,34477,34481,34483,34484,34485,34487,34488,34489,34495,34496,34497,34499,34501,34513,34514,34517,34519,34522,34524,34528,34531,34533,34535,34440,34554,34556,34557,34564,34565,34567,34571,34574,34575,34576,34579,34580,34585,34590,34591,34593,34595,34600,34606,34607,34609,34610,34617,34618,34620,34621,34622,34624,34627,34629,34637,34648,34653,34657,34660,34661,34671,34673,34674,34683,34691,34692,34693,34694,34695,34696,34697,34699,34700,34704,34707,34709,34711,34712,34713,34718,34720,34723,34727,34732,34733,34734,34737,34741,34750,34751,34753,34760,34761,34762,34766,34773,34774,34777,34778,34780,34783,34786,34787,34788,34794,34795,34797,34801,34803,34808,34810,34815,34817,34819,34822,34825,34826,34827,34832,34841,34834,34835,34836,34840,34842,34843,34844,34846,34847,34856,34861,34862,34864,34866,34869,34874,34876,34881,34883,34885,34888,34889,34890,34891,34894,34897,34901,34902,34904,34906,34908,34911,34912,34916,34921,34929,34937,34939,34944,34968,34970,34971,34972,34975,34976,34984,34986,35002,35005,35006,35008,35018,35019,35020,35021,35022,35025,35026,35027,35035,35038,35047,35055,35056,35057,35061,35063,35073,35078,35085,35086,35087,35093,35094,35096,35097,35098,35100,35104,35110,35111,35112,35120,35121,35122,35125,35129,35130,35134,35136,35138,35141,35142,35145,35151,35154,35159,35162,35163,35164,35169,35170,35171,35179,35182,35184,35187,35189,35194,35195,35196,35197,35209,35213,35216,35220,35221,35227,35228,35231,35232,35237,35248,35252,35253,35254,35255,35260,35284,35285,35286,35287,35288,35301,35305,35307,35309,35313,35315,35318,35321,35325,35327,35332,35333,35335,35343,35345,35346,35348,35349,35358,35360,35362,35364,35366,35371,35372,35375,35381,35383,35389,35390,35392,35395,35397,35399,35401,35405,35406,35411,35414,35415,35416,35420,35421,35425,35429,35431,35445,35446,35447,35449,35450,35451,35454,35455,35456,35459,35462,35467,35471,35472,35474,35478,35479,35481,35487,35495,35497,35502,35503,35507,35510,35511,35515,35518,35523,35526,35528,35529,35530,35537,35539,35540,35541,35543,35549,35551,35564,35568,35572,35573,35574,35580,35583,35589,35590,35595,35601,35612,35614,35615,35594,35629,35632,35639,35644,35650,35651,35652,35653,35654,35656,35666,35667,35668,35673,35661,35678,35683,35693,35702,35704,35705,35708,35710,35713,35716,35717,35723,35725,35727,35732,35733,35740,35742,35743,35896,35897,35901,35902,35909,35911,35913,35915,35919,35921,35923,35924,35927,35928,35931,35933,35929,35939,35940,35942,35944,35945,35949,35955,35957,35958,35963,35966,35974,35975,35979,35984,35986,35987,35993,35995,35996,36004,36025,36026,36037,36038,36041,36043,36047,36054,36053,36057,36061,36065,36072,36076,36079,36080,36082,36085,36087,36088,36094,36095,36097,36099,36105,36114,36119,36123,36197,36201,36204,36206,36223,36226,36228,36232,36237,36240,36241,36245,36254,36255,36256,36262,36267,36268,36271,36274,36277,36279,36281,36283,36288,36293,36294,36295,36296,36298,36302,36305,36308,36309,36311,36313,36324,36325,36327,36332,36336,36284,36337,36338,36340,36349,36353,36356,36357,36358,36363,36369,36372,36374,36384,36385,36386,36387,36390,36391,36401,36403,36406,36407,36408,36409,36413,36416,36417,36427,36429,36430,36431,36436,36443,36444,36445,36446,36449,36450,36457,36460,36461,36463,36464,36465,36473,36474,36475,36482,36483,36489,36496,36498,36501,36506,36507,36509,36510,36514,36519,36521,36525,36526,36531,36533,36538,36539,36544,36545,36547,36548,36551,36559,36561,36564,36572,36584,36590,36592,36593,36599,36601,36602,36589,36608,36610,36615,36616,36623,36624,36630,36631,36632,36638,36640,36641,36643,36645,36647,36648,36652,36653,36654,36660,36661,36662,36663,36666,36672,36673,36675,36679,36687,36689,36690,36691,36692,36693,36696,36701,36702,36709,36765,36768,36769,36772,36773,36774,36789,36790,36792,36798,36800,36801,36806,36810,36811,36813,36816,36818,36819,36821,36832,36835,36836,36840,36846,36849,36853,36854,36859,36862,36866,36868,36872,36876,36888,36891,36904,36905,36911,36906,36908,36909,36915,36916,36919,36927,36931,36932,36940,36955,36957,36962,36966,36967,36972,36976,36980,36985,36997,37e3,37003,37004,37006,37008,37013,37015,37016,37017,37019,37024,37025,37026,37029,37040,37042,37043,37044,37046,37053,37068,37054,37059,37060,37061,37063,37064,37077,37079,37080,37081,37084,37085,37087,37093,37074,37110,37099,37103,37104,37108,37118,37119,37120,37124,37125,37126,37128,37133,37136,37140,37142,37143,37144,37146,37148,37150,37152,37157,37154,37155,37159,37161,37166,37167,37169,37172,37174,37175,37177,37178,37180,37181,37187,37191,37192,37199,37203,37207,37209,37210,37211,37217,37220,37223,37229,37236,37241,37242,37243,37249,37251,37253,37254,37258,37262,37265,37267,37268,37269,37272,37278,37281,37286,37288,37292,37293,37294,37296,37297,37298,37299,37302,37307,37308,37309,37311,37314,37315,37317,37331,37332,37335,37337,37338,37342,37348,37349,37353,37354,37356,37357,37358,37359,37360,37361,37367,37369,37371,37373,37376,37377,37380,37381,37382,37383,37385,37386,37388,37392,37394,37395,37398,37400,37404,37405,37411,37412,37413,37414,37416,37422,37423,37424,37427,37429,37430,37432,37433,37434,37436,37438,37440,37442,37443,37446,37447,37450,37453,37454,37455,37457,37464,37465,37468,37469,37472,37473,37477,37479,37480,37481,37486,37487,37488,37493,37494,37495,37496,37497,37499,37500,37501,37503,37512,37513,37514,37517,37518,37522,37527,37529,37535,37536,37540,37541,37543,37544,37547,37551,37554,37558,37560,37562,37563,37564,37565,37567,37568,37569,37570,37571,37573,37574,37575,37576,37579,37580,37581,37582,37584,37587,37589,37591,37592,37593,37596,37597,37599,37600,37601,37603,37605,37607,37608,37612,37614,37616,37625,37627,37631,37632,37634,37640,37645,37649,37652,37653,37660,37661,37662,37663,37665,37668,37669,37671,37673,37674,37683,37684,37686,37687,37703,37704,37705,37712,37713,37714,37717,37719,37720,37722,37726,37732,37733,37735,37737,37738,37741,37743,37744,37745,37747,37748,37750,37754,37757,37759,37760,37761,37762,37768,37770,37771,37773,37775,37778,37781,37784,37787,37790,37793,37795,37796,37798,37800,37803,37812,37813,37814,37818,37801,37825,37828,37829,37830,37831,37833,37834,37835,37836,37837,37843,37849,37852,37854,37855,37858,37862,37863,37881,37879,37880,37882,37883,37885,37889,37890,37892,37896,37897,37901,37902,37903,37909,37910,37911,37919,37934,37935,37937,37938,37939,37940,37947,37951,37949,37955,37957,37960,37962,37964,37973,37977,37980,37983,37985,37987,37992,37995,37997,37998,37999,38001,38002,38020,38019,38264,38265,38270,38276,38280,38284,38285,38286,38301,38302,38303,38305,38310,38313,38315,38316,38324,38326,38330,38333,38335,38342,38344,38345,38347,38352,38353,38354,38355,38361,38362,38365,38366,38367,38368,38372,38374,38429,38430,38434,38436,38437,38438,38444,38449,38451,38455,38456,38457,38458,38460,38461,38465,38482,38484,38486,38487,38488,38497,38510,38516,38523,38524,38526,38527,38529,38530,38531,38532,38537,38545,38550,38554,38557,38559,38564,38565,38566,38569,38574,38575,38579,38586,38602,38610,23986,38616,38618,38621,38622,38623,38633,38639,38641,38650,38658,38659,38661,38665,38682,38683,38685,38689,38690,38691,38696,38705,38707,38721,38723,38730,38734,38735,38741,38743,38744,38746,38747,38755,38759,38762,38766,38771,38774,38775,38776,38779,38781,38783,38784,38793,38805,38806,38807,38809,38810,38814,38815,38818,38828,38830,38833,38834,38837,38838,38840,38841,38842,38844,38846,38847,38849,38852,38853,38855,38857,38858,38860,38861,38862,38864,38865,38868,38871,38872,38873,38877,38878,38880,38875,38881,38884,38895,38897,38900,38903,38904,38906,38919,38922,38937,38925,38926,38932,38934,38940,38942,38944,38947,38950,38955,38958,38959,38960,38962,38963,38965,38949,38974,38980,38983,38986,38993,38994,38995,38998,38999,39001,39002,39010,39011,39013,39014,39018,39020,39083,39085,39086,39088,39092,39095,39096,39098,39099,39103,39106,39109,39112,39116,39137,39139,39141,39142,39143,39146,39155,39158,39170,39175,39176,39185,39189,39190,39191,39194,39195,39196,39199,39202,39206,39207,39211,39217,39218,39219,39220,39221,39225,39226,39227,39228,39232,39233,39238,39239,39240,39245,39246,39252,39256,39257,39259,39260,39262,39263,39264,39323,39325,39327,39334,39344,39345,39346,39349,39353,39354,39357,39359,39363,39369,39379,39380,39385,39386,39388,39390,39399,39402,39403,39404,39408,39412,39413,39417,39421,39422,39426,39427,39428,39435,39436,39440,39441,39446,39454,39456,39458,39459,39460,39463,39469,39470,39475,39477,39478,39480,39495,39489,39492,39498,39499,39500,39502,39505,39508,39510,39517,39594,39596,39598,39599,39602,39604,39605,39606,39609,39611,39614,39615,39617,39619,39622,39624,39630,39632,39634,39637,39638,39639,39643,39644,39648,39652,39653,39655,39657,39660,39666,39667,39669,39673,39674,39677,39679,39680,39681,39682,39683,39684,39685,39688,39689,39691,39692,39693,39694,39696,39698,39702,39705,39707,39708,39712,39718,39723,39725,39731,39732,39733,39735,39737,39738,39741,39752,39755,39756,39765,39766,39767,39771,39774,39777,39779,39781,39782,39784,39786,39787,39788,39789,39790,39795,39797,39799,39800,39801,39807,39808,39812,39813,39814,39815,39817,39818,39819,39821,39823,39824,39828,39834,39837,39838,39846,39847,39849,39852,39856,39857,39858,39863,39864,39867,39868,39870,39871,39873,39879,39880,39886,39888,39895,39896,39901,39903,39909,39911,39914,39915,39919,39923,39927,39928,39929,39930,39933,39935,39936,39938,39947,39951,39953,39958,39960,39961,39962,39964,39966,39970,39971,39974,39975,39976,39977,39978,39985,39989,39990,39991,39997,40001,40003,40004,40005,40009,40010,40014,40015,40016,40019,40020,40022,40024,40027,40029,40030,40031,40035,40041,40042,40028,40043,40040,40046,40048,40050,40053,40055,40059,40166,40178,40183,40185,40203,40194,40209,40215,40216,40220,40221,40222,40239,40240,40242,40243,40244,40250,40252,40261,40253,40258,40259,40263,40266,40275,40276,40287,40291,40290,40293,40297,40298,40299,40304,40310,40311,40315,40316,40318,40323,40324,40326,40330,40333,40334,40338,40339,40341,40342,40343,40344,40353,40362,40364,40366,40369,40373,40377,40380,40383,40387,40391,40393,40394,40404,40405,40406,40407,40410,40414,40415,40416,40421,40423,40425,40427,40430,40432,40435,40436,40446,40458,40450,40455,40462,40464,40465,40466,40469,40470,40473,40476,40477,40570,40571,40572,40576,40578,40579,40580,40581,40583,40590,40591,40598,40600,40603,40606,40612,40616,40620,40622,40623,40624,40627,40628,40629,40646,40648,40651,40661,40671,40676,40679,40684,40685,40686,40688,40689,40690,40693,40696,40703,40706,40707,40713,40719,40720,40721,40722,40724,40726,40727,40729,40730,40731,40735,40738,40742,40746,40747,40751,40753,40754,40756,40759,40761,40762,40764,40765,40767,40769,40771,40772,40773,40774,40775,40787,40789,40790,40791,40792,40794,40797,40798,40808,40809,40813,40814,40815,40816,40817,40819,40821,40826,40829,40847,40848,40849,40850,40852,40854,40855,40862,40865,40866,40867,40869,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],ibm866:[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160],"iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],"iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729],"iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729],"iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119],"iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null],"iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],"iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],"iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312],"iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217],"iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255],"iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],"iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255],"koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],"koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,1118,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,1038,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],macintosh:[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711],"windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null],"windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],"windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103],"windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],"windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],"windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255],"windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],"windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746],"windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729],"windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255],"x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364]}})(this||{})},{}],4:[function(e,n){(function(d){'use strict';function i(e,n,d){return n<=e&&e<=d}function f(e,n){return-1!==e.indexOf(n)}function u(e){if(e===void 0)return{};if(e===Object(e))return e;throw TypeError("Could not convert argument to dictionary")}function o(e){for(var f=e+"",o=f.length,n=0,s=[];n<o;){var u=f.charCodeAt(n);if(55296>u||57343<u)s.push(u);else if(56320<=u&&57343>=u)s.push(65533);else if(55296<=u&&56319>=u)if(n===o-1)s.push(65533);else{var a=f.charCodeAt(n+1);if(56320<=a&&57343>=a){s.push(65536+((1023&u)<<10)+(1023&a)),n+=1}else s.push(65533)}n+=1}return s}function s(e){for(var n=String.fromCharCode,d="",f=0,u;f<e.length;++f)u=e[f],65535>=u?d+=n(u):(u-=65536,d+=n((u>>10)+55296,(1023&u)+56320));return d}function a(e){return 0<=e&&127>=e}function t(e){this.tokens=[].slice.call(e),this.tokens.reverse()}function r(e,n){if(e)throw TypeError("Decoder error");return n||65533}function c(e){throw TypeError("The code point "+e+" could not be encoded.")}function l(e){return e=(e+"").trim().toLowerCase(),Object.prototype.hasOwnProperty.call(G,e)?G[e]:null}function p(e,n){return n?n[e]||null:null}function m(e,n){var d=n.indexOf(e);return-1===d?null:d}function g(e){if(!("encoding-indexes"in d))throw Error("Indexes missing. Did you forget to include encoding-indexes.js first?");return d["encoding-indexes"][e]}function h(e){if(39419<e&&189e3>e||1237575<e)return null;if(7457===e)return 59335;var n=0,d=0,f=g("gb18030-ranges"),u;for(u=0;u<f.length;++u){var o=f[u];if(o[0]<=e)n=o[0],d=o[1];else break}return d+e-n}function y(e){if(59335===e)return 7457;var n=0,d=0,f=g("gb18030-ranges"),u;for(u=0;u<f.length;++u){var o=f[u];if(o[1]<=e)n=o[1],d=o[0];else break}return d+e-n}function w(e){$=$||g("jis0208").map(function(e,n){return i(n,8272,8835)?null:e});var n=$;return n.indexOf(e)}function _(e){Y=Y||g("big5").map(function(e,n){return n<5024?null:e});var n=Y;return 9552===e||9566===e||9569===e||9578===e||21313===e||21317===e?n.lastIndexOf(e):m(e,n)}function b(e,n){if(!(this instanceof b))throw TypeError("Called as a function. Did you forget 'new'?");e=void 0===e?"utf-8":e+"",n=u(n),this._encoding=null,this._decoder=null,this._ignoreBOM=!1,this._BOMseen=!1,this._error_mode="replacement",this._do_not_flush=!1;var d=l(e);if(null===d||"replacement"===d.name)throw RangeError("Unknown encoding: "+e);if(!Q[d.name])throw Error("Decoder not present. Did you forget to include encoding-indexes.js first?");var i=this;return i._encoding=d,!!n.fatal&&(i._error_mode="fatal"),!!n.ignoreBOM&&(i._ignoreBOM=!0),Object.defineProperty||(this.encoding=i._encoding.name.toLowerCase(),this.fatal="fatal"===i._error_mode,this.ignoreBOM=i._ignoreBOM),i}function E(e,n){if(!(this instanceof E))throw TypeError("Called as a function. Did you forget 'new'?");n=u(n),this._encoding=null,this._encoder=null,this._do_not_flush=!1,this._fatal=!n.fatal?"replacement":"fatal";var i=this;if(!!n.NONSTANDARD_allowLegacyEncoding){e=void 0===e?"utf-8":e+"";var f=l(e);if(null===f||"replacement"===f.name)throw RangeError("Unknown encoding: "+e);if(!X[f.name])throw Error("Encoder not present. Did you forget to include encoding-indexes.js first?");i._encoding=f}else i._encoding=l("utf-8"),void 0!==e&&"console"in d&&console.warn("TextEncoder constructor called with encoding label, which is ignored.");return Object.defineProperty||(this.encoding=i._encoding.name.toLowerCase()),i}function v(e){var n=e.fatal,d=0,f=0,u=0,o=128,s=191;this.handler=function(e,a){if(-1===a&&0!==u)return u=0,r(n);if(-1===a)return-1;if(0===u){if(i(a,0,127))return a;if(i(a,194,223))u=1,d=31&a;else if(i(a,224,239))224===a&&(o=160),237===a&&(s=159),u=2,d=15&a;else if(i(a,240,244))240===a&&(o=144),244===a&&(s=143),u=3,d=7&a;else return r(n);return null}if(!i(a,o,s))return d=u=f=0,o=128,s=191,e.prepend(a),r(n);if(o=128,s=191,d=d<<6|63&a,f+=1,f!==u)return null;var t=d;return d=u=f=0,t}}function O(e){e.fatal;this.handler=function(e,n){if(n===-1)return-1;if(z(n))return n;var d,f;i(n,128,2047)?(d=1,f=192):i(n,2048,65535)?(d=2,f=224):i(n,65536,1114111)&&(d=3,f=240);for(var u=[(n>>6*d)+f];0<d;){var o=n>>6*(d-1);u.push(128|63&o),d-=1}return u}}function I(e,n){var d=n.fatal;this.handler=function(n,i){if(i===-1)return-1;if(a(i))return i;var f=e[i-128];return null===f?r(d):f}}function k(e,n){n.fatal;this.handler=function(n,d){if(-1===d)return-1;if(z(d))return d;var i=m(d,e);return null===i&&c(d),i+128}}function x(e){var n=e.fatal,d=0,f=0,u=0;this.handler=function(e,o){if(o===-1&&0===d&&0===f&&0===u)return-1;o===-1&&(0!==d||0!==f||0!==u)&&(d=0,f=0,u=0,r(n));var s;if(0!==u){s=null,i(o,48,57)&&(s=h(10*(126*(10*(d-129)+f-48)+u-129)+o-48));var t=[f,u,o];return d=0,f=0,u=0,null===s?(e.prepend(t),r(n)):s}if(0!==f)return i(o,129,254)?(u=o,null):(e.prepend([f,o]),d=0,f=0,r(n));if(0!==d){if(i(o,48,57))return f=o,null;var c=d,l=null;d=0;var m=127>o?64:65;return(i(o,64,126)||i(o,128,254))&&(l=190*(c-129)+(o-m)),s=null===l?null:p(l,g("gb18030")),null===s&&a(o)&&e.prepend(o),null===s?r(n):s}return a(o)?o:128===o?8364:i(o,129,254)?(d=o,null):r(n)}}function N(e,n){e.fatal;this.handler=function(e,d){if(d===-1)return-1;if(z(d))return d;if(58853===d)return c(d);if(n&&8364===d)return 128;var i=m(d,g("gb18030"));if(null!==i){var f=W(i/190)+129,u=i%190,o=63>u?64:65;return[f,u+o]}if(n)return c(d);i=y(d);var s=W(i/10/126/10);i-=10*(126*(10*s));var a=W(i/10/126);i-=126*(10*a);var t=W(i/10),r=i-10*t;return[s+129,a+48,t+129,r+48]}}function C(e){var n=e.fatal,d=0;this.handler=function(e,f){if(-1===f&&0!==d)return d=0,r(n);if(-1===f&&0===d)return-1;if(0!==d){var u=d,o=null;d=0;var s=127>f?64:98;switch((i(f,64,126)||i(f,161,254))&&(o=157*(u-129)+(f-s)),o){case 1133:return[202,772];case 1135:return[202,780];case 1164:return[234,772];case 1166:return[234,780];}var t=null===o?null:p(o,g("big5"));return null===t&&a(f)&&e.prepend(f),null===t?r(n):t}return a(f)?f:i(f,129,254)?(d=f,null):r(n)}}function R(e){e.fatal;this.handler=function(e,n){if(n===-1)return-1;if(z(n))return n;var d=_(n);if(null===d)return c(n);var i=W(d/157)+129;if(161>i)return c(n);var f=d%157,u=63>f?64:98;return[i,f+u]}}function S(e){var n=e.fatal,d=!1,f=0;this.handler=function(e,u){if(-1===u&&0!==f)return f=0,r(n);if(-1===u&&0===f)return-1;if(142===f&&i(u,161,223))return f=0,65216+u;if(143===f&&i(u,161,254))return d=!0,f=u,null;if(0!==f){var o=f;f=0;var s=null;return i(o,161,254)&&i(u,161,254)&&(s=p(94*(o-161)+(u-161),g(d?"jis0212":"jis0208"))),d=!1,i(u,161,254)||e.prepend(u),null===s?r(n):s}return a(u)?u:142===u||143===u||i(u,161,254)?(f=u,null):r(n)}}function L(e){e.fatal;this.handler=function(e,n){if(n===-1)return-1;if(z(n))return n;if(165===n)return 92;if(8254===n)return 126;if(i(n,65377,65439))return[142,n-65377+161];8722===n&&(n=65293);var d=m(n,g("jis0208"));if(null===d)return c(n);var f=W(d/94)+161;return[f,d%94+161]}}function B(e){var n=e.fatal,d={ASCII:0,Roman:1,Katakana:2,LeadByte:3,TrailByte:4,EscapeStart:5,Escape:6},f=d.ASCII,u=d.ASCII,o=0,s=!1;this.handler=function(e,a){switch(f){default:case d.ASCII:return 27===a?(f=d.EscapeStart,null):i(a,0,127)&&14!==a&&15!==a&&27!==a?(s=!1,a):-1===a?-1:(s=!1,r(n));case d.Roman:return 27===a?(f=d.EscapeStart,null):92===a?(s=!1,165):126===a?(s=!1,8254):i(a,0,127)&&14!==a&&15!==a&&27!==a&&92!==a&&126!==a?(s=!1,a):-1===a?-1:(s=!1,r(n));case d.Katakana:return 27===a?(f=d.EscapeStart,null):i(a,33,95)?(s=!1,65344+a):-1===a?-1:(s=!1,r(n));case d.LeadByte:return 27===a?(f=d.EscapeStart,null):i(a,33,126)?(s=!1,o=a,f=d.TrailByte,null):-1===a?-1:(s=!1,r(n));case d.TrailByte:if(27===a)return f=d.EscapeStart,r(n);if(i(a,33,126)){f=d.LeadByte;var t=94*(o-33)+a-33,c=p(t,g("jis0208"));return null===c?r(n):c}return-1===a?(f=d.LeadByte,e.prepend(a),r(n)):(f=d.LeadByte,r(n));case d.EscapeStart:return 36===a||40===a?(o=a,f=d.Escape,null):(e.prepend(a),s=!1,f=u,r(n));case d.Escape:var l=o;o=0;var m=null;if(40===l&&66===a&&(m=d.ASCII),40===l&&74===a&&(m=d.Roman),40===l&&73===a&&(m=d.Katakana),36===l&&(64===a||66===a)&&(m=d.LeadByte),null!==m){f=f=m;var h=s;return s=!0,h?r(n):null}return e.prepend([l,a]),s=!1,f=u,r(n);}}}function j(e){var n=e.fatal,d={ASCII:0,Roman:1,jis0208:2},i=d.ASCII;this.handler=function(e,n){if(-1===n&&i!==d.ASCII)return e.prepend(n),i=d.ASCII,[27,40,66];if(-1===n&&i===d.ASCII)return-1;if((i===d.ASCII||i===d.Roman)&&(14===n||15===n||27===n))return c(65533);if(i===d.ASCII&&z(n))return n;if(i===d.Roman&&(z(n)&&92!==n&&126!==n||165==n||8254==n)){if(z(n))return n;if(165===n)return 92;if(8254===n)return 126}if(z(n)&&i!==d.ASCII)return e.prepend(n),i=d.ASCII,[27,40,66];if((165===n||8254===n)&&i!==d.Roman)return e.prepend(n),i=d.Roman,[27,40,74];8722===n&&(n=65293);var f=m(n,g("jis0208"));if(null===f)return c(n);if(i!==d.jis0208)return e.prepend(n),i=d.jis0208,[27,36,66];var u=W(f/94)+33;return[u,f%94+33]}}function A(e){var n=e.fatal,d=0;this.handler=function(e,f){if(-1===f&&0!==d)return d=0,r(n);if(-1===f&&0===d)return-1;if(0!==d){var u=d,o=null;d=0;var s=127>f?64:65,t=160>u?129:193;if((i(f,64,126)||i(f,128,252))&&(o=188*(u-t)+f-s),i(o,8836,10715))return 48508+o;var c=null===o?null:p(o,g("jis0208"));return null===c&&a(f)&&e.prepend(f),null===c?r(n):c}return a(f)||128===f?f:i(f,161,223)?65216+f:i(f,129,159)||i(f,224,252)?(d=f,null):r(n)}}function T(e){e.fatal;this.handler=function(e,n){if(n===-1)return-1;if(z(n)||128===n)return n;if(165===n)return 92;if(8254===n)return 126;if(i(n,65377,65439))return n-65377+161;8722===n&&(n=65293);var d=w(n);if(null===d)return c(n);var f=W(d/188),u=31>f?129:193,o=d%188,s=63>o?64:65;return[f+u,o+s]}}function M(e){var n=e.fatal,d=0;this.handler=function(e,f){if(-1===f&&0!==d)return d=0,r(n);if(-1===f&&0===d)return-1;if(0!==d){var u=d,o=null;d=0,i(f,65,254)&&(o=190*(u-129)+(f-65));var s=null===o?null:p(o,g("euc-kr"));return null===o&&a(f)&&e.prepend(f),null===s?r(n):s}return a(f)?f:i(f,129,254)?(d=f,null):r(n)}}function D(e){e.fatal;this.handler=function(e,n){if(n===-1)return-1;if(z(n))return n;var d=m(n,g("euc-kr"));if(null===d)return c(n);var i=W(d/190)+129;return[i,d%190+65]}}function J(e,n){var d=e>>8,i=255&e;return n?[d,i]:[i,d]}function U(e,n){var d=n.fatal,f=null,u=null;this.handler=function(n,o){if(-1===o&&(null!==f||null!==u))return r(d);if(-1===o&&null===f&&null===u)return-1;if(null===f)return f=o,null;var s;if(s=e?(f<<8)+o:(o<<8)+f,f=null,null!==u){var a=u;return(u=null,i(s,56320,57343))?65536+1024*(a-55296)+(s-56320):(n.prepend(J(s,e)),r(d))}return i(s,55296,56319)?(u=s,null):i(s,56320,57343)?r(d):s}}function P(e,n){n.fatal;this.handler=function(n,d){if(d===-1)return-1;if(i(d,0,65535))return J(d,e);var f=J((d-65536>>10)+55296,e),u=J((1023&d-65536)+56320,e);return f.concat(u)}}function F(e){e.fatal;this.handler=function(e,n){return-1===n?-1:a(n)?n:63360+n-128}}function K(e){e.fatal;this.handler=function(e,n){return-1===n?-1:z(n)?n:i(n,63360,63487)?n-63360+128:c(n)}}"undefined"!=typeof n&&n.exports&&!d["encoding-indexes"]&&(d["encoding-indexes"]=e("./encoding-indexes.js")["encoding-indexes"]);var W=Math.floor,z=a,H=-1;t.prototype={endOfStream:function(){return!this.tokens.length},read:function(){return this.tokens.length?this.tokens.pop():H},prepend:function(e){if(Array.isArray(e))for(var n=e;n.length;)this.tokens.push(n.pop());else this.tokens.push(e)},push:function(e){if(Array.isArray(e))for(var n=e;n.length;)this.tokens.unshift(n.shift());else this.tokens.unshift(e)}};(function(){}).prototype={handler:function(){}},function(){}.prototype={handler:function(){}};var q=[{encodings:[{labels:["unicode-1-1-utf-8","utf-8","utf8"],name:"UTF-8"}],heading:"The Encoding"},{encodings:[{labels:["866","cp866","csibm866","ibm866"],name:"IBM866"},{labels:["csisolatin2","iso-8859-2","iso-ir-101","iso8859-2","iso88592","iso_8859-2","iso_8859-2:1987","l2","latin2"],name:"ISO-8859-2"},{labels:["csisolatin3","iso-8859-3","iso-ir-109","iso8859-3","iso88593","iso_8859-3","iso_8859-3:1988","l3","latin3"],name:"ISO-8859-3"},{labels:["csisolatin4","iso-8859-4","iso-ir-110","iso8859-4","iso88594","iso_8859-4","iso_8859-4:1988","l4","latin4"],name:"ISO-8859-4"},{labels:["csisolatincyrillic","cyrillic","iso-8859-5","iso-ir-144","iso8859-5","iso88595","iso_8859-5","iso_8859-5:1988"],name:"ISO-8859-5"},{labels:["arabic","asmo-708","csiso88596e","csiso88596i","csisolatinarabic","ecma-114","iso-8859-6","iso-8859-6-e","iso-8859-6-i","iso-ir-127","iso8859-6","iso88596","iso_8859-6","iso_8859-6:1987"],name:"ISO-8859-6"},{labels:["csisolatingreek","ecma-118","elot_928","greek","greek8","iso-8859-7","iso-ir-126","iso8859-7","iso88597","iso_8859-7","iso_8859-7:1987","sun_eu_greek"],name:"ISO-8859-7"},{labels:["csiso88598e","csisolatinhebrew","hebrew","iso-8859-8","iso-8859-8-e","iso-ir-138","iso8859-8","iso88598","iso_8859-8","iso_8859-8:1988","visual"],name:"ISO-8859-8"},{labels:["csiso88598i","iso-8859-8-i","logical"],name:"ISO-8859-8-I"},{labels:["csisolatin6","iso-8859-10","iso-ir-157","iso8859-10","iso885910","l6","latin6"],name:"ISO-8859-10"},{labels:["iso-8859-13","iso8859-13","iso885913"],name:"ISO-8859-13"},{labels:["iso-8859-14","iso8859-14","iso885914"],name:"ISO-8859-14"},{labels:["csisolatin9","iso-8859-15","iso8859-15","iso885915","iso_8859-15","l9"],name:"ISO-8859-15"},{labels:["iso-8859-16"],name:"ISO-8859-16"},{labels:["cskoi8r","koi","koi8","koi8-r","koi8_r"],name:"KOI8-R"},{labels:["koi8-ru","koi8-u"],name:"KOI8-U"},{labels:["csmacintosh","mac","macintosh","x-mac-roman"],name:"macintosh"},{labels:["dos-874","iso-8859-11","iso8859-11","iso885911","tis-620","windows-874"],name:"windows-874"},{labels:["cp1250","windows-1250","x-cp1250"],name:"windows-1250"},{labels:["cp1251","windows-1251","x-cp1251"],name:"windows-1251"},{labels:["ansi_x3.4-1968","ascii","cp1252","cp819","csisolatin1","ibm819","iso-8859-1","iso-ir-100","iso8859-1","iso88591","iso_8859-1","iso_8859-1:1987","l1","latin1","us-ascii","windows-1252","x-cp1252"],name:"windows-1252"},{labels:["cp1253","windows-1253","x-cp1253"],name:"windows-1253"},{labels:["cp1254","csisolatin5","iso-8859-9","iso-ir-148","iso8859-9","iso88599","iso_8859-9","iso_8859-9:1989","l5","latin5","windows-1254","x-cp1254"],name:"windows-1254"},{labels:["cp1255","windows-1255","x-cp1255"],name:"windows-1255"},{labels:["cp1256","windows-1256","x-cp1256"],name:"windows-1256"},{labels:["cp1257","windows-1257","x-cp1257"],name:"windows-1257"},{labels:["cp1258","windows-1258","x-cp1258"],name:"windows-1258"},{labels:["x-mac-cyrillic","x-mac-ukrainian"],name:"x-mac-cyrillic"}],heading:"Legacy single-byte encodings"},{encodings:[{labels:["chinese","csgb2312","csiso58gb231280","gb2312","gb_2312","gb_2312-80","gbk","iso-ir-58","x-gbk"],name:"GBK"},{labels:["gb18030"],name:"gb18030"}],heading:"Legacy multi-byte Chinese (simplified) encodings"},{encodings:[{labels:["big5","big5-hkscs","cn-big5","csbig5","x-x-big5"],name:"Big5"}],heading:"Legacy multi-byte Chinese (traditional) encodings"},{encodings:[{labels:["cseucpkdfmtjapanese","euc-jp","x-euc-jp"],name:"EUC-JP"},{labels:["csiso2022jp","iso-2022-jp"],name:"ISO-2022-JP"},{labels:["csshiftjis","ms932","ms_kanji","shift-jis","shift_jis","sjis","windows-31j","x-sjis"],name:"Shift_JIS"}],heading:"Legacy multi-byte Japanese encodings"},{encodings:[{labels:["cseuckr","csksc56011987","euc-kr","iso-ir-149","korean","ks_c_5601-1987","ks_c_5601-1989","ksc5601","ksc_5601","windows-949"],name:"EUC-KR"}],heading:"Legacy multi-byte Korean encodings"},{encodings:[{labels:["csiso2022kr","hz-gb-2312","iso-2022-cn","iso-2022-cn-ext","iso-2022-kr"],name:"replacement"},{labels:["utf-16be"],name:"UTF-16BE"},{labels:["utf-16","utf-16le"],name:"UTF-16LE"},{labels:["x-user-defined"],name:"x-user-defined"}],heading:"Legacy miscellaneous encodings"}],G={};q.forEach(function(e){e.encodings.forEach(function(e){e.labels.forEach(function(n){G[n]=e})})});var X={},Q={},$,Y;Object.defineProperty&&(Object.defineProperty(b.prototype,"encoding",{get:function(){return this._encoding.name.toLowerCase()}}),Object.defineProperty(b.prototype,"fatal",{get:function(){return"fatal"===this._error_mode}}),Object.defineProperty(b.prototype,"ignoreBOM",{get:function(){return this._ignoreBOM}})),b.prototype.decode=function(e,n){var d;d="object"==typeof e&&e instanceof ArrayBuffer?new Uint8Array(e):"object"==typeof e&&"buffer"in e&&e.buffer instanceof ArrayBuffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(0),n=u(n),this._do_not_flush||(this._decoder=Q[this._encoding.name]({fatal:"fatal"===this._error_mode}),this._BOMseen=!1),this._do_not_flush=!!n.stream;for(var i=new t(d),o=[],a,r;(r=i.read(),r!==H)&&!(a=this._decoder.handler(i,r),-1===a);)null!==a&&(Array.isArray(a)?o.push.apply(o,a):o.push(a));if(!this._do_not_flush){do{if(a=this._decoder.handler(i,i.read()),-1===a)break;if(null===a)continue;Array.isArray(a)?o.push.apply(o,a):o.push(a)}while(!i.endOfStream());this._decoder=null}return function(e){return!f(["UTF-8","UTF-16LE","UTF-16BE"],this._encoding.name)||this._ignoreBOM||this._BOMseen||(0<e.length&&65279===e[0]?(this._BOMseen=!0,e.shift()):0<e.length&&(this._BOMseen=!0)),s(e)}.call(this,o)},Object.defineProperty&&Object.defineProperty(E.prototype,"encoding",{get:function(){return this._encoding.name.toLowerCase()}}),E.prototype.encode=function(e,n){e=e===void 0?"":e+"",n=u(n),this._do_not_flush||(this._encoder=X[this._encoding.name]({fatal:"fatal"===this._fatal})),this._do_not_flush=!!n.stream;for(var d=new t(o(e)),i=[],f,s;(s=d.read(),s!==H)&&!(f=this._encoder.handler(d,s),-1===f);)Array.isArray(f)?i.push.apply(i,f):i.push(f);if(!this._do_not_flush){for(;f=this._encoder.handler(d,d.read()),-1!==f;)Array.isArray(f)?i.push.apply(i,f):i.push(f);this._encoder=null}return new Uint8Array(i)},X["UTF-8"]=function(e){return new O(e)},Q["UTF-8"]=function(e){return new v(e)},function(){"encoding-indexes"in d&&q.forEach(function(e){"Legacy single-byte encodings"!==e.heading||e.encodings.forEach(function(e){var n=e.name,d=g(n.toLowerCase());Q[n]=function(e){return new I(d,e)},X[n]=function(e){return new k(d,e)}})})}(),Q.GBK=function(e){return new x(e)},X.GBK=function(e){return new N(e,!0)},X.gb18030=function(e){return new N(e)},Q.gb18030=function(e){return new x(e)},X.Big5=function(e){return new R(e)},Q.Big5=function(e){return new C(e)},X["EUC-JP"]=function(e){return new L(e)},Q["EUC-JP"]=function(e){return new S(e)},X["ISO-2022-JP"]=function(e){return new j(e)},Q["ISO-2022-JP"]=function(e){return new B(e)},X.Shift_JIS=function(e){return new T(e)},Q.Shift_JIS=function(e){return new A(e)},X["EUC-KR"]=function(e){return new D(e)},Q["EUC-KR"]=function(e){return new M(e)},X["UTF-16BE"]=function(e){return new P(!0,e)},Q["UTF-16BE"]=function(e){return new U(!0,e)},X["UTF-16LE"]=function(e){return new P(!1,e)},Q["UTF-16LE"]=function(e){return new U(!1,e)},X["x-user-defined"]=function(e){return new K(e)},Q["x-user-defined"]=function(e){return new F(e)},d.TextEncoder||(d.TextEncoder=E),d.TextDecoder||(d.TextDecoder=b),"undefined"!=typeof n&&n.exports&&(n.exports={TextEncoder:d.TextEncoder,TextDecoder:d.TextDecoder,EncodingIndexes:d["encoding-indexes"]})})(this||{})},{"./encoding-indexes.js":3}],5:[function(e,n,d){(function(i,f){function u(e){return!("_OnNamespaceConnect"!==e&&"_OnNamespaceConnected"!==e&&"_OnNamespaceDisconnect"!==e&&"_OnRoomJoin"!==e&&"_OnRoomJoined"!==e&&"_OnRoomLeave"!==e&&"_OnRoomLeft"!==e)}function o(e){return!(void 0!==e)||!(null!==e)||(""==e||"string"==typeof e||e instanceof String?0===e.length||""===e:!!(e instanceof Error)&&o(e.message))}function s(e){return JSON.stringify(e)}function a(e){return o(e)?"":e.replace(F,"@%!semicolon@%!")}function t(e){return o(e)?"":e.replace(K,";")}function r(e){return new W(e)}function c(e){return e instanceof W}function l(e){if(e.IsNative&&o(e.wait))return e.Body;var n="0",d="0",i=e.Body||"";o(e.Err)||(i=e.Err.message,!c(e.Err)&&(n="1")),e.isNoOp&&(d="1");var f=[e.wait||"",a(e.Namespace),a(e.Room),a(e.Event),n,d,""].join(";");if(e.SetBinary){var u=z.encode(f);f=new Uint8Array(u.length+i.length),f.set(u,0),f.set(i,u.length)}else i instanceof Uint8Array&&(i=H.decode(i,{stream:!1})),f+=i;return f}function p(e,n,d){if(0==d)return[e];var i=e.split(n,d);if(i.length==d){var f=i.join(n)+n;return i.push(e.substr(f.length)),i}return[e]}function m(e,n){var d=new U;if(0==e.length)return d.isInvalid=!0,d;var f=e instanceof ArrayBuffer,u;if(f){for(var s=new Uint8Array(e),a=1,r=0,c=0;c<s.length&&!(s[c]==q&&(a++,r=c,7==a));c++);if(7!=a)return d.isInvalid=!0,d;u=p(H.decode(s.slice(0,r),{stream:!1}),";",5),u.push(e.slice(r+1,e.length)),d.SetBinary=!0}else u=p(e,";",6);if(7!=u.length)return n?(d.Event="_OnNativeMessage",d.Body=e):d.isInvalid=!0,d;d.wait=u[0],d.Namespace=t(u[1]),d.Room=t(u[2]),d.Event=t(u[3]),d.isError="1"==u[4]||!1,d.isNoOp="1"==u[5]||!1;var l=u[6];return o(l)?d.Body="":d.isError?d.Err=new Error(l):d.Body=l,d.isInvalid=!1,d.IsForced=!1,d.IsLocal=!1,d.IsNative=n&&"_OnNativeMessage"==d.Event||!1,d}function g(){if(!S){var e=i.hrtime();return"$"+1e9*e[0]+e[1]}var n=window.performance.now();return"$"+n.toString()}function h(e){return e+";".repeat(6)}function y(e,n){return e.events.has(n.Event)?e.events.get(n.Event)(e,n):e.events.has("_OnAnyEvent")?e.events.get("_OnAnyEvent")(e,n):null}function w(e){return null===e||e===void 0||"undefined"==typeof e}function _(e,n){if(w(e))return w(n)||n("connHandler is empty."),null;var d=new Map,i=new Map,f=0;if(Object.keys(e).forEach(function(n){f++;var u=e[n];if(u instanceof Function)i.set(n,u);else if(u instanceof Map)d.set(n,u);else{var o=new Map;Object.keys(u).forEach(function(e){o.set(e,u[e])}),d.set(n,o)}}),0<i.size){if(f!=i.size)return w(n)||n("all keys of connHandler should be events, mix of namespaces and event callbacks is not supported "+i.size+" vs total "+f),null;d.set("",i)}return d}function b(e,n){return e.has(n)?e.get(n):null}function E(e,n){if(w(e))return n;for(var d in e)if(e.hasOwnProperty(d)){var i=e[d];d=encodeURIComponent("X-Websocket-Header-"+d),i=encodeURIComponent(i);var f=d+"="+i;n=-1==n.indexOf("?")?-1==n.indexOf("#")?n+"?"+f:n.split("#")[0]+"?"+f+"#"+n.split("#")[1]:n.split("?")[0]+"?"+f+"&"+n.split("?")[1]}return n}function v(e,n,d){return O(e,n,0,d)}function O(e,n,d,i){if(S&&0==e.indexOf("/")){var f="https:"==document.location.protocol?"wss":"ws",u=document.location.port?":"+document.location.port:"";e=f+"://"+document.location.hostname+u+e}return-1==e.indexOf("ws")&&(e="ws://"+e),new Promise(function(f,u){WebSocket||u("WebSocket is not accessible through this browser.");var s=_(n,u);if(!w(s)){w(i)&&(i={}),w(i.headers)&&(i.headers={});var a=i.reconnect?i.reconnect:0;0<d&&0<a?i.headers["X-Websocket-Reconnect"]=d.toString():!w(i.headers["X-Websocket-Reconnect"])&&delete i.headers["X-Websocket-Reconnect"];var t=I(e,i),r=new ee(t,s);r.reconnectTries=d,t.binaryType="arraybuffer",t.onmessage=function(e){var n=r.handle(e);return o(n)?void(r.isAcknowledged()&&f(r)):void u(n)},t.onopen=function(){t.send("M")},t.onerror=function(e){r.close(),u(e)},t.onclose=function(){if(r.isClosed());else{if(t.onmessage=void 0,t.onopen=void 0,t.onerror=void 0,t.onclose=void 0,0>=a)return r.close(),null;var d=new Map;r.connectedNamespaces.forEach(function(e,n){var i=[];!w(e.rooms)&&0<e.rooms.size&&e.rooms.forEach(function(e,n){i.push(n)}),d.set(n,i)}),r.close(),k(e,a,function(o){O(e,n,o,i).then(function(e){return w(f)||"function () { [native code] }"==f.toString()?void d.forEach(function(n,d){e.connect(d).then(function(e){return function(n){e.forEach(function(e){n.joinRoom(e)})}}(n))}):void f(e)}).catch(u)})}return null}}})}function I(e,n){return S&&!w(n)?(n.headers&&(e=E(n.headers,e)),n.protocols?new WebSocket(e,n.protocols):new WebSocket(e)):new WebSocket(e,n)}function k(e,n,d){var i=e.replace(/(ws)(s)?\:\/\//,"http$2://"),f=1,u={method:"HEAD",mode:"no-cors"},o=function(){L(i,u).then(function(){d(f)}).catch(function(){f++,setTimeout(function(){o()},n)})};setTimeout(o,n)}function x(e){return!(!e||o(e.message))&&0<=e.message.indexOf("[-1] write closed")}var N=this&&this.__extends||function(){var e=function(n,d){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,n){e.__proto__=n}||function(e,n){for(var d in n)n.hasOwnProperty(d)&&(e[d]=n[d])},e(n,d)};return function(n,d){function i(){this.constructor=n}e(n,d),n.prototype=null===d?Object.create(d):(i.prototype=d.prototype,new i)}}(),C=this&&this.__awaiter||function(e,n,d,i){function f(e){return e instanceof d?e:new d(function(n){n(e)})}return new(d||(d=Promise))(function(d,u){function o(e){try{a(i.next(e))}catch(n){u(n)}}function s(e){try{a(i["throw"](e))}catch(n){u(n)}}function a(e){e.done?d(e.value):f(e.value).then(o,s)}a((i=i.apply(e,n||[])).next())})},R=this&&this.__generator||function(e,n){function d(e){return function(n){return i([e,n])}}function i(d){if(o)throw new TypeError("Generator is already executing.");for(;u;)try{if(o=1,s&&(a=2&d[0]?s["return"]:d[0]?s["throw"]||((a=s["return"])&&a.call(s),0):s.next)&&!(a=a.call(s,d[1])).done)return a;switch((s=0,a)&&(d=[2&d[0],a.value]),d[0]){case 0:case 1:a=d;break;case 4:return u.label++,{value:d[1],done:!1};case 5:u.label++,s=d[1],d=[0];continue;case 7:d=u.ops.pop(),u.trys.pop();continue;default:if((a=u.trys,!(a=0<a.length&&a[a.length-1]))&&(6===d[0]||2===d[0])){u=0;continue}if(3===d[0]&&(!a||d[1]>a[0]&&d[1]<a[3])){u.label=d[1];break}if(6===d[0]&&u.label<a[1]){u.label=a[1],a=d;break}if(a&&u.label<a[2]){u.label=a[2],u.ops.push(d);break}a[2]&&u.ops.pop(),u.trys.pop();continue;}d=n.call(e,u)}catch(n){d=[6,n],s=0}finally{o=a=0}if(5&d[0])throw d[1];return{value:d[0]?d[1]:void 0,done:!0}}var u={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o,s,a,r;return r={next:d(0),throw:d(1),return:d(2)},"function"==typeof Symbol&&(r[Symbol.iterator]=function(){return this}),r},S="undefined"!=typeof window,L="undefined"==typeof fetch?void 0:fetch;S?WebSocket=window.WebSocket:(WebSocket=e("ws"),L=e("node-fetch"),TextDecoder=e("@sinonjs/text-encoding").TextDecoder,TextEncoder=e("@sinonjs/text-encoding").TextEncoder);var B="_OnNamespaceConnected",j="_OnNamespaceDisconnect",A="_OnRoomJoin",T="_OnRoomJoined",M="_OnRoomLeave",D="_OnRoomLeft",J="_OnNativeMessage",U=function(){function e(){}return e.prototype.isConnect=function(){return"_OnNamespaceConnect"==this.Event||!1},e.prototype.isDisconnect=function(){return this.Event==j||!1},e.prototype.isRoomJoin=function(){return this.Event==A||!1},e.prototype.isRoomLeft=function(){return this.Event==D||!1},e.prototype.isWait=function(){return!o(this.wait)&&(this.wait[0]=="#"||this.wait[0]=="$"||!1)},e.prototype.unmarshal=function(){return JSON.parse(this.Body)},e}(),P=";",F=new RegExp(P,"g"),K=new RegExp("@%!semicolon@%!","g"),W=function(e){function n(d){var i=e.call(this,d)||this;return i.name="replyError",Error.captureStackTrace(i,n),Object.setPrototypeOf(i,n.prototype),i}return N(n,e),n}(Error),z=new TextEncoder,H=new TextDecoder("utf-8"),q=P.charCodeAt(0),G=function(){function e(e,n){this.nsConn=e,this.name=n}return e.prototype.emit=function(e,n){var d=new U;return d.Namespace=this.nsConn.namespace,d.Room=this.name,d.Event=e,d.Body=n,this.nsConn.conn.write(d)},e.prototype.leave=function(){var e=new U;return e.Namespace=this.nsConn.namespace,e.Room=this.name,e.Event=M,this.nsConn.askRoomLeave(e)},e}(),X=function(){function e(e,n,d){this.conn=e,this.namespace=n,this.events=d,this.rooms=new Map}return e.prototype.emit=function(e,n){var d=new U;return d.Namespace=this.namespace,d.Event=e,d.Body=n,this.conn.write(d)},e.prototype.emitBinary=function(e,n){var d=new U;return d.Namespace=this.namespace,d.Event=e,d.Body=n,d.SetBinary=!0,this.conn.write(d)},e.prototype.ask=function(e,n){var d=new U;return d.Namespace=this.namespace,d.Event=e,d.Body=n,this.conn.ask(d)},e.prototype.joinRoom=function(e){return C(this,void 0,void 0,function(){return R(this,function(n){switch(n.label){case 0:return[4,this.askRoomJoin(e)];case 1:return[2,n.sent()];}})})},e.prototype.room=function(e){return this.rooms.get(e)},e.prototype.leaveAll=function(){return C(this,void 0,void 0,function(){var e=this,n;return R(this,function(){return n=new U,n.Namespace=this.namespace,n.Event=D,n.IsLocal=!0,this.rooms.forEach(function(d,i){return C(e,void 0,void 0,function(){var e;return R(this,function(d){switch(d.label){case 0:n.Room=i,d.label=1;case 1:return d.trys.push([1,3,,4]),[4,this.askRoomLeave(n)];case 2:return d.sent(),[3,4];case 3:return e=d.sent(),[2,e];case 4:return[2];}})})}),[2,null]})})},e.prototype.forceLeaveAll=function(e){var n=this,d=new U;d.Namespace=this.namespace,d.Event=M,d.IsForced=!0,d.IsLocal=e,this.rooms.forEach(function(e,i){d.Room=i,y(n,d),n.rooms.delete(i),d.Event=D,y(n,d),d.Event=M})},e.prototype.disconnect=function(){var e=new U;return e.Namespace=this.namespace,e.Event=j,this.conn.askDisconnect(e)},e.prototype.askRoomJoin=function(e){var n=this;return new Promise(function(d,i){return C(n,void 0,void 0,function(){var n,f,u,s;return R(this,function(a){switch(a.label){case 0:if(n=this.rooms.get(e),void 0!==n)return d(n),[2];f=new U,f.Namespace=this.namespace,f.Room=e,f.Event=A,f.IsLocal=!0,a.label=1;case 1:return a.trys.push([1,3,,4]),[4,this.conn.ask(f)];case 2:return a.sent(),[3,4];case 3:return u=a.sent(),i(u),[2];case 4:return(s=y(this,f),!o(s))?(i(s),[2]):(n=new G(this,e),this.rooms.set(e,n),f.Event=T,y(this,f),d(n),[2]);}})})})},e.prototype.askRoomLeave=function(e){return C(this,void 0,void 0,function(){var n,d;return R(this,function(i){switch(i.label){case 0:if(!this.rooms.has(e.Room))return[2,Y];i.label=1;case 1:return i.trys.push([1,3,,4]),[4,this.conn.ask(e)];case 2:return i.sent(),[3,4];case 3:return n=i.sent(),[2,n];case 4:return(d=y(this,e),!o(d))?[2,d]:(this.rooms.delete(e.Room),e.Event=D,y(this,e),[2,null]);}})})},e.prototype.replyRoomJoin=function(e){if(!(o(e.wait)||e.isNoOp)){if(!this.rooms.has(e.Room)){var n=y(this,e);if(!o(n))return e.Err=n,void this.conn.write(e);this.rooms.set(e.Room,new G(this,e.Room)),e.Event=T,y(this,e)}this.conn.writeEmptyReply(e.wait)}},e.prototype.replyRoomLeave=function(e){return o(e.wait)||e.isNoOp?void 0:this.rooms.has(e.Room)?void(y(this,e),this.rooms.delete(e.Room),this.conn.writeEmptyReply(e.wait),e.Event=D,y(this,e)):void this.conn.writeEmptyReply(e.wait)},e}(),Q=new Error("invalid payload"),$=new Error("bad namespace"),Y=new Error("bad room"),Z=new Error("use of closed connection"),V=new Error("write closed"),ee=function(){function e(e,n){this.conn=e,this.reconnectTries=0,this._isAcknowledged=!1,this.namespaces=n;var d=n.has("");this.allowNativeMessages=d&&n.get("").has(J),this.queue=[],this.waitingMessages=new Map,this.connectedNamespaces=new Map,this.closed=!1}return e.prototype.wasReconnected=function(){return 0<this.reconnectTries},e.prototype.isAcknowledged=function(){return this._isAcknowledged},e.prototype.handle=function(e){if(!this._isAcknowledged){var n=this.handleAck(e.data);return null==n?(this._isAcknowledged=!0,this.handleQueue()):this.conn.close(),n}return this.handleMessage(e.data)},e.prototype.handleAck=function(e){var n=e[0];switch(n){case"A":var d=e.slice(1);this.ID=d;break;case"H":var i=e.slice(1);return new Error(i);default:return this.queue.push(e),null;}},e.prototype.handleQueue=function(){var e=this;null==this.queue||0==this.queue.length||this.queue.forEach(function(n,d){e.queue.splice(d,1),e.handleMessage(n)})},e.prototype.handleMessage=function(e){var n=m(e,this.allowNativeMessages);if(n.isInvalid)return Q;if(n.IsNative&&this.allowNativeMessages){var d=this.namespace("");return y(d,n)}if(n.isWait()){var i=this.waitingMessages.get(n.wait);if(null!=i)return void i(n)}var f=this.namespace(n.Namespace);switch(n.Event){case"_OnNamespaceConnect":this.replyConnect(n);break;case j:this.replyDisconnect(n);break;case A:if(void 0!==f){f.replyRoomJoin(n);break}case M:if(void 0!==f){f.replyRoomLeave(n);break}default:if(void 0===f)return $;n.IsLocal=!1;var u=y(f,n);if(!o(u))return n.Err=u,this.write(n),u;}return null},e.prototype.connect=function(e){return this.askConnect(e)},e.prototype.waitServerConnect=function(e){var n=this;return w(this.waitServerConnectNotifiers)&&(this.waitServerConnectNotifiers=new Map),new Promise(function(d){return C(n,void 0,void 0,function(){var n=this;return R(this,function(){return this.waitServerConnectNotifiers.set(e,function(){n.waitServerConnectNotifiers.delete(e),d(n.namespace(e))}),[2]})})})},e.prototype.namespace=function(e){return this.connectedNamespaces.get(e)},e.prototype.replyConnect=function(e){if(!(o(e.wait)||e.isNoOp)){var n=this.namespace(e.Namespace);if(void 0!==n)return void this.writeEmptyReply(e.wait);var d=b(this.namespaces,e.Namespace);return w(d)?(e.Err=$,void this.write(e)):void(n=new X(this,e.Namespace,d),this.connectedNamespaces.set(e.Namespace,n),this.writeEmptyReply(e.wait),e.Event=B,y(n,e),!w(this.waitServerConnectNotifiers)&&0<this.waitServerConnectNotifiers.size&&this.waitServerConnectNotifiers.has(e.Namespace)&&this.waitServerConnectNotifiers.get(e.Namespace)())}},e.prototype.replyDisconnect=function(e){if(!(o(e.wait)||e.isNoOp)){var n=this.namespace(e.Namespace);return void 0===n?void this.writeEmptyReply(e.wait):void(n.forceLeaveAll(!0),this.connectedNamespaces.delete(e.Namespace),this.writeEmptyReply(e.wait),y(n,e))}},e.prototype.ask=function(e){var n=this;return new Promise(function(d,i){return n.isClosed()?void i(Z):(e.wait=g(),n.waitingMessages.set(e.wait,function(e){return e.isError?void i(e.Err):void d(e)}),!n.write(e))?void i(V):void 0})},e.prototype.askConnect=function(e){var n=this;return new Promise(function(d,i){return C(n,void 0,void 0,function(){var n,f,u,s,a;return R(this,function(t){switch(t.label){case 0:if(n=this.namespace(e),void 0!==n)return d(n),[2];if(f=b(this.namespaces,e),w(f))return i($),[2];if(u=new U,u.Namespace=e,u.Event="_OnNamespaceConnect",u.IsLocal=!0,n=new X(this,e,f),s=y(n,u),!o(s))return i(s),[2];t.label=1;case 1:return t.trys.push([1,3,,4]),[4,this.ask(u)];case 2:return t.sent(),[3,4];case 3:return a=t.sent(),i(a),[2];case 4:return this.connectedNamespaces.set(e,n),u.Event=B,y(n,u),d(n),[2];}})})})},e.prototype.askDisconnect=function(e){return C(this,void 0,void 0,function(){var n,d;return R(this,function(i){switch(i.label){case 0:if(n=this.namespace(e.Namespace),void 0===n)return[2,$];i.label=1;case 1:return i.trys.push([1,3,,4]),[4,this.ask(e)];case 2:return i.sent(),[3,4];case 3:return d=i.sent(),[2,d];case 4:return n.forceLeaveAll(!0),this.connectedNamespaces.delete(e.Namespace),e.IsLocal=!0,[2,y(n,e)];}})})},e.prototype.isClosed=function(){return this.closed},e.prototype.write=function(e){if(this.isClosed())return!1;if(!e.isConnect()&&!e.isDisconnect()){var n=this.namespace(e.Namespace);if(void 0===n)return!1;if(!o(e.Room)&&!e.isRoomJoin()&&!e.isRoomLeft()&&!n.rooms.has(e.Room))return!1}return this.conn.send(l(e)),!0},e.prototype.writeEmptyReply=function(e){this.conn.send(h(e))},e.prototype.close=function(){var e=this;if(!this.closed){var n=new U;n.Event=j,n.IsForced=!0,n.IsLocal=!0,this.connectedNamespaces.forEach(function(d){d.forceLeaveAll(!0),n.Namespace=d.namespace,y(d,n),e.connectedNamespaces.delete(d.namespace)}),this.waitingMessages.clear(),this.closed=!0,this.conn.readyState===this.conn.OPEN&&this.conn.close()}},e}();(function(){var e={dial:v,isSystemEvent:u,OnNamespaceConnect:"_OnNamespaceConnect",OnNamespaceConnected:B,OnNamespaceDisconnect:j,OnRoomJoin:A,OnRoomJoined:T,OnRoomLeave:M,OnRoomLeft:D,OnAnyEvent:"_OnAnyEvent",OnNativeMessage:J,Message:U,Room:G,NSConn:X,Conn:ee,ErrInvalidPayload:Q,ErrBadNamespace:$,ErrBadRoom:Y,ErrClosed:Z,ErrWrite:V,isCloseError:x,reply:r,marshal:s};if("undefined"!=typeof d)d=e,n.exports=e;else{var i="object"==typeof self&&self.self===self&&self||"object"==typeof f&&f.global===f&&f;i.neffos=e}})()}).call(this,e("_process"),"undefined"==typeof global?"undefined"==typeof self?"undefined"==typeof window?{}:window:self:global)},{"@sinonjs/text-encoding":2,_process:7,"node-fetch":6,ws:8}],6:[function(e,n,d){(function(e){"use strict";var i=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if("undefined"!=typeof e)return e;throw new Error("unable to locate global object")},e=i();n.exports=d=e.fetch,d.default=e.fetch.bind(e),d.Headers=e.Headers,d.Request=e.Request,d.Response=e.Response}).call(this,"undefined"==typeof global?"undefined"==typeof self?"undefined"==typeof window?{}:window:self:global)},{}],7:[function(e,n){function d(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function f(n){if(c===setTimeout)return setTimeout(n,0);if((c===d||!c)&&setTimeout)return c=setTimeout,setTimeout(n,0);try{return c(n,0)}catch(d){try{return c.call(null,n,0)}catch(d){return c.call(this,n,0)}}}function u(n){if(l===clearTimeout)return clearTimeout(n);if((l===i||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(n);try{return l(n)}catch(d){try{return l.call(null,n)}catch(d){return l.call(this,n)}}}function o(){m&&h&&(m=!1,h.length?p=h.concat(p):g=-1,p.length&&s())}function s(){if(!m){var e=f(o);m=!0;for(var n=p.length;n;){for(h=p,p=[];++g<n;)h&&h[g].run();g=-1,n=p.length}h=null,m=!1,u(e)}}function a(e,n){this.fun=e,this.array=n}function t(){}var r=n.exports={},c,l;(function(){try{c="function"==typeof setTimeout?setTimeout:d}catch(n){c=d}try{l="function"==typeof clearTimeout?clearTimeout:i}catch(n){l=i}})();var p=[],m=!1,g=-1,h;r.nextTick=function(e){var n=Array(arguments.length-1);if(1<arguments.length)for(var d=1;d<arguments.length;d++)n[d-1]=arguments[d];p.push(new a(e,n)),1!==p.length||m||f(s)},a.prototype.run=function(){this.fun.apply(null,this.array)},r.title="browser",r.browser=!0,r.env={},r.argv=[],r.version="",r.versions={},r.on=t,r.addListener=t,r.once=t,r.off=t,r.removeListener=t,r.removeAllListeners=t,r.emit=t,r.prependListener=t,r.prependOnceListener=t,r.listeners=function(){return[]},r.binding=function(){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(){throw new Error("process.chdir is not supported")},r.umask=function(){return 0}},{}],8:[function(e,n){'use strict';n.exports=function(){throw new Error("ws does not work in the browser. Browser clients must use the native WebSocket object")}},{}]},{},[1]); \ No newline at end of file diff --git a/websocket/basic/browserify/client.html b/websocket/basic/browserify/client.html new file mode 100644 index 00000000..dc5af80e --- /dev/null +++ b/websocket/basic/browserify/client.html @@ -0,0 +1,10 @@ +<!-- the message's input --> +<input id="input" type="text" /> + +<!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' --> +<button id="sendBtn" disabled>Send</button> + +<!-- the messages will be shown here --> +<pre id="output"></pre> + +<script src="./bundle.js"></script> diff --git a/websocket/basic/browserify/package.json b/websocket/basic/browserify/package.json new file mode 100644 index 00000000..de851367 --- /dev/null +++ b/websocket/basic/browserify/package.json @@ -0,0 +1,16 @@ +{ + "name": "neffos.js.example.browserify", + "version": "0.0.1", + "scripts": { + "browserify": "browserify ./app.js -o ./bundle.js", + "minifyES6": "minify ./bundle.js --outFile ./bundle.js", + "build": "npm run-script browserify && npm run-script minifyES6" + }, + "dependencies": { + "neffos.js": "latest" + }, + "devDependencies": { + "browserify": "^16.2.3", + "babel-minify": "^0.5.0" + } +} diff --git a/websocket/basic/go-client/client.go b/websocket/basic/go-client/client.go new file mode 100644 index 00000000..05464887 --- /dev/null +++ b/websocket/basic/go-client/client.go @@ -0,0 +1,85 @@ +package main + +import ( + "bufio" + "bytes" + "context" + "fmt" + "log" + "os" + "time" + + "github.com/kataras/iris/v12/websocket" +) + +const ( + endpoint = "ws://localhost:8080/echo" + namespace = "default" + dialAndConnectTimeout = 5 * time.Second +) + +// this can be shared with the server.go's. +// `NSConn.Conn` has the `IsClient() bool` method which can be used to +// check if that's is a client or a server-side callback. +var clientEvents = websocket.Namespaces{ + namespace: websocket.Events{ + websocket.OnNamespaceConnected: func(c *websocket.NSConn, msg websocket.Message) error { + log.Printf("connected to namespace: %s", msg.Namespace) + return nil + }, + websocket.OnNamespaceDisconnect: func(c *websocket.NSConn, msg websocket.Message) error { + log.Printf("disconnected from namespace: %s", msg.Namespace) + return nil + }, + "chat": func(c *websocket.NSConn, msg websocket.Message) error { + log.Printf("%s", string(msg.Body)) + return nil + }, + }, +} + +func main() { + ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(dialAndConnectTimeout)) + defer cancel() + + // username := "my_username" + // dialer := websocket.GobwasDialer(websocket.GobwasDialerOptions{Header: websocket.GobwasHeader{"X-Username": []string{username}}}) + dialer := websocket.DefaultGobwasDialer + client, err := websocket.Dial(ctx, dialer, endpoint, clientEvents) + if err != nil { + panic(err) + } + defer client.Close() + + c, err := client.Connect(ctx, namespace) + if err != nil { + panic(err) + } + + c.Emit("chat", []byte("Hello from Go client side!")) + + fmt.Fprint(os.Stdout, ">> ") + scanner := bufio.NewScanner(os.Stdin) + for { + if !scanner.Scan() { + log.Printf("ERROR: %v", scanner.Err()) + return + } + + text := scanner.Bytes() + + if bytes.Equal(text, []byte("exit")) { + if err := c.Disconnect(nil); err != nil { + log.Printf("reply from server: %v", err) + } + break + } + + ok := c.Emit("chat", text) + if !ok { + break + } + + fmt.Fprint(os.Stdout, ">> ") + } +} // try running this program twice or/and run the server's http://localhost:8080 to check the browser client as well. diff --git a/websocket/basic/go.mod b/websocket/basic/go.mod new file mode 100644 index 00000000..a36e1e22 --- /dev/null +++ b/websocket/basic/go.mod @@ -0,0 +1,65 @@ +module github.com/kataras/iris/_examples/websocket/basic + +go 1.22 + +require ( + github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mediocregopher/radix/v3 v3.8.1 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/nats-io/nats.go v1.34.1 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/websocket/basic/go.sum b/websocket/basic/go.sum new file mode 100644 index 00000000..53bff17d --- /dev/null +++ b/websocket/basic/go.sum @@ -0,0 +1,202 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q= +github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee h1:23N+vuMpu0Dh3fbtrWkf/+uIt9zAyPtqJa3fb3M0bp0= +github.com/iris-contrib/middleware/jwt v0.0.0-20240111010557-e34016a4d6ee/go.mod h1:0l8Dv+O13+WeimDdbTzwpOqjtcHYrFfNVBcZbBTV/v8= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede h1:ZnSJQ+ri9x46Yz15wHqSb93Q03yY12XMVLUFDJJ0+/g= +github.com/kataras/neffos v0.0.24-0.20240408172741-99c879ba0ede/go.mod h1:i0dtcTbpnw1lqIbojYtGtZlu6gDWPxJ4Xl2eJ6oQ1bE= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/websocket/basic/nodejs-client/client.js b/websocket/basic/nodejs-client/client.js new file mode 100644 index 00000000..fd4612ef --- /dev/null +++ b/websocket/basic/nodejs-client/client.js @@ -0,0 +1,35 @@ +const neffos = require('neffos.js'); +const stdin = process.openStdin(); + +const wsURL = "ws://localhost:8080/echo"; + +async function runExample() { + try { + const conn = await neffos.dial(wsURL, { + default: { // "default" namespace. + _OnNamespaceConnected: function (nsConn, msg) { + console.log("connected to namespace: " + msg.Namespace); + }, + _OnNamespaceDisconnect: function (nsConn, msg) { + console.log("disconnected from namespace: " + msg.Namespace); + }, + chat: function (nsConn, msg) { // "chat" event. + console.log(msg.Body); + } + } + }); + + const nsConn = await conn.connect("default"); + nsConn.emit("chat", "Hello from Nodejs client side!"); + + stdin.addListener("data", function (data) { + const text = data.toString().trim(); + nsConn.emit("chat", text); + }); + + } catch (err) { + console.error(err); + } +} + +runExample(); diff --git a/websocket/basic/nodejs-client/package.json b/websocket/basic/nodejs-client/package.json new file mode 100644 index 00000000..58540d07 --- /dev/null +++ b/websocket/basic/nodejs-client/package.json @@ -0,0 +1,8 @@ +{ + "name": "neffos.js.example.nodejsclient", + "version": "0.0.1", + "main": "client.js", + "dependencies": { + "neffos.js": "latest" + } +} diff --git a/websocket/basic/overview.png b/websocket/basic/overview.png new file mode 100644 index 00000000..69afa9d3 Binary files /dev/null and b/websocket/basic/overview.png differ diff --git a/websocket/basic/server.go b/websocket/basic/server.go new file mode 100644 index 00000000..60ff818a --- /dev/null +++ b/websocket/basic/server.go @@ -0,0 +1,126 @@ +package main + +import ( + "log" + + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/websocket" + + // Used when "enableJWT" constant is true: + "github.com/iris-contrib/middleware/jwt" +) + +// values should match with the client sides as well. +const enableJWT = true +const namespace = "default" + +// if namespace is empty then simply websocket.Events{...} can be used instead. +var serverEvents = websocket.Namespaces{ + namespace: websocket.Events{ + websocket.OnNamespaceConnected: func(nsConn *websocket.NSConn, msg websocket.Message) error { + // with `websocket.GetContext` you can retrieve the Iris' `Context`. + ctx := websocket.GetContext(nsConn.Conn) + + log.Printf("[%s] connected to namespace [%s] with IP [%s]", + nsConn, msg.Namespace, + ctx.RemoteAddr()) + return nil + }, + websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error { + log.Printf("[%s] disconnected from namespace [%s]", nsConn, msg.Namespace) + return nil + }, + "chat": func(nsConn *websocket.NSConn, msg websocket.Message) error { + // room.String() returns -> NSConn.String() returns -> Conn.String() returns -> Conn.ID() + log.Printf("[%s] sent: %s", nsConn, string(msg.Body)) + + // Write message back to the client message owner with: + // nsConn.Emit("chat", msg) + // Write message to all except this client with: + nsConn.Conn.Server().Broadcast(nsConn, msg) + return nil + }, + }, +} + +func main() { + app := iris.New() + websocketServer := websocket.New( + websocket.DefaultGorillaUpgrader, /* DefaultGobwasUpgrader can be used too. */ + serverEvents) + + j := jwt.New(jwt.Config{ + // Extract by the "token" url, + // so the client should dial with ws://localhost:8080/echo?token=$token + Extractor: jwt.FromParameter("token"), + + ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { + return []byte("My Secret"), nil + }, + + // When set, the middleware verifies that tokens are signed + // with the specific signing algorithm + // If the signing method is not constant the + // `Config.ValidationKeyGetter` callback field can be used + // to implement additional checks + // Important to avoid security issues described here: + // https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ + SigningMethod: jwt.SigningMethodHS256, + }) + + idGen := func(ctx iris.Context) string { + if username := ctx.GetHeader("X-Username"); username != "" { + return username + } + + return websocket.DefaultIDGenerator(ctx) + } + + // serves the endpoint of ws://localhost:8080/echo + // with optional custom ID generator. + websocketRoute := app.Get("/echo", websocket.Handler(websocketServer, idGen)) + + if enableJWT { + // Register the jwt middleware (on handshake): + websocketRoute.Use(j.Serve) + // OR + // + // Check for token through the jwt middleware + // on websocket connection or on any event: + /* websocketServer.OnConnect = func(c *websocket.Conn) error { + ctx := websocket.GetContext(c) + if err := j.CheckJWT(ctx); err != nil { + // will send the above error on the client + // and will not allow it to connect to the websocket server at all. + return err + } + + user := ctx.Values().Get("jwt").(*jwt.Token) + // or just: user := j.Get(ctx) + + log.Printf("This is an authenticated request\n") + log.Printf("Claim content:") + log.Printf("%#+v\n", user.Claims) + + log.Printf("[%s] connected to the server", c.ID()) + + return nil + } */ + } + + // serves the browser-based websocket client. + app.Get("/", func(ctx iris.Context) { + ctx.ServeFile("./browser/index.html") + }) + + app.Get("/other", func(ctx iris.Context) { + ctx.WriteString("Other route") + }) + + // serves the npm browser websocket client usage example. + app.HandleDir("/browserify", iris.Dir("./browserify")) + + // http://localhost:8080 + // http://localhost:8080/browserify/client.html + app.Listen(":8080") +} diff --git a/websocket/chat/main.go b/websocket/chat/main.go deleted file mode 100644 index fce0a664..00000000 --- a/websocket/chat/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/kataras/iris" - "github.com/kataras/iris/websocket" -) - -func main() { - app := iris.New() - - app.Get("/", func(ctx iris.Context) { - ctx.ServeFile("websockets.html", false) // second parameter: enable gzip? - }) - - setupWebsocket(app) - - // x2 - // http://localhost:8080 - // http://localhost:8080 - // write something, press submit, see the result. - app.Run(iris.Addr(":8080")) -} - -func setupWebsocket(app *iris.Application) { - // create our echo websocket server - ws := websocket.New(websocket.Config{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - }) - ws.OnConnection(handleConnection) - - // register the server on an endpoint. - // see the inline javascript code in the websockets.html, this endpoint is used to connect to the server. - app.Get("/echo", ws.Handler()) - - // serve the javascript built'n client-side library, - // see websockets.html script tags, this path is used. - app.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) - }) -} - -func handleConnection(c websocket.Connection) { - // Read events from browser - c.On("chat", func(msg string) { - // Print the message to the console, c.Context() is the iris's http context. - fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg) - // Write message back to the client message owner with: - // c.Emit("chat", msg) - // Write message to all except this client with: - c.To(websocket.Broadcast).Emit("chat", msg) - }) -} diff --git a/websocket/chat/websockets.html b/websocket/chat/websockets.html deleted file mode 100644 index c6d22514..00000000 --- a/websocket/chat/websockets.html +++ /dev/null @@ -1,45 +0,0 @@ -<!-- the message's input --> -<input id="input" type="text" /> - -<!-- when clicked then an iris websocket event will be sent to the server, at this example we registered the 'chat' --> -<button onclick="send()">Send</button> - -<!-- the messages will be shown here --> -<pre id="output"></pre> -<!-- import the iris client-side library for browser--> -<script src="/iris-ws.js"></script> - -<script> - var scheme = document.location.protocol == "https:" ? "wss" : "ws"; - var port = document.location.port ? (":" + document.location.port) : ""; - // see app.Get("/echo", ws.Handler()) on main.go - var wsURL = scheme + "://" + document.location.hostname + port+"/echo"; - - var input = document.getElementById("input"); - var output = document.getElementById("output"); - - // Ws comes from the auto-served '/iris-ws.js' - var socket = new Ws(wsURL) - socket.OnConnect(function () { - output.innerHTML += "Status: Connected\n"; - }); - - socket.OnDisconnect(function () { - output.innerHTML += "Status: Disconnected\n"; - }); - - // read events from the server - socket.On("chat", function (msg) { - addMessage(msg); - }); - - function send() { - addMessage("Me: " + input.value); // write ourselves - socket.Emit("chat", input.value);// send chat event data to the websocket server - input.value = ""; // clear the input - } - - function addMessage(msg) { - output.innerHTML += msg + "\n"; - } -</script> \ No newline at end of file diff --git a/websocket/connectionlist/main.go b/websocket/connectionlist/main.go deleted file mode 100644 index 490f85c6..00000000 --- a/websocket/connectionlist/main.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "fmt" - "sync" - "time" - - "github.com/kataras/iris" - - "github.com/kataras/iris/websocket" -) - -type clientPage struct { - Title string - Host string -} - -func main() { - app := iris.New() - app.RegisterView(iris.HTML("./templates", ".html")) // select the html engine to serve templates - - ws := websocket.New(websocket.Config{}) - - // register the server on an endpoint. - // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server. - app.Get("/my_endpoint", ws.Handler()) - - // serve the javascript built'n client-side library, - // see websockets.html script tags, this path is used. - app.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) - }) - - app.StaticWeb("/js", "./static/js") // serve our custom javascript code - - app.Get("/", func(ctx iris.Context) { - ctx.ViewData("", clientPage{"Client Page", "localhost:8080"}) - ctx.View("client.html") - }) - - Conn := make(map[websocket.Connection]bool) - var myChatRoom = "room1" - var mutex = new(sync.Mutex) - - ws.OnConnection(func(c websocket.Connection) { - c.Join(myChatRoom) - mutex.Lock() - Conn[c] = true - mutex.Unlock() - c.On("chat", func(message string) { - if message == "leave" { - c.Leave(myChatRoom) - c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.") - c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.") - return - } - }) - c.OnDisconnect(func() { - mutex.Lock() - delete(Conn, c) - mutex.Unlock() - fmt.Printf("\nConnection with ID: %s has been disconnected!\n", c.ID()) - }) - }) - - var delay = 1 * time.Second - go func() { - i := 0 - for { - mutex.Lock() - broadcast(Conn, fmt.Sprintf("aaaa %d\n", i)) - mutex.Unlock() - time.Sleep(delay) - i++ - } - }() - - go func() { - i := 0 - for range time.Tick(1 * time.Second) { //another way to get clock signal - mutex.Lock() - broadcast(Conn, fmt.Sprintf("aaaa2 %d\n", i)) - mutex.Unlock() - time.Sleep(delay) - i++ - } - }() - - app.Run(iris.Addr(":8080")) -} - -func broadcast(Conn map[websocket.Connection]bool, message string) { - for k := range Conn { - k.To("room1").Emit("chat", message) - } -} diff --git a/websocket/connectionlist/static/js/chat.js b/websocket/connectionlist/static/js/chat.js deleted file mode 100644 index 920a2050..00000000 --- a/websocket/connectionlist/static/js/chat.js +++ /dev/null @@ -1,38 +0,0 @@ -var messageTxt; -var messages; - -$(function () { - - messageTxt = $("#messageTxt"); - messages = $("#messages"); - - - w = new Ws("ws://" + HOST + "/my_endpoint"); - w.OnConnect(function () { - console.log("Websocket connection established"); - }); - - w.OnDisconnect(function () { - appendMessage($("<div><center><h3>Disconnected</h3></center></div>")); - }); - - w.On("chat", function (message) { - appendMessage($("<div>" + message + "</div>")); - }); - - $("#sendBtn").click(function () { - w.Emit("chat", messageTxt.val().toString()); - messageTxt.val(""); - }); - -}) - - -function appendMessage(messageDiv) { - var theDiv = messages[0]; - var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight; - messageDiv.appendTo(messages); - if (doScroll) { - theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight; - } -} diff --git a/websocket/connectionlist/static/js/vendor/jquery-2.2.3.min.js b/websocket/connectionlist/static/js/vendor/jquery-2.2.3.min.js deleted file mode 100644 index b8c4187d..00000000 --- a/websocket/connectionlist/static/js/vendor/jquery-2.2.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; -}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0!==g?g+"":g}function Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ca(b),i="border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Fa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Ba.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+Oa(b,c,e||(i?"border":"content"),f,h)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b, -e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m=n.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Hb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n}); diff --git a/websocket/connectionlist/templates/client.html b/websocket/connectionlist/templates/client.html deleted file mode 100644 index 35db0daa..00000000 --- a/websocket/connectionlist/templates/client.html +++ /dev/null @@ -1,24 +0,0 @@ -<html> - -<head> -<title>{{ .Title}}</title> -</head> - -<body> - <div id="messages" - style="border-width: 1px; border-style: solid; height: 400px; width: 375px;"> - - </div> - <input type="text" id="messageTxt" /> - <button type="button" id="sendBtn">Send</button> - <script type="text/javascript"> - var HOST = {{.Host}} - </script> - <script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script> - <!-- This is auto-serving by the iris, you don't need to have this file in your disk--> - <script src="/iris-ws.js" type="text/javascript"></script> - <!-- --> - <script src="js/chat.js" type="text/javascript"></script> -</body> - -</html> diff --git a/websocket/custom-go-client/main.go b/websocket/custom-go-client/main.go deleted file mode 100644 index dde7560a..00000000 --- a/websocket/custom-go-client/main.go +++ /dev/null @@ -1,177 +0,0 @@ -package main - -// Run first `go run main.go server` -// and `go run main.go client` as many times as you want. -// Originally written by: github.com/antlaw to describe an old issue. -import ( - "fmt" - "os" - "strings" - "time" - - "github.com/kataras/iris" - "github.com/kataras/iris/websocket" - - xwebsocket "golang.org/x/net/websocket" -) - -// WS is the current websocket connection -var WS *xwebsocket.Conn - -func main() { - if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "server" { - ServerLoop() - } else if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "client" { - ClientLoop() - } else { - fmt.Println("wsserver [server|client]") - } -} - -///////////////////////////////////////////////////////////////////////// -// client side -func sendUntilErr(sendInterval int) { - i := 1 - for { - time.Sleep(time.Duration(sendInterval) * time.Second) - err := SendMessage("2", "all", "objectupdate", "2.UsrSchedule_v1_1") - if err != nil { - fmt.Println("failed to send join message", err.Error()) - return - } - fmt.Println("objectupdate", i) - i++ - } -} - -func recvUntilErr() { - var msg = make([]byte, 2048) - var n int - var err error - i := 1 - for { - if n, err = WS.Read(msg); err != nil { - fmt.Println(err.Error()) - return - } - fmt.Printf("%v Received: %s.%v\n", time.Now(), string(msg[:n]), i) - i++ - } - -} - -//ConnectWebSocket connect a websocket to host -func ConnectWebSocket() error { - var origin = "http://localhost/" - var url = "ws://localhost:8080/socket" - var err error - WS, err = xwebsocket.Dial(url, "", origin) - return err -} - -// CloseWebSocket closes the current websocket connection -func CloseWebSocket() error { - if WS != nil { - return WS.Close() - } - return nil -} - -// SendMessage broadcast a message to server -func SendMessage(serverID, to, method, message string) error { - buffer := []byte(message) - return SendtBytes(serverID, to, method, buffer) -} - -// SendtBytes broadcast a message to server -func SendtBytes(serverID, to, method string, message []byte) error { - // look https://github.com/kataras/iris/blob/master/websocket/message.go , client.go and client.js - // to understand the buffer line: - buffer := []byte(fmt.Sprintf("iris-websocket-message:%v;0;%v;%v;", method, serverID, to)) - buffer = append(buffer, message...) - _, err := WS.Write(buffer) - if err != nil { - fmt.Println(err) - return err - } - return nil -} - -// ClientLoop connects to websocket server, the keep send and recv dataS -func ClientLoop() { - for { - time.Sleep(time.Second) - err := ConnectWebSocket() - if err != nil { - fmt.Println("failed to connect websocket", err.Error()) - continue - } - // time.Sleep(time.Second) - err = SendMessage("2", "all", "join", "dummy2") - go sendUntilErr(1) - recvUntilErr() - err = CloseWebSocket() - if err != nil { - fmt.Println("failed to close websocket", err.Error()) - } - } - -} - -///////////////////////////////////////////////////////////////////////// -// server side - -// OnConnect handles incoming websocket connection -func OnConnect(c websocket.Connection) { - fmt.Println("socket.OnConnect()") - c.On("join", func(message string) { OnJoin(message, c) }) - c.On("objectupdate", func(message string) { OnObjectUpdated(message, c) }) - // ok works too c.EmitMessage([]byte("dsadsa")) - c.OnDisconnect(func() { OnDisconnect(c) }) - -} - -// ServerLoop listen and serve websocket requests -func ServerLoop() { - app := iris.New() - - ws := websocket.New(websocket.Config{}) - - // register the server on an endpoint. - // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server. - app.Get("/socket", ws.Handler()) - - ws.OnConnection(OnConnect) - app.Run(iris.Addr(":8080")) -} - -// OnJoin handles Join broadcast group request -func OnJoin(message string, c websocket.Connection) { - t := time.Now() - c.Join("server2") - fmt.Println("OnJoin() time taken:", time.Since(t)) -} - -// OnObjectUpdated broadcasts to all client an incoming message -func OnObjectUpdated(message string, c websocket.Connection) { - t := time.Now() - s := strings.Split(message, ";") - if len(s) != 3 { - fmt.Println("OnObjectUpdated() invalid message format:" + message) - return - } - serverID, _, objectID := s[0], s[1], s[2] - err := c.To("server"+serverID).Emit("objectupdate", objectID) - if err != nil { - fmt.Println(err, "failed to broacast object") - return - } - fmt.Println(fmt.Sprintf("OnObjectUpdated() message:%v, time taken: %v", message, time.Since(t))) -} - -// OnDisconnect clean up things when a client is disconnected -func OnDisconnect(c websocket.Connection) { - c.Leave("server2") - fmt.Println("OnDisconnect(): client disconnected!") - -} diff --git a/websocket/gorilla-filewatch/go.mod b/websocket/gorilla-filewatch/go.mod new file mode 100644 index 00000000..6fe39108 --- /dev/null +++ b/websocket/gorilla-filewatch/go.mod @@ -0,0 +1,54 @@ +module gorilla-filewatch-example + +go 1.22 + +require ( + github.com/gorilla/websocket v1.5.1 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/websocket/gorilla-filewatch/go.sum b/websocket/gorilla-filewatch/go.sum new file mode 100644 index 00000000..94127478 --- /dev/null +++ b/websocket/gorilla-filewatch/go.sum @@ -0,0 +1,178 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/websocket/gorilla-filewatch/main.go b/websocket/gorilla-filewatch/main.go new file mode 100644 index 00000000..4254ab50 --- /dev/null +++ b/websocket/gorilla-filewatch/main.go @@ -0,0 +1,170 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// This example shows a use case with gorilla webscokets package +// sends a file to the browser client for display whenever the file is modified. +// +// $ go run main.go <name of file to watch> +// # Open http://localhost:8080/ . +// # Modify the file to see it update in the browser. +package main + +import ( + "flag" + "log" + "os" + "strconv" + "time" + + "github.com/gorilla/websocket" + "github.com/kataras/iris/v12" +) + +const ( + // Time allowed to write the file to the client. + writeWait = 10 * time.Second + + // Time allowed to read the next pong message from the client. + pongWait = 60 * time.Second + + // Send pings to client with this period. Must be less than pongWait. + pingPeriod = (pongWait * 9) / 10 + + // Poll file for changes with this period. + filePeriod = 10 * time.Second +) + +var ( + addr = flag.String("addr", ":8080", "http service address") + filename string + upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + } +) + +func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) { + fi, err := os.Stat(filename) + if err != nil { + return nil, lastMod, err + } + if !fi.ModTime().After(lastMod) { + return nil, lastMod, nil + } + p, err := os.ReadFile(filename) + if err != nil { + return nil, fi.ModTime(), err + } + return p, fi.ModTime(), nil +} + +func reader(ws *websocket.Conn) { + defer ws.Close() + ws.SetReadLimit(512) + ws.SetReadDeadline(time.Now().Add(pongWait)) + ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) + for { + _, _, err := ws.ReadMessage() + if err != nil { + break + } + } +} + +func writer(ws *websocket.Conn, lastMod time.Time) { + lastError := "" + pingTicker := time.NewTicker(pingPeriod) + fileTicker := time.NewTicker(filePeriod) + defer func() { + pingTicker.Stop() + fileTicker.Stop() + ws.Close() + }() + for { + select { + case <-fileTicker.C: + var p []byte + var err error + + p, lastMod, err = readFileIfModified(lastMod) + + if err != nil { + if s := err.Error(); s != lastError { + lastError = s + p = []byte(lastError) + } + } else { + lastError = "" + } + + if p != nil { + ws.SetWriteDeadline(time.Now().Add(writeWait)) + if err := ws.WriteMessage(websocket.TextMessage, p); err != nil { + return + } + } + case <-pingTicker.C: + ws.SetWriteDeadline(time.Now().Add(writeWait)) + if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil { + return + } + } + } +} + +func serveWs(ctx iris.Context) { + ws, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil) + if err != nil { + if _, ok := err.(websocket.HandshakeError); !ok { + log.Println(err) + } + return + } + + var lastMod time.Time + if n, err := strconv.ParseInt(ctx.FormValue("lastMod"), 16, 64); err == nil { + lastMod = time.Unix(0, n) + } + + go writer(ws, lastMod) + reader(ws) +} + +func serveHome(ctx iris.Context) { + p, lastMod, err := readFileIfModified(time.Time{}) + if err != nil { + p = []byte(err.Error()) + lastMod = time.Unix(0, 0) + } + var v = struct { + Host string + Data string + LastMod string + }{ + ctx.Host(), + string(p), + strconv.FormatInt(lastMod.UnixNano(), 16), + } + if err := ctx.View("home.html", v); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } +} + +// $ go get github.com/gorilla/websocket +// $ go run main.go testfile.txt +func main() { + flag.Parse() + if flag.NArg() != 1 { + log.Fatal("filename not specified") + } + filename = flag.Args()[0] + + app := iris.New() + app.RegisterView(iris.HTML("./views", ".html")) + app.Get("/", serveHome) + app.Any("/ws", serveWs) + + app.Listen(*addr) +} diff --git a/websocket/gorilla-filewatch/testfile.txt b/websocket/gorilla-filewatch/testfile.txt new file mode 100644 index 00000000..21b4fc73 --- /dev/null +++ b/websocket/gorilla-filewatch/testfile.txt @@ -0,0 +1,4 @@ +Some Contents +# you can edit this file locally +# and http://localhost:8080 +# will render the new contents through the live websocket connection. \ No newline at end of file diff --git a/websocket/gorilla-filewatch/views/home.html b/websocket/gorilla-filewatch/views/home.html new file mode 100644 index 00000000..e8e1d1d9 --- /dev/null +++ b/websocket/gorilla-filewatch/views/home.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <title>WebSocket Example</title> + </head> + <body> + <pre id="fileData">{{.Data}}</pre> + <script type="text/javascript"> + (function() { + var data = document.getElementById("fileData"); + var conn = new WebSocket("ws://{{.Host}}/ws?lastMod={{.LastMod}}"); + conn.onclose = function(evt) { + data.textContent = 'Connection closed'; + } + conn.onmessage = function(evt) { + console.log('file updated'); + data.textContent = evt.data; + } + })(); + </script> + </body> +</html> \ No newline at end of file diff --git a/websocket/native-messages/main.go b/websocket/native-messages/main.go index 254cb2a6..ffd83d57 100644 --- a/websocket/native-messages/main.go +++ b/websocket/native-messages/main.go @@ -1,21 +1,12 @@ package main import ( - "fmt" + "log" - "github.com/kataras/iris" - - "github.com/kataras/iris/websocket" + "github.com/kataras/iris/v12" + "github.com/kataras/iris/v12/websocket" ) -/* Native messages no need to import the iris-ws.js to the ./templates.client.html -Use of: OnMessage and EmitMessage. - - -NOTICE: IF YOU HAVE RAN THE PREVIOUS EXAMPLES YOU HAVE TO CLEAR YOUR BROWSER's CACHE -BECAUSE chat.js is different than the CACHED. OTHERWISE YOU WILL GET Ws is undefined from the browser's console, because it will use the cached. -*/ - type clientPage struct { Title string Host string @@ -26,36 +17,46 @@ func main() { app.RegisterView(iris.HTML("./templates", ".html")) // select the html engine to serve templates - ws := websocket.New(websocket.Config{ - // to enable binary messages (useful for protobuf): - // BinaryMessages: true, + // Almost all features of neffos are disabled because no custom message can pass + // when app expects to accept and send only raw websocket native messages. + // When only allow native messages is a fact? + // When the registered namespace is just one and it's empty + // and contains only one registered event which is the `OnNativeMessage`. + // When `Events{...}` is used instead of `Namespaces{ "namespaceName": Events{...}}` + // then the namespace is empty "". + ws := websocket.New(websocket.DefaultGorillaUpgrader, websocket.Events{ + websocket.OnNativeMessage: func(nsConn *websocket.NSConn, msg websocket.Message) error { + log.Printf("Server got: %s from [%s]", msg.Body, nsConn.Conn.ID()) + + nsConn.Conn.Server().Broadcast(nsConn, msg) + return nil + }, }) - // register the server on an endpoint. - // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server. - app.Get("/my_endpoint", ws.Handler()) - - app.StaticWeb("/js", "./static/js") // serve our custom javascript code + ws.OnConnect = func(c *websocket.Conn) error { + log.Printf("[%s] Connected to server!", c.ID()) + return nil + } - app.Get("/", func(ctx iris.Context) { - ctx.ViewData("", clientPage{"Client Page", "localhost:8080"}) - ctx.View("client.html") - }) + ws.OnDisconnect = func(c *websocket.Conn) { + log.Printf("[%s] Disconnected from server", c.ID()) + } - ws.OnConnection(func(c websocket.Connection) { + app.HandleDir("/js", iris.Dir("./static/js")) // serve our custom javascript code. - c.OnMessage(func(data []byte) { - message := string(data) - c.To(websocket.Broadcast).EmitMessage([]byte("Message from: " + c.ID() + "-> " + message)) // broadcast to all clients except this - c.EmitMessage([]byte("Me: " + message)) // writes to itself - }) - - c.OnDisconnect(func() { - fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID()) - }) + // register the server on an endpoint. + // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server. + app.Get("/my_endpoint", websocket.Handler(ws)) + app.Get("/", func(ctx iris.Context) { + if err := ctx.View("client.html", clientPage{"Client Page", "localhost:8080"}); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } }) - app.Run(iris.Addr(":8080")) - + // Target some browser windows/tabs to http://localhost:8080 and send some messages, + // see the static/js/chat.js, + // note that the client is using only the browser's native WebSocket API instead of the neffos one. + app.Listen(":8080") } diff --git a/websocket/native-messages/static/js/chat.js b/websocket/native-messages/static/js/chat.js index 344ea3b7..b4fda3a2 100644 --- a/websocket/native-messages/static/js/chat.js +++ b/websocket/native-messages/static/js/chat.js @@ -1,38 +1,35 @@ -var messageTxt; -var messages; - -$(function () { - - messageTxt = $("#messageTxt"); - messages = $("#messages"); - - - w = new WebSocket("ws://" + HOST + "/my_endpoint"); - w.onopen = function () { - console.log("Websocket connection enstablished"); - }; - - w.onclose = function () { - appendMessage($("<div><center><h3>Disconnected</h3></center></div>")); - }; - w.onmessage = function(message){ - appendMessage($("<div>" + message.data + "</div>")); - }; - - - $("#sendBtn").click(function () { - w.send(messageTxt.val().toString()); - messageTxt.val(""); - }); - -}) - - -function appendMessage(messageDiv) { - var theDiv = messages[0]; - var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight; - messageDiv.appendTo(messages); - if (doScroll) { - theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight; - } +var messageTxt = document.getElementById("messageTxt"); +var messages = document.getElementById("messages"); +var sendBtn = document.getElementById("sendBtn") + +w = new WebSocket("ws://" + HOST + "/my_endpoint"); +w.onopen = function () { + console.log("Websocket connection enstablished"); +}; + +w.onclose = function () { + appendMessage("<div><center><h3>Disconnected</h3></center></div>"); +}; +w.onmessage = function (message) { + appendMessage("<div>" + message.data + "</div>"); +}; + +sendBtn.onclick = function () { + myText = messageTxt.value; + messageTxt.value = ""; + + appendMessage("<div style='color: red'> me: " + myText + "</div>"); + w.send(myText); +}; + +messageTxt.addEventListener("keyup", function (e) { + if (e.keyCode === 13) { + e.preventDefault(); + + sendBtn.click(); + } +}); + +function appendMessage(messageDivHTML) { + messages.insertAdjacentHTML('afterbegin', messageDivHTML); } diff --git a/websocket/native-messages/static/js/vendor/jquery-2.2.3.min.js b/websocket/native-messages/static/js/vendor/jquery-2.2.3.min.js deleted file mode 100644 index b8c4187d..00000000 --- a/websocket/native-messages/static/js/vendor/jquery-2.2.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; -}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0!==g?g+"":g}function Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ca(b),i="border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Fa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Ba.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+Oa(b,c,e||(i?"border":"content"),f,h)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b, -e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m=n.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Hb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n}); diff --git a/websocket/native-messages/templates/client.html b/websocket/native-messages/templates/client.html index 312a4143..c443a94f 100644 --- a/websocket/native-messages/templates/client.html +++ b/websocket/native-messages/templates/client.html @@ -1,21 +1,19 @@ <html> <head> -<title>{{ .Title}}</title> + <title>{{ .Title}}</title> </head> -<body> - <div id="messages" - style="border-width: 1px; border-style: solid; height: 400px; width: 375px;"> - - </div> +<body style="padding:10px;"> <input type="text" id="messageTxt" /> <button type="button" id="sendBtn">Send</button> + <div id="messages" style="width: 375px;margin:10 0 0 0px;border-top: 1px solid black;"> + </div> + <script type="text/javascript"> - var HOST = {{.Host}} + var HOST = {{.Host }} </script> - <script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script> <script src="js/chat.js" type="text/javascript"></script> </body> -</html> +</html> \ No newline at end of file diff --git a/websocket/online-visitors/main.go b/websocket/online-visitors/main.go new file mode 100644 index 00000000..5b2b9651 --- /dev/null +++ b/websocket/online-visitors/main.go @@ -0,0 +1,179 @@ +package main + +import ( + "fmt" + "sync/atomic" + + "github.com/kataras/iris/v12" + + "github.com/kataras/iris/v12/websocket" +) + +var events = websocket.Namespaces{ + "default": websocket.Events{ + websocket.OnRoomJoined: onRoomJoined, + websocket.OnRoomLeft: onRoomLeft, + }, +} + +func main() { + // init the web application instance + // app := iris.New() + app := iris.Default() + + // load templates + app.RegisterView(iris.HTML("./templates", ".html").Reload(true)) + // setup the websocket server + ws := websocket.New(websocket.DefaultGorillaUpgrader, events) + + app.Get("/my_endpoint", websocket.Handler(ws)) + + // register static assets request path and system directory + app.HandleDir("/js", iris.Dir("./static/assets/js")) + + h := func(ctx iris.Context) { + ctx.ViewData("", page{PageID: "index page"}) + if err := ctx.View("index.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + } + + h2 := func(ctx iris.Context) { + ctx.ViewData("", page{PageID: "other page"}) + if err := ctx.View("other.html"); err != nil { + ctx.HTML("<h3>%s</h3>", err.Error()) + return + } + } + + // Open some browser tabs/or windows + // and navigate to + // http://localhost:8080/ and http://localhost:8080/other multiple times. + // Each page has its own online-visitors counter. + app.Get("/", h) + app.Get("/other", h2) + app.Listen(":8080") +} + +type page struct { + PageID string +} + +type pageView struct { + source string + count uint64 +} + +func (v *pageView) increment() { + atomic.AddUint64(&v.count, 1) +} + +func (v *pageView) decrement() { + atomic.AddUint64(&v.count, ^uint64(0)) +} + +func (v *pageView) getCount() uint64 { + return atomic.LoadUint64(&v.count) +} + +type ( + pageViews []pageView +) + +func (v *pageViews) Add(source string) { + args := *v + n := len(args) + for i := 0; i < n; i++ { + kv := &args[i] + if kv.source == source { + kv.increment() + return + } + } + + c := cap(args) + if c > n { + args = args[:n+1] + kv := &args[n] + kv.source = source + kv.count = 1 + *v = args + return + } + + kv := pageView{} + kv.source = source + kv.count = 1 + *v = append(args, kv) +} + +func (v *pageViews) Get(source string) *pageView { + args := *v + n := len(args) + for i := 0; i < n; i++ { + kv := &args[i] + if kv.source == source { + return kv + } + } + return nil +} + +func (v *pageViews) Reset() { + *v = (*v)[:0] +} + +var v pageViews + +func viewsCountBytes(viewsCount uint64) []byte { + // * there are other methods to convert uint64 to []byte + return []byte(fmt.Sprintf("%d", viewsCount)) +} + +func onRoomJoined(ns *websocket.NSConn, msg websocket.Message) error { + // the roomName here is the source. + pageSource := string(msg.Room) + + v.Add(pageSource) + + viewsCount := v.Get(pageSource).getCount() + if viewsCount == 0 { + viewsCount++ // count should be always > 0 here + } + + // fire the "onNewVisit" client event + // on each connection joined to this room (source page) + // and notify of the new visit, + // including this connection (see nil on first input arg). + ns.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Room: pageSource, + Event: "onNewVisit", // fire the "onNewVisit" client event. + Body: viewsCountBytes(viewsCount), + }) + + return nil +} + +func onRoomLeft(ns *websocket.NSConn, msg websocket.Message) error { + // the roomName here is the source. + pageV := v.Get(msg.Room) + if pageV == nil { + return nil // for any case that this room is not a pageView source + } + // decrement -1 the specific counter for this page source. + pageV.decrement() + + // fire the "onNewVisit" client event + // on each connection joined to this room (source page) + // and notify of the new, decremented by one, visits count. + ns.Conn.Server().Broadcast(nil, websocket.Message{ + Namespace: msg.Namespace, + Room: msg.Room, + Event: "onNewVisit", + Body: viewsCountBytes(pageV.getCount()), + }) + + return nil +} diff --git a/websocket/online-visitors/static/assets/js/visitors.js b/websocket/online-visitors/static/assets/js/visitors.js new file mode 100644 index 00000000..0e74bc29 --- /dev/null +++ b/websocket/online-visitors/static/assets/js/visitors.js @@ -0,0 +1,24 @@ +(function () { + var events = { + default: { + _OnNamespaceConnected: function (ns, msg) { + ns.joinRoom(PAGE_SOURCE); + }, + _OnNamespaceDisconnect: function (ns, msg) { + document.getElementById("online_views").innerHTML = "you've been disconnected"; + }, + onNewVisit: function (ns, msg) { + var text = "1 online view"; + var onlineViews = Number(msg.Body); + if (onlineViews > 1) { + text = onlineViews + " online views"; + } + document.getElementById("online_views").innerHTML = text; + } + } + }; + + neffos.dial("ws://localhost:8080/my_endpoint", events).then(function (client) { + client.connect("default"); + }); +})(); diff --git a/tutorial/online-visitors/templates/index.html b/websocket/online-visitors/templates/index.html similarity index 78% rename from tutorial/online-visitors/templates/index.html rename to websocket/online-visitors/templates/index.html index 92028ff5..bdf1503e 100644 --- a/tutorial/online-visitors/templates/index.html +++ b/websocket/online-visitors/templates/index.html @@ -30,14 +30,14 @@ </div> <script type="text/javascript"> - /* take the page source from our passed struct on .Render */ - var PAGE_SOURCE = {{ .PageID }} + /* take the page source from our passed struct on .Render */ + var PAGE_SOURCE = {{ .PageID }} </script> - <script src="/iris-ws.js"></script> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> <script src="/js/visitors.js"></script> </body> -</html> +</html> \ No newline at end of file diff --git a/tutorial/online-visitors/templates/other.html b/websocket/online-visitors/templates/other.html similarity index 63% rename from tutorial/online-visitors/templates/other.html rename to websocket/online-visitors/templates/other.html index 3c9d0de0..c90ac9c0 100644 --- a/tutorial/online-visitors/templates/other.html +++ b/websocket/online-visitors/templates/other.html @@ -16,14 +16,14 @@ <script type="text/javascript"> - /* take the page source from our passed struct on .Render */ - var PAGE_SOURCE = {{ .PageID }} + /* take the page source from our passed struct on .Render */ + var PAGE_SOURCE = {{ .PageID }} </script> - <script src="/iris-ws.js"></script> + <script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.27/dist/neffos.min.js"></script> <script src="/js/visitors.js"></script> </body> -</html> +</html> \ No newline at end of file diff --git a/websocket/secure/README.md b/websocket/secure/README.md new file mode 100644 index 00000000..9b99bafd --- /dev/null +++ b/websocket/secure/README.md @@ -0,0 +1,6 @@ +# Secure Websockets + +1. Run your server through `https://` (`iris.Run(iris.TLS)` or `iris.Run(iris.AutoTLS)` or a custom `iris.Listener(...)`) +2. Nothing changes inside the whole app, including the websocket side +3. The clients must dial the websocket server endpoint (i.e `/echo`) via `wss://` prefix (instead of the non-secure `ws://`), for example `wss://example.com/echo` +4. Ready to GO. diff --git a/websocket/secure/main.go b/websocket/secure/main.go deleted file mode 100644 index 3d289114..00000000 --- a/websocket/secure/main.go +++ /dev/null @@ -1,174 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "os" - "time" - - "github.com/kataras/iris" - - "github.com/kataras/iris/websocket" -) - -type clientPage struct { - Title string - Host string -} - -func main() { - app := iris.New() - app.RegisterView(iris.HTML("./templates", ".html")) // select the html engine to serve templates - - ws := websocket.New(websocket.Config{}) - - // register the server on an endpoint. - // see the inline javascript code i the websockets.html, this endpoint is used to connect to the server. - app.Get("/my_endpoint", ws.Handler()) - - // serve the javascript built'n client-side library, - // see websockets.html script tags, this path is used. - app.Any("/iris-ws.js", func(ctx iris.Context) { - ctx.Write(websocket.ClientSource) - }) - - app.StaticWeb("/js", "./static/js") - app.Get("/", func(ctx iris.Context) { - // send our custom javascript source file before client really asks for that - // using the go v1.8's HTTP/2 Push. - // Note that you have to listen using ListenTLS in order this to work. - if err := ctx.ResponseWriter().Push("/js/chat.js", nil); err != nil { - ctx.Application().Logger().Warn(err.Error()) - } - ctx.ViewData("", clientPage{"Client Page", ctx.Host()}) - ctx.View("client.html") - }) - - var myChatRoom = "room1" - - ws.OnConnection(func(c websocket.Connection) { - // Context returns the (upgraded) iris.Context of this connection - // avoid using it, you normally don't need it, - // websocket has everything you need to authenticate the user BUT if it's necessary - // then you use it to receive user information, for example: from headers. - - // ctx := c.Context() - - // join to a room (optional) - c.Join(myChatRoom) - - c.On("chat", func(message string) { - if message == "leave" { - c.Leave(myChatRoom) - c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.") - c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.") - return - } - // to all except this connection -> - // c.To(websocket.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message) - // to all connected clients: c.To(websocket.All) - - // to the client itself -> - //c.Emit("chat", "Message from myself: "+message) - - //send the message to the whole room, - //all connections are inside this room will receive this message - c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message) - }) - - // or create a new leave event - // c.On("leave", func() { - // c.Leave(myChatRoom) - // }) - - c.OnDisconnect(func() { - fmt.Printf("Connection with ID: %s has been disconnected!\n", c.ID()) - }) - }) - - listenTLS(app) - -} - -// a test listenTLS for our localhost -func listenTLS(app *iris.Application) { - - const ( - testTLSCert = `-----BEGIN CERTIFICATE----- -MIIDBTCCAe2gAwIBAgIJAOYzROngkH6NMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV -BAMMDmxvY2FsaG9zdDo4MDgwMB4XDTE3MDIxNzAzNDM1NFoXDTI3MDIxNTAzNDM1 -NFowGTEXMBUGA1UEAwwObG9jYWxob3N0OjgwODAwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCfsiVHO14FpKsi0pvBv68oApQm2MO+dCvq87sDU4E0QJhG -KV1RCUmQVypChEqdLlUQsopcXSyKwbWoyg1/KNHYO3DHMfePb4bC1UD2HENq7Ph2 -8QJTEi/CJvUB9hqke/YCoWYdjFiI3h3Hw8q5whGO5XR3R23z69vr5XxoNlcF2R+O -TdkzArd0CWTZS27vbgdnyi9v3Waydh/rl+QRtPUgEoCEqOOkMSMldXO6Z9GlUk9b -FQHwIuEnlSoVFB5ot5cqebEjJnWMLLP83KOCQekJeHZOyjeTe8W0Fy1DGu5fvFNh -xde9e/7XlFE//00vT7nBmJAUV/2CXC8U5lsjLEqdAgMBAAGjUDBOMB0GA1UdDgQW -BBQOfENuLn/t0Z4ZY1+RPWaz7RBH+TAfBgNVHSMEGDAWgBQOfENuLn/t0Z4ZY1+R -PWaz7RBH+TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBG7AEEuIq6 -rWCE5I2t4IXz0jN7MilqEhUWDbUajl1paYf6Ikx5QhMsFx21p6WEWYIYcnWAKZe2 -chAgnnGojuxdx0qjiaH4N4xWGHsWhaesnIF1xJepLlX3kJZQURvRxM4wlljlQPIb -9tqzKP131K1HDqplAtp7nWQ72m3J0ZfzH0mYIUxuaS/uQIVtgKqdilwy/VE5dRZ9 -QFIb4G9TnNThXMqgTLjfNr33jVbTuv6fzKHYNbCkP3L10ydEs/ddlREmtsn9nE8Q -XCTIYXzA2kr5kWk7d3LkUiSvu3g2S1Ol1YaIKaOQyRveseCGwR4xohLT+dPUW9dL -3hDVLlwE3mB3 ------END CERTIFICATE----- - -` - testTLSKey = `-----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAn7IlRzteBaSrItKbwb+vKAKUJtjDvnQr6vO7A1OBNECYRild -UQlJkFcqQoRKnS5VELKKXF0sisG1qMoNfyjR2DtwxzH3j2+GwtVA9hxDauz4dvEC -UxIvwib1AfYapHv2AqFmHYxYiN4dx8PKucIRjuV0d0dt8+vb6+V8aDZXBdkfjk3Z -MwK3dAlk2Utu724HZ8ovb91msnYf65fkEbT1IBKAhKjjpDEjJXVzumfRpVJPWxUB -8CLhJ5UqFRQeaLeXKnmxIyZ1jCyz/NyjgkHpCXh2Tso3k3vFtBctQxruX7xTYcXX -vXv+15RRP/9NL0+5wZiQFFf9glwvFOZbIyxKnQIDAQABAoIBAEzBx4ExW8PCni8i -o5LAm2PTuXniflMwa1uGwsCahmOjGI3AnAWzPRSPkNRf2a0q8+AOsMosTphy+umi -FFKmQBZ6m35i2earaE6FSbABbbYbKGGi/ccH2sSrDOBgdfXRTzF8eiSBrJw8hnvZ -87rNOLtCNnSOdJ7lItODfgRo+fLo4uQenJ8VONYwtwm1ejn8qLXq8O5zF66IYUD6 -gAzqOiAWumgZL0tEmndeQ+noe4STpJZlOjiCsA12NiJaKDDeDIn5A/pXce+bYNfJ -k4yoroyq/JXBkhyuZDvX9vYp5AA+Q68h8/KmsKkifUgSGSHun5/80lYyT/f60TLX -PxT9GYECgYEA0s8qck7L29nBBTQ6IPF3GHGmqiRdfH+qhP/Jn4NtoW3XuVe4A15i -REq1L8WAiOUIBnBaD8HzbeioqJJYx1pu7x9h/GCNDhdBfwhTjnBe+JjfLqvJKnc0 -HUT5wj4DVqattxKzUW8kTRBSWtVremzeffDo+EL6dnR7Bc02Ibs4WpUCgYEAwe34 -Uqhie+/EFr4HjYRUNZSNgYNAJkKHVxk4qGzG5VhvjPafnHUbo+Kk/0QW7eIB+kvR -FDO8oKh9wTBrWZEcLJP4jDIKh4y8hZTo9B8EjxFONXVxZlOSYuGjheL8AiLzE7L9 -C1spaKMM/MyxAXDRHpG/NeEgXM7Kn6kUGwJdNekCgYAshLNiEGHcu8+XWcAs1NFh -yB56L9PORuerzpi1pvuv65JzAaNKktQNt/krbXoHbtaTBYb/bOYLf+aeMsmsz9w9 -g1MeCQXAxAiA2zFKE1D7Ds2S/ZQt8559z+MusgnicrCcyMY1nFL+M0QxCoD4CaWy -0v1f8EUUXuTcBMo5tV/hQQKBgDoBBW8jsiFDu7DZscSgOde00QZVzZAkAfsJLisi -LfNXGjZdZawUUuoX1iYLpZgNK25D0wtp1hdvjf2Ej/dAMd8bexHjvcaBT7ncqjiq -NmDcWjofIIXspTIyLwjStXGmJnJT7N/CqoYDjtTmHGND7Shpi3mAFn/r0isjFUJm -2J5RAoGALuGXxzmSRWmkIp11F/Qr3PBFWBWkrRWaH2TRLMhrU/wO8kCsSyo4PmAZ -ltOfD7InpDiCu43hcDPQ/29FUbDnmAhvMnmIQuHXGgPF/LhqEhbKPA/o/eZdQVCK -QG+tmveBBIYMed5YbWstZu/95lIHF+u8Hl+Z6xgveozfE5yqiUA= ------END RSA PRIVATE KEY----- - - ` - ) - - // create the key and cert files on the fly, and delete them when this test finished - certFile, ferr := ioutil.TempFile("", "cert") - - if ferr != nil { - panic(ferr) - } - - keyFile, ferr := ioutil.TempFile("", "key") - if ferr != nil { - panic(ferr) - } - - certFile.WriteString(testTLSCert) - keyFile.WriteString(testTLSKey) - - // https://localhost - app.Run(iris.TLS("localhost:443", certFile.Name(), keyFile.Name())) - - certFile.Close() - time.Sleep(50 * time.Millisecond) - os.Remove(certFile.Name()) - - keyFile.Close() - time.Sleep(50 * time.Millisecond) - os.Remove(keyFile.Name()) -} diff --git a/websocket/secure/static/js/chat.js b/websocket/secure/static/js/chat.js deleted file mode 100644 index 1bef06bd..00000000 --- a/websocket/secure/static/js/chat.js +++ /dev/null @@ -1,38 +0,0 @@ -var messageTxt; -var messages; - -$(function () { - - messageTxt = $("#messageTxt"); - messages = $("#messages"); - - /* secure wss because we ListenTLS */ - w = new Ws("wss://" + HOST + "/my_endpoint"); - w.OnConnect(function () { - console.log("Websocket connection established"); - }); - - w.OnDisconnect(function () { - appendMessage($("<div><center><h3>Disconnected</h3></center></div>")); - }); - - w.On("chat", function (message) { - appendMessage($("<div>" + message + "</div>")); - }); - - $("#sendBtn").click(function () { - w.Emit("chat", messageTxt.val().toString()); - messageTxt.val(""); - }); - -}) - - -function appendMessage(messageDiv) { - var theDiv = messages[0]; - var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight; - messageDiv.appendTo(messages); - if (doScroll) { - theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight; - } -} diff --git a/websocket/secure/static/js/vendor/jquery-2.2.3.min.js b/websocket/secure/static/js/vendor/jquery-2.2.3.min.js deleted file mode 100644 index b8c4187d..00000000 --- a/websocket/secure/static/js/vendor/jquery-2.2.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; -}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0!==g?g+"":g}function Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ca(b),i="border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Fa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Ba.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+Oa(b,c,e||(i?"border":"content"),f,h)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b, -e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m=n.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Hb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n}); diff --git a/websocket/secure/templates/client.html b/websocket/secure/templates/client.html deleted file mode 100644 index 437b8904..00000000 --- a/websocket/secure/templates/client.html +++ /dev/null @@ -1,24 +0,0 @@ -<html> - -<head> -<title>{{ .Title}}</title> -</head> - -<body> - <div id="messages" - style="border-width: 1px; border-style: solid; height: 400px; width: 375px;"> - - </div> - <input type="text" id="messageTxt" /> - <button type="button" id="sendBtn">Send</button> - <script type="text/javascript"> - var HOST = {{.Host}} - </script> - <script src="/js/vendor/jquery-2.2.3.min.js"></script> - <!-- This is auto-serving by the iris, you don't need to have this file in your disk--> - <script src="/iris-ws.js"></script> - <!-- --> - <script src="/js/chat.js"></script> -</body> - -</html> diff --git a/websocket/socketio/asset/index.html b/websocket/socketio/asset/index.html new file mode 100644 index 00000000..6c839ab8 --- /dev/null +++ b/websocket/socketio/asset/index.html @@ -0,0 +1,80 @@ +<!doctype html> +<html> + +<head> + <title>Socket.IO chat</title> + <style> + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font: 13px Helvetica, Arial; + } + + form { + background: #000; + padding: 3px; + position: fixed; + bottom: 0; + width: 100%; + } + + form input { + border: 0; + padding: 10px; + width: 90%; + margin-right: .5%; + } + + form button { + width: 9%; + background: rgb(130, 224, 255); + border: none; + padding: 10px; + } + + #messages { + list-style-type: none; + margin: 0; + padding: 0; + } + + #messages li { + padding: 5px 10px; + } + + #messages li:nth-child(odd) { + background: #eee; + } + </style> +</head> + +<body> + <ul id="messages"></ul> + <form action=""> + <input id="m" autocomplete="off" /><button>Send</button> + </form> + <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> + <script src="https://code.jquery.com/jquery-1.11.1.js"></script> + <script> + var socket = io(); + // socket.emit('msg', 'hello'); + var s2 = io("/chat"); + socket.on('reply', function (msg) { + $('#messages').append($('<li>').text(msg)); + }); + $('form').submit(function () { + s2.emit('msg', $('#m').val(), function (data) { + $('#messages').append($('<li>').text('ACK CALLBACK: ' + data)); + }); + socket.emit('notice', $('#m').val()); + $('#m').val(''); + return false; + }); + </script> +</body> + +</html> \ No newline at end of file diff --git a/websocket/socketio/go.mod b/websocket/socketio/go.mod new file mode 100644 index 00000000..316064d6 --- /dev/null +++ b/websocket/socketio/go.mod @@ -0,0 +1,57 @@ +module github.com/kataras/iris/_examples/websocket/socketio + +go 1.22 + +require ( + github.com/googollee/go-socket.io v1.7.0 + github.com/kataras/iris/v12 v12.2.11 +) + +require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/gofrs/uuid v4.0.0+incompatible // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 // indirect + github.com/gomodule/redigo v1.8.4 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/kataras/blocks v0.0.8 // indirect + github.com/kataras/golog v0.1.11 // indirect + github.com/kataras/pio v0.0.13 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.20.19 // indirect + github.com/tdewolff/parse/v2 v2.7.12 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/websocket/socketio/go.sum b/websocket/socketio/go.sum new file mode 100644 index 00000000..d67b67a7 --- /dev/null +++ b/websocket/socketio/go.sum @@ -0,0 +1,188 @@ +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= +github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/gomodule/redigo v1.8.4 h1:Z5JUg94HMTR1XpwBaSH4vq3+PNSIykBLxMdglbw10gg= +github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googollee/go-socket.io v1.7.0 h1:ODcQSAvVIPvKozXtUGuJDV3pLwdpBLDs1Uoq/QHIlY8= +github.com/googollee/go-socket.io v1.7.0/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go= +github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE= +github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM= +github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg= +github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20= +github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A= +github.com/kataras/iris/v12 v12.2.11 h1:sGgo43rMPfzDft8rjVhPs6L3qDJy3TbBrMD/zGL1pzk= +github.com/kataras/iris/v12 v12.2.11/go.mod h1:uMAeX8OqG9vqdhyrIPv8Lajo/wXTtAF43wchP9WHt2w= +github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM= +github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM= +github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tdewolff/minify/v2 v2.20.19 h1:tX0SR0LUrIqGoLjXnkIzRSIbKJ7PaNnSENLD4CyH6Xo= +github.com/tdewolff/minify/v2 v2.20.19/go.mod h1:ulkFoeAVWMLEyjuDz1ZIWOA31g5aWOawCFRp9R/MudM= +github.com/tdewolff/parse/v2 v2.7.12 h1:tgavkHc2ZDEQVKy1oWxwIyh5bP4F5fEh/JmBwPP/3LQ= +github.com/tdewolff/parse/v2 v2.7.12/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA= +github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo= +github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/websocket/socketio/main.go b/websocket/socketio/main.go new file mode 100644 index 00000000..dae68a15 --- /dev/null +++ b/websocket/socketio/main.go @@ -0,0 +1,53 @@ +// Package main runs a go-socket.io based websocket server. +// An Iris compatible clone of: https://github.com/googollee/go-socket.io#example, +// use of `iris.FromStd` to convert its handler. +package main + +import ( + "fmt" + + socketio "github.com/googollee/go-socket.io" + "github.com/kataras/iris/v12" +) + +func main() { + app := iris.New() + server := socketio.NewServer(nil) + server.OnConnect("/", func(s socketio.Conn) error { + s.SetContext("") + fmt.Println("connected:", s.ID()) + return nil + }) + server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { + fmt.Println("notice:", msg) + s.Emit("reply", "have "+msg) + }) + server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { + s.SetContext(msg) + return "recv " + msg + }) + server.OnEvent("/", "bye", func(s socketio.Conn) string { + last := s.Context().(string) + s.Emit("bye", last) + s.Close() + return last + }) + server.OnError("/", func(s socketio.Conn, e error) { + fmt.Println("meet error:", e) + }) + server.OnDisconnect("/", func(s socketio.Conn, reason string) { + fmt.Println("closed", reason) + }) + go server.Serve() + defer server.Close() + + app.HandleMany("GET POST", "/socket.io/{any:path}", iris.FromStd(server)) + app.HandleDir("/", iris.Dir("./asset")) + + app.Listen(":8000", iris.WithoutPathCorrection) +} + +/* +If you want to enable CORS in your websocket handler, +please follow this post: https://github.com/googollee/go-socket.io/issues/242 +*/ diff --git a/websocket/third-party-socketio/main.go b/websocket/third-party-socketio/main.go deleted file mode 100644 index e9ea5b8f..00000000 --- a/websocket/third-party-socketio/main.go +++ /dev/null @@ -1,44 +0,0 @@ -package main - -import ( - "github.com/kataras/iris" - - "github.com/googollee/go-socket.io" -) - -/* - go get -u github.com/googollee/go-socket.io -*/ - -func main() { - app := iris.New() - server, err := socketio.NewServer(nil) - if err != nil { - app.Logger().Fatal(err) - } - - server.On("connection", func(so socketio.Socket) { - app.Logger().Infof("on connection") - so.Join("chat") - so.On("chat message", func(msg string) { - app.Logger().Infof("emit: %v", so.Emit("chat message", msg)) - so.BroadcastTo("chat", "chat message", msg) - }) - so.On("disconnection", func() { - app.Logger().Infof("on disconnect") - }) - }) - - server.On("error", func(so socketio.Socket, err error) { - app.Logger().Errorf("error: %v", err) - }) - - // serve the socket.io endpoint. - app.Any("/socket.io/{p:path}", iris.FromStd(server)) - - // serve the index.html and the javascript libraries at - // http://localhost:8080 - app.StaticWeb("/", "./public") - - app.Run(iris.Addr("localhost:8080")) -} diff --git a/websocket/third-party-socketio/public/index.html b/websocket/third-party-socketio/public/index.html deleted file mode 100644 index 566ad06f..00000000 --- a/websocket/third-party-socketio/public/index.html +++ /dev/null @@ -1,38 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Socket.IO chat</title> - <style> - * { margin: 0; padding: 0; box-sizing: border-box; } - body { font: 13px Helvetica, Arial; } - form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } - form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; } - form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } - #messages { list-style-type: none; margin: 0; padding: 0; } - #messages li { padding: 5px 10px; } - #messages li:nth-child(odd) { background: #eee; } - </style> - </head> - <body> - <ul id="messages"></ul> - <form action=""> - <input id="m" autocomplete="off" /><button>Send</button> - </form> - <script src="/socket.io-1.3.7.js"></script> - <script src="/jquery-1.11.1.js"></script> - <script> - var socket = io(); - $('form').submit(function(){ - socket.emit('chat message with ack', $('#m').val(), function(data){ - $('#messages').append($('<li>').text('ACK CALLBACK: ' + data)); - }); - socket.emit('chat message', $('#m').val()); - $('#m').val(''); - return false; - }); - socket.on('chat message', function(msg){ - $('#messages').append($('<li>').text(msg)); - }); - </script> - </body> -</html> \ No newline at end of file diff --git a/websocket/third-party-socketio/public/jquery-1.11.1.js b/websocket/third-party-socketio/public/jquery-1.11.1.js deleted file mode 100644 index 176d3850..00000000 --- a/websocket/third-party-socketio/public/jquery-1.11.1.js +++ /dev/null @@ -1,10309 +0,0 @@ -/*! - * jQuery JavaScript Library v1.11.1 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-05-01T17:42Z - */ - -(function (global, factory) { - - if (typeof module === "object" && typeof module.exports === "object") { - // For CommonJS and CommonJS-like environments where a proper window is present, - // execute the factory and get jQuery - // For environments that do not inherently posses a window with a document - // (such as Node.js), expose a jQuery-making factory as module.exports - // This accentuates the need for the creation of a real window - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info - module.exports = global.document ? - factory(global, true) : - function (w) { - if (!w.document) { - throw new Error("jQuery requires a window with a document"); - } - return factory(w); - }; - } else { - factory(global); - } - - // Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function (window, noGlobal) { - - // Can't do this because several apps including ASP.NET trace - // the stack via arguments.caller.callee and Firefox dies if - // you try to trace through "use strict" call chains. (#13335) - // Support: Firefox 18+ - // - - var deletedIds = []; - - var slice = deletedIds.slice; - - var concat = deletedIds.concat; - - var push = deletedIds.push; - - var indexOf = deletedIds.indexOf; - - var class2type = {}; - - var toString = class2type.toString; - - var hasOwn = class2type.hasOwnProperty; - - var support = {}; - - - - var - version = "1.11.1", - - // Define a local copy of jQuery - jQuery = function (selector, context) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init(selector, context); - }, - - // Support: Android<4.1, IE<9 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function (all, letter) { - return letter.toUpperCase(); - }; - - jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function () { - return slice.call(this); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function (num) { - return num != null ? - - // Return just the one element from the set - (num < 0 ? this[num + this.length] : this[num]) : - - // Return all the elements in a clean array - slice.call(this); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function (elems) { - - // Build a new jQuery matched element set - var ret = jQuery.merge(this.constructor(), elems); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function (callback, args) { - return jQuery.each(this, callback, args); - }, - - map: function (callback) { - return this.pushStack(jQuery.map(this, function (elem, i) { - return callback.call(elem, i, elem); - })); - }, - - slice: function () { - return this.pushStack(slice.apply(this, arguments)); - }, - - first: function () { - return this.eq(0); - }, - - last: function () { - return this.eq(-1); - }, - - eq: function (i) { - var len = this.length, - j = +i + (i < 0 ? len : 0); - return this.pushStack(j >= 0 && j < len ? [this[j]] : []); - }, - - end: function () { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: deletedIds.sort, - splice: deletedIds.splice - }; - - jQuery.extend = jQuery.fn.extend = function () { - var src, copyIsArray, copy, name, options, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if (typeof target === "boolean") { - deep = target; - - // skip the boolean and the target - target = arguments[i] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if (typeof target !== "object" && !jQuery.isFunction(target)) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if (i === length) { - target = this; - i--; - } - - for (; i < length; i++) { - // Only deal with non-null/undefined values - if ((options = arguments[i]) != null) { - // Extend the base object - for (name in options) { - src = target[name]; - copy = options[name]; - - // Prevent never-ending loop - if (target === copy) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[name] = jQuery.extend(deep, clone, copy); - - // Don't bring in undefined values - } else if (copy !== undefined) { - target[name] = copy; - } - } - } - } - - // Return the modified object - return target; - }; - - jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + (version + Math.random()).replace(/\D/g, ""), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function (msg) { - throw new Error(msg); - }, - - noop: function () { }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function (obj) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function (obj) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function (obj) { - /* jshint eqeqeq: false */ - return obj != null && obj == obj.window; - }, - - isNumeric: function (obj) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - return !jQuery.isArray(obj) && obj - parseFloat(obj) >= 0; - }, - - isEmptyObject: function (obj) { - var name; - for (name in obj) { - return false; - } - return true; - }, - - isPlainObject: function (obj) { - var key; - - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if (!obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)) { - return false; - } - - try { - // Not own constructor property must be Object - if (obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { - return false; - } - } catch (e) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if (support.ownLast) { - for (key in obj) { - return hasOwn.call(obj, key); - } - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for (key in obj) { } - - return key === undefined || hasOwn.call(obj, key); - }, - - type: function (obj) { - if (obj == null) { - return obj + ""; - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[toString.call(obj)] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function (data) { - if (data && jQuery.trim(data)) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - (window.execScript || function (data) { - window["eval"].call(window, data); - })(data); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function (string) { - return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase); - }, - - nodeName: function (elem, name) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function (obj, callback, args) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike(obj); - - if (args) { - if (isArray) { - for (; i < length; i++) { - value = callback.apply(obj[i], args); - - if (value === false) { - break; - } - } - } else { - for (i in obj) { - value = callback.apply(obj[i], args); - - if (value === false) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if (isArray) { - for (; i < length; i++) { - value = callback.call(obj[i], i, obj[i]); - - if (value === false) { - break; - } - } - } else { - for (i in obj) { - value = callback.call(obj[i], i, obj[i]); - - if (value === false) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1, IE<9 - trim: function (text) { - return text == null ? - "" : - (text + "").replace(rtrim, ""); - }, - - // results is for internal usage only - makeArray: function (arr, results) { - var ret = results || []; - - if (arr != null) { - if (isArraylike(Object(arr))) { - jQuery.merge(ret, - typeof arr === "string" ? - [arr] : arr - ); - } else { - push.call(ret, arr); - } - } - - return ret; - }, - - inArray: function (elem, arr, i) { - var len; - - if (arr) { - if (indexOf) { - return indexOf.call(arr, elem, i); - } - - len = arr.length; - i = i ? i < 0 ? Math.max(0, len + i) : i : 0; - - for (; i < len; i++) { - // Skip accessing in sparse arrays - if (i in arr && arr[i] === elem) { - return i; - } - } - } - - return -1; - }, - - merge: function (first, second) { - var len = +second.length, - j = 0, - i = first.length; - - while (j < len) { - first[i++] = second[j++]; - } - - // Support: IE<9 - // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) - if (len !== len) { - while (second[j] !== undefined) { - first[i++] = second[j++]; - } - } - - first.length = i; - - return first; - }, - - grep: function (elems, callback, invert) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for (; i < length; i++) { - callbackInverse = !callback(elems[i], i); - if (callbackInverse !== callbackExpect) { - matches.push(elems[i]); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function (elems, callback, arg) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike(elems), - ret = []; - - // Go through the array, translating each of the items to their new values - if (isArray) { - for (; i < length; i++) { - value = callback(elems[i], i, arg); - - if (value != null) { - ret.push(value); - } - } - - // Go through every key on the object, - } else { - for (i in elems) { - value = callback(elems[i], i, arg); - - if (value != null) { - ret.push(value); - } - } - } - - // Flatten any nested arrays - return concat.apply([], ret); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function (fn, context) { - var args, proxy, tmp; - - if (typeof context === "string") { - tmp = fn[context]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if (!jQuery.isFunction(fn)) { - return undefined; - } - - // Simulated bind - args = slice.call(arguments, 2); - proxy = function () { - return fn.apply(context || this, args.concat(slice.call(arguments))); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: function () { - return +(new Date()); - }, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support - }); - - // Populate the class2type map - jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (i, name) { - class2type["[object " + name + "]"] = name.toLowerCase(); - }); - - function isArraylike(obj) { - var length = obj.length, - type = jQuery.type(obj); - - if (type === "function" || jQuery.isWindow(obj)) { - return false; - } - - if (obj.nodeType === 1 && length) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && (length - 1) in obj; - } - var Sizzle = - /*! - * Sizzle CSS Selector Engine v1.10.19 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-04-18 - */ - (function (window) { - - var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function (a, b) { - if (a === b) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function (elem) { - var i = 0, - len = this.length; - for (; i < len; i++) { - if (this[i] === elem) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace("w", "w#"), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"), - - rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"), - rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), - - rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"), - - rpseudo = new RegExp(pseudos), - ridentifier = new RegExp("^" + identifier + "$"), - - matchExpr = { - "ID": new RegExp("^#(" + characterEncoding + ")"), - "CLASS": new RegExp("^\\.(" + characterEncoding + ")"), - "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"), - "ATTR": new RegExp("^" + attributes), - "PSEUDO": new RegExp("^" + pseudos), - "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i"), - "bool": new RegExp("^(?:" + booleans + ")$", "i"), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i") - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"), - funescape = function (_, escaped, escapedWhitespace) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode(high + 0x10000) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00); - }; - - // Optimize for push.apply( _, NodeList ) - try { - push.apply( - (arr = slice.call(preferredDoc.childNodes)), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[preferredDoc.childNodes.length].nodeType; - } catch (e) { - push = { - apply: arr.length ? - - // Leverage slice if possible - function (target, els) { - push_native.apply(target, slice.call(els)); - } : - - // Support: IE<9 - // Otherwise append directly - function (target, els) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ((target[j++] = els[i++])) { } - target.length = j - 1; - } - }; - } - - function Sizzle(selector, context, results, seed) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ((context ? context.ownerDocument || context : preferredDoc) !== document) { - setDocument(context); - } - - context = context || document; - results = results || []; - - if (!selector || typeof selector !== "string") { - return results; - } - - if ((nodeType = context.nodeType) !== 1 && nodeType !== 9) { - return []; - } - - if (documentIsHTML && !seed) { - - // Shortcuts - if ((match = rquickExpr.exec(selector))) { - // Speed-up: Sizzle("#ID") - if ((m = match[1])) { - if (nodeType === 9) { - elem = context.getElementById(m); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if (elem && elem.parentNode) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if (elem.id === m) { - results.push(elem); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && - contains(context, elem) && elem.id === m) { - results.push(elem); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if (match[2]) { - push.apply(results, context.getElementsByTagName(selector)); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) { - push.apply(results, context.getElementsByClassName(m)); - return results; - } - } - - // QSA path - if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if (nodeType === 1 && context.nodeName.toLowerCase() !== "object") { - groups = tokenize(selector); - - if ((old = context.getAttribute("id"))) { - nid = old.replace(rescape, "\\$&"); - } else { - context.setAttribute("id", nid); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while (i--) { - groups[i] = nid + toSelector(groups[i]); - } - newContext = rsibling.test(selector) && testContext(context.parentNode) || context; - newSelector = groups.join(","); - } - - if (newSelector) { - try { - push.apply(results, - newContext.querySelectorAll(newSelector) - ); - return results; - } catch (qsaError) { - } finally { - if (!old) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select(selector.replace(rtrim, "$1"), context, results, seed); - } - - /** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ - function createCache() { - var keys = []; - - function cache(key, value) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if (keys.push(key + " ") > Expr.cacheLength) { - // Only keep the most recent entries - delete cache[keys.shift()]; - } - return (cache[key + " "] = value); - } - return cache; - } - - /** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ - function markFunction(fn) { - fn[expando] = true; - return fn; - } - - /** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ - function assert(fn) { - var div = document.createElement("div"); - - try { - return !!fn(div); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if (div.parentNode) { - div.parentNode.removeChild(div); - } - // release memory in IE - div = null; - } - } - - /** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ - function addHandle(attrs, handler) { - var arr = attrs.split("|"), - i = attrs.length; - - while (i--) { - Expr.attrHandle[arr[i]] = handler; - } - } - - /** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ - function siblingCheck(a, b) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - (~b.sourceIndex || MAX_NEGATIVE) - - (~a.sourceIndex || MAX_NEGATIVE); - - // Use IE sourceIndex if available on both nodes - if (diff) { - return diff; - } - - // Check if b follows a - if (cur) { - while ((cur = cur.nextSibling)) { - if (cur === b) { - return -1; - } - } - } - - return a ? 1 : -1; - } - - /** - * Returns a function to use in pseudos for input types - * @param {String} type - */ - function createInputPseudo(type) { - return function (elem) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ - function createButtonPseudo(type) { - return function (elem) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; - } - - /** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ - function createPositionalPseudo(fn) { - return markFunction(function (argument) { - argument = +argument; - return markFunction(function (seed, matches) { - var j, - matchIndexes = fn([], seed.length, argument), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while (i--) { - if (seed[(j = matchIndexes[i])]) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); - } - - /** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ - function testContext(context) { - return context && typeof context.getElementsByTagName !== strundefined && context; - } - - // Expose support vars for convenience - support = Sizzle.support = {}; - - /** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ - isXML = Sizzle.isXML = function (elem) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; - }; - - /** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ - setDocument = Sizzle.setDocument = function (node) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if (doc === document || doc.nodeType !== 9 || !doc.documentElement) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML(doc); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if (parent && parent !== parent.top) { - // IE11 does not have attachEvent, so all must suffer - if (parent.addEventListener) { - parent.addEventListener("unload", function () { - setDocument(); - }, false); - } else if (parent.attachEvent) { - parent.attachEvent("onunload", function () { - setDocument(); - }); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function (div) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function (div) { - div.appendChild(doc.createComment("")); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test(doc.getElementsByClassName) && assert(function (div) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function (div) { - docElem.appendChild(div).id = expando; - return !doc.getElementsByName || !doc.getElementsByName(expando).length; - }); - - // ID find and filter - if (support.getById) { - Expr.find["ID"] = function (id, context) { - if (typeof context.getElementById !== strundefined && documentIsHTML) { - var m = context.getElementById(id); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }; - Expr.filter["ID"] = function (id) { - var attrId = id.replace(runescape, funescape); - return function (elem) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function (id) { - var attrId = id.replace(runescape, funescape); - return function (elem) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function (tag, context) { - if (typeof context.getElementsByTagName !== strundefined) { - return context.getElementsByTagName(tag); - } - } : - function (tag, context) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName(tag); - - // Filter out possible comments - if (tag === "*") { - while ((elem = results[i++])) { - if (elem.nodeType === 1) { - tmp.push(elem); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function (className, context) { - if (typeof context.getElementsByClassName !== strundefined && documentIsHTML) { - return context.getElementsByClassName(className); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ((support.qsa = rnative.test(doc.querySelectorAll))) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function (div) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if (div.querySelectorAll("[msallowclip^='']").length) { - rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")"); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if (!div.querySelectorAll("[selected]").length) { - rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")"); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if (!div.querySelectorAll(":checked").length) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function (div) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute("type", "hidden"); - div.appendChild(input).setAttribute("name", "D"); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if (div.querySelectorAll("[name=d]").length) { - rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?="); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if (!div.querySelectorAll(":enabled").length) { - rbuggyQSA.push(":enabled", ":disabled"); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ((support.matchesSelector = rnative.test((matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector)))) { - - assert(function (div) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call(div, "div"); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call(div, "[s!='']:x"); - rbuggyMatches.push("!=", pseudos); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|")); - rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|")); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test(docElem.compareDocumentPosition); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test(docElem.contains) ? - function (a, b) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!(bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains(bup) : - a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16 - )); - } : - function (a, b) { - if (b) { - while ((b = b.parentNode)) { - if (b === a) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function (a, b) { - - // Flag for duplicate removal - if (a === b) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if (compare) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? - a.compareDocumentPosition(b) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if (compare & 1 || - (!support.sortDetached && b.compareDocumentPosition(a) === compare)) { - - // Choose the first element that is related to our preferred document - if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) { - return -1; - } - if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) { - return 1; - } - - // Maintain original order - return sortInput ? - (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function (a, b) { - // Exit early if the nodes are identical - if (a === b) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [a], - bp = [b]; - - // Parentless nodes are either documents or disconnected - if (!aup || !bup) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - (indexOf.call(sortInput, a) - indexOf.call(sortInput, b)) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if (aup === bup) { - return siblingCheck(a, b); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ((cur = cur.parentNode)) { - ap.unshift(cur); - } - cur = b; - while ((cur = cur.parentNode)) { - bp.unshift(cur); - } - - // Walk down the tree looking for a discrepancy - while (ap[i] === bp[i]) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck(ap[i], bp[i]) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; - }; - - Sizzle.matches = function (expr, elements) { - return Sizzle(expr, null, null, elements); - }; - - Sizzle.matchesSelector = function (elem, expr) { - // Set document vars if needed - if ((elem.ownerDocument || elem) !== document) { - setDocument(elem); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace(rattributeQuotes, "='$1']"); - - if (support.matchesSelector && documentIsHTML && - (!rbuggyMatches || !rbuggyMatches.test(expr)) && - (!rbuggyQSA || !rbuggyQSA.test(expr))) { - - try { - var ret = matches.call(elem, expr); - - // IE 9's matchesSelector returns false on disconnected nodes - if (ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11) { - return ret; - } - } catch (e) { } - } - - return Sizzle(expr, document, null, [elem]).length > 0; - }; - - Sizzle.contains = function (context, elem) { - // Set document vars if needed - if ((context.ownerDocument || context) !== document) { - setDocument(context); - } - return contains(context, elem); - }; - - Sizzle.attr = function (elem, name) { - // Set document vars if needed - if ((elem.ownerDocument || elem) !== document) { - setDocument(elem); - } - - var fn = Expr.attrHandle[name.toLowerCase()], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? - fn(elem, name, !documentIsHTML) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute(name) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; - }; - - Sizzle.error = function (msg) { - throw new Error("Syntax error, unrecognized expression: " + msg); - }; - - /** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ - Sizzle.uniqueSort = function (results) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice(0); - results.sort(sortOrder); - - if (hasDuplicate) { - while ((elem = results[i++])) { - if (elem === results[i]) { - j = duplicates.push(i); - } - } - while (j--) { - results.splice(duplicates[j], 1); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; - }; - - /** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ - getText = Sizzle.getText = function (elem) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if (!nodeType) { - // If no nodeType, this is expected to be an array - while ((node = elem[i++])) { - // Do not traverse comment nodes - ret += getText(node); - } - } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if (typeof elem.textContent === "string") { - return elem.textContent; - } else { - // Traverse its children - for (elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText(elem); - } - } - } else if (nodeType === 3 || nodeType === 4) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; - }; - - Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function (match) { - match[1] = match[1].replace(runescape, funescape); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape); - - if (match[2] === "~=") { - match[3] = " " + match[3] + " "; - } - - return match.slice(0, 4); - }, - - "CHILD": function (match) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if (match[1].slice(0, 3) === "nth") { - // nth-* requires argument - if (!match[3]) { - Sizzle.error(match[0]); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd")); - match[5] = +((match[7] + match[8]) || match[3] === "odd"); - - // other types prohibit arguments - } else if (match[3]) { - Sizzle.error(match[0]); - } - - return match; - }, - - "PSEUDO": function (match) { - var excess, - unquoted = !match[6] && match[2]; - - if (matchExpr["CHILD"].test(match[0])) { - return null; - } - - // Accept quoted arguments as-is - if (match[3]) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if (unquoted && rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize(unquoted, true)) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) { - - // excess is a negative index - match[0] = match[0].slice(0, excess); - match[2] = unquoted.slice(0, excess); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice(0, 3); - } - }, - - filter: { - - "TAG": function (nodeNameSelector) { - var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase(); - return nodeNameSelector === "*" ? - function () { return true; } : - function (elem) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function (className) { - var pattern = classCache[className + " "]; - - return pattern || - (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && - classCache(className, function (elem) { - return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || ""); - }); - }, - - "ATTR": function (name, operator, check) { - return function (elem) { - var result = Sizzle.attr(elem, name); - - if (result == null) { - return operator === "!="; - } - if (!operator) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf(check) === 0 : - operator === "*=" ? check && result.indexOf(check) > -1 : - operator === "$=" ? check && result.slice(-check.length) === check : - operator === "~=" ? (" " + result + " ").indexOf(check) > -1 : - operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : - false; - }; - }, - - "CHILD": function (type, what, argument, first, last) { - var simple = type.slice(0, 3) !== "nth", - forward = type.slice(-4) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function (elem) { - return !!elem.parentNode; - } : - - function (elem, context, xml) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if (parent) { - - // :(first|last|only)-(child|of-type) - if (simple) { - while (dir) { - node = elem; - while ((node = node[dir])) { - if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [forward ? parent.firstChild : parent.lastChild]; - - // non-xml :nth-child(...) stores cache data on `parent` - if (forward && useCache) { - // Seek `elem` from a previously-cached index - outerCache = parent[expando] || (parent[expando] = {}); - cache = outerCache[type] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[nodeIndex]; - - while ((node = ++nodeIndex && node && node[dir] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop())) { - - // When found, cache indexes on `parent` and break - if (node.nodeType === 1 && ++diff && node === elem) { - outerCache[type] = [dirruns, nodeIndex, diff]; - break; - } - } - - // Use previously-cached element index if available - } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ((node = ++nodeIndex && node && node[dir] || - (diff = nodeIndex = 0) || start.pop())) { - - if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) { - // Cache the index of each encountered element - if (useCache) { - (node[expando] || (node[expando] = {}))[type] = [dirruns, diff]; - } - - if (node === elem) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || (diff % first === 0 && diff / first >= 0); - } - }; - }, - - "PSEUDO": function (pseudo, argument) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || - Sizzle.error("unsupported pseudo: " + pseudo); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if (fn[expando]) { - return fn(argument); - } - - // But maintain support for old signatures - if (fn.length > 1) { - args = [pseudo, pseudo, "", argument]; - return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? - markFunction(function (seed, matches) { - var idx, - matched = fn(seed, argument), - i = matched.length; - while (i--) { - idx = indexOf.call(seed, matched[i]); - seed[idx] = !(matches[idx] = matched[i]); - } - }) : - function (elem) { - return fn(elem, 0, args); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function (selector) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile(selector.replace(rtrim, "$1")); - - return matcher[expando] ? - markFunction(function (seed, matches, context, xml) { - var elem, - unmatched = matcher(seed, null, xml, []), - i = seed.length; - - // Match elements unmatched by `matcher` - while (i--) { - if ((elem = unmatched[i])) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function (elem, context, xml) { - input[0] = elem; - matcher(input, null, xml, results); - return !results.pop(); - }; - }), - - "has": markFunction(function (selector) { - return function (elem) { - return Sizzle(selector, elem).length > 0; - }; - }), - - "contains": markFunction(function (text) { - return function (elem) { - return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction(function (lang) { - // lang value must be a valid identifier - if (!ridentifier.test(lang || "")) { - Sizzle.error("unsupported lang: " + lang); - } - lang = lang.replace(runescape, funescape).toLowerCase(); - return function (elem) { - var elemLang; - do { - if ((elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang"))) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf(lang + "-") === 0; - } - } while ((elem = elem.parentNode) && elem.nodeType === 1); - return false; - }; - }), - - // Miscellaneous - "target": function (elem) { - var hash = window.location && window.location.hash; - return hash && hash.slice(1) === elem.id; - }, - - "root": function (elem) { - return elem === docElem; - }, - - "focus": function (elem) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function (elem) { - return elem.disabled === false; - }, - - "disabled": function (elem) { - return elem.disabled === true; - }, - - "checked": function (elem) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function (elem) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if (elem.parentNode) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function (elem) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for (elem = elem.firstChild; elem; elem = elem.nextSibling) { - if (elem.nodeType < 6) { - return false; - } - } - return true; - }, - - "parent": function (elem) { - return !Expr.pseudos["empty"](elem); - }, - - // Element/input types - "header": function (elem) { - return rheader.test(elem.nodeName); - }, - - "input": function (elem) { - return rinputs.test(elem.nodeName); - }, - - "button": function (elem) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function (elem) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text"); - }, - - // Position-in-collection - "first": createPositionalPseudo(function () { - return [0]; - }), - - "last": createPositionalPseudo(function (matchIndexes, length) { - return [length - 1]; - }), - - "eq": createPositionalPseudo(function (matchIndexes, length, argument) { - return [argument < 0 ? argument + length : argument]; - }), - - "even": createPositionalPseudo(function (matchIndexes, length) { - var i = 0; - for (; i < length; i += 2) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function (matchIndexes, length) { - var i = 1; - for (; i < length; i += 2) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function (matchIndexes, length, argument) { - var i = argument < 0 ? argument + length : argument; - for (; --i >= 0;) { - matchIndexes.push(i); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function (matchIndexes, length, argument) { - var i = argument < 0 ? argument + length : argument; - for (; ++i < length;) { - matchIndexes.push(i); - } - return matchIndexes; - }) - } - }; - - Expr.pseudos["nth"] = Expr.pseudos["eq"]; - - // Add button/input type pseudos - for (i in { radio: true, checkbox: true, file: true, password: true, image: true }) { - Expr.pseudos[i] = createInputPseudo(i); - } - for (i in { submit: true, reset: true }) { - Expr.pseudos[i] = createButtonPseudo(i); - } - - // Easy API for creating new setFilters - function setFilters() { } - setFilters.prototype = Expr.filters = Expr.pseudos; - Expr.setFilters = new setFilters(); - - tokenize = Sizzle.tokenize = function (selector, parseOnly) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[selector + " "]; - - if (cached) { - return parseOnly ? 0 : cached.slice(0); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while (soFar) { - - // Comma and first run - if (!matched || (match = rcomma.exec(soFar))) { - if (match) { - // Don't consume trailing commas as valid - soFar = soFar.slice(match[0].length) || soFar; - } - groups.push((tokens = [])); - } - - matched = false; - - // Combinators - if ((match = rcombinators.exec(soFar))) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace(rtrim, " ") - }); - soFar = soFar.slice(matched.length); - } - - // Filters - for (type in Expr.filter) { - if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || - (match = preFilters[type](match)))) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice(matched.length); - } - } - - if (!matched) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error(selector) : - // Cache the tokens - tokenCache(selector, groups).slice(0); - }; - - function toSelector(tokens) { - var i = 0, - len = tokens.length, - selector = ""; - for (; i < len; i++) { - selector += tokens[i].value; - } - return selector; - } - - function addCombinator(matcher, combinator, base) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function (elem, context, xml) { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - return matcher(elem, context, xml); - } - } - } : - - // Check against all ancestor/preceding elements - function (elem, context, xml) { - var oldCache, outerCache, - newCache = [dirruns, doneName]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if (xml) { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - if (matcher(elem, context, xml)) { - return true; - } - } - } - } else { - while ((elem = elem[dir])) { - if (elem.nodeType === 1 || checkNonElements) { - outerCache = elem[expando] || (elem[expando] = {}); - if ((oldCache = outerCache[dir]) && - oldCache[0] === dirruns && oldCache[1] === doneName) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[2] = oldCache[2]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[dir] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ((newCache[2] = matcher(elem, context, xml))) { - return true; - } - } - } - } - } - }; - } - - function elementMatcher(matchers) { - return matchers.length > 1 ? - function (elem, context, xml) { - var i = matchers.length; - while (i--) { - if (!matchers[i](elem, context, xml)) { - return false; - } - } - return true; - } : - matchers[0]; - } - - function multipleContexts(selector, contexts, results) { - var i = 0, - len = contexts.length; - for (; i < len; i++) { - Sizzle(selector, contexts[i], results); - } - return results; - } - - function condense(unmatched, map, filter, context, xml) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for (; i < len; i++) { - if ((elem = unmatched[i])) { - if (!filter || filter(elem, context, xml)) { - newUnmatched.push(elem); - if (mapped) { - map.push(i); - } - } - } - } - - return newUnmatched; - } - - function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) { - if (postFilter && !postFilter[expando]) { - postFilter = setMatcher(postFilter); - } - if (postFinder && !postFinder[expando]) { - postFinder = setMatcher(postFinder, postSelector); - } - return markFunction(function (seed, results, context, xml) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && (seed || !selector) ? - condense(elems, preMap, preFilter, context, xml) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || (seed ? preFilter : preexisting || postFilter) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if (matcher) { - matcher(matcherIn, matcherOut, context, xml); - } - - // Apply postFilter - if (postFilter) { - temp = condense(matcherOut, postMap); - postFilter(temp, [], context, xml); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while (i--) { - if ((elem = temp[i])) { - matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem); - } - } - } - - if (seed) { - if (postFinder || preFilter) { - if (postFinder) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while (i--) { - if ((elem = matcherOut[i])) { - // Restore matcherIn since elem is not yet a final match - temp.push((matcherIn[i] = elem)); - } - } - postFinder(null, (matcherOut = []), temp, xml); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while (i--) { - if ((elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call(seed, elem) : preMap[i]) > -1) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice(preexisting, matcherOut.length) : - matcherOut - ); - if (postFinder) { - postFinder(null, results, matcherOut, xml); - } else { - push.apply(results, matcherOut); - } - } - }); - } - - function matcherFromTokens(tokens) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[tokens[0].type], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator(function (elem) { - return elem === checkContext; - }, implicitRelative, true), - matchAnyContext = addCombinator(function (elem) { - return indexOf.call(checkContext, elem) > -1; - }, implicitRelative, true), - matchers = [function (elem, context, xml) { - return (!leadingRelative && (xml || context !== outermostContext)) || ( - (checkContext = context).nodeType ? - matchContext(elem, context, xml) : - matchAnyContext(elem, context, xml)); - }]; - - for (; i < len; i++) { - if ((matcher = Expr.relative[tokens[i].type])) { - matchers = [addCombinator(elementMatcher(matchers), matcher)]; - } else { - matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); - - // Return special upon seeing a positional matcher - if (matcher[expando]) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for (; j < len; j++) { - if (Expr.relative[tokens[j].type]) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher(matchers), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === " " ? "*" : "" }) - ).replace(rtrim, "$1"), - matcher, - i < j && matcherFromTokens(tokens.slice(i, j)), - j < len && matcherFromTokens((tokens = tokens.slice(j))), - j < len && toSelector(tokens) - ); - } - matchers.push(matcher); - } - } - - return elementMatcher(matchers); - } - - function matcherFromGroupMatchers(elementMatchers, setMatchers) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function (seed, context, xml, results, outermost) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]("*", outermost), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if (outermost) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id - for (; i !== len && (elem = elems[i]) != null; i++) { - if (byElement && elem) { - j = 0; - while ((matcher = elementMatchers[j++])) { - if (matcher(elem, context, xml)) { - results.push(elem); - break; - } - } - if (outermost) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if (bySet) { - // They will have gone through all possible matchers - if ((elem = !matcher && elem)) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if (seed) { - unmatched.push(elem); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if (bySet && i !== matchedCount) { - j = 0; - while ((matcher = setMatchers[j++])) { - matcher(unmatched, setMatched, context, xml); - } - - if (seed) { - // Reintegrate element matches to eliminate the need for sorting - if (matchedCount > 0) { - while (i--) { - if (!(unmatched[i] || setMatched[i])) { - setMatched[i] = pop.call(results); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense(setMatched); - } - - // Add matches to results - push.apply(results, setMatched); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if (outermost && !seed && setMatched.length > 0 && - (matchedCount + setMatchers.length) > 1) { - - Sizzle.uniqueSort(results); - } - } - - // Override manipulation of globals by nested matchers - if (outermost) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction(superMatcher) : - superMatcher; - } - - compile = Sizzle.compile = function (selector, match /* Internal Use Only */) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[selector + " "]; - - if (!cached) { - // Generate a function of recursive functions that can be used to check each element - if (!match) { - match = tokenize(selector); - } - i = match.length; - while (i--) { - cached = matcherFromTokens(match[i]); - if (cached[expando]) { - setMatchers.push(cached); - } else { - elementMatchers.push(cached); - } - } - - // Cache the compiled function - cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; - }; - - /** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ - select = Sizzle.select = function (selector, context, results, seed) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize((selector = compiled.selector || selector)); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if (match.length === 1) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice(0); - if (tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[tokens[1].type]) { - - context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0]; - if (!context) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if (compiled) { - context = context.parentNode; - } - - selector = selector.slice(tokens.shift().value.length); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length; - while (i--) { - token = tokens[i]; - - // Abort if we hit a combinator - if (Expr.relative[(type = token.type)]) { - break; - } - if ((find = Expr.find[type])) { - // Search, expanding context for leading sibling combinators - if ((seed = find( - token.matches[0].replace(runescape, funescape), - rsibling.test(tokens[0].type) && testContext(context.parentNode) || context - ))) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice(i, 1); - selector = seed.length && toSelector(tokens); - if (!selector) { - push.apply(results, seed); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - (compiled || compile(selector, match))( - seed, - context, - !documentIsHTML, - results, - rsibling.test(selector) && testContext(context.parentNode) || context - ); - return results; - }; - - // One-time assignments - - // Sort stability - support.sortStable = expando.split("").sort(sortOrder).join("") === expando; - - // Support: Chrome<14 - // Always assume duplicates if they aren't passed to the comparison function - support.detectDuplicates = !!hasDuplicate; - - // Initialize against the default document - setDocument(); - - // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) - // Detached nodes confoundingly follow *each other* - support.sortDetached = assert(function (div1) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition(document.createElement("div")) & 1; - }); - - // Support: IE<8 - // Prevent attribute/property "interpolation" - // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx - if (!assert(function (div) { - div.innerHTML = "<a href='#'></a>"; - return div.firstChild.getAttribute("href") === "#"; - })) { - addHandle("type|href|height|width", function (elem, name, isXML) { - if (!isXML) { - return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2); - } - }); - } - - // Support: IE<9 - // Use defaultValue in place of getAttribute("value") - if (!support.attributes || !assert(function (div) { - div.innerHTML = "<input/>"; - div.firstChild.setAttribute("value", ""); - return div.firstChild.getAttribute("value") === ""; - })) { - addHandle("value", function (elem, name, isXML) { - if (!isXML && elem.nodeName.toLowerCase() === "input") { - return elem.defaultValue; - } - }); - } - - // Support: IE<9 - // Use getAttributeNode to fetch booleans when getAttribute lies - if (!assert(function (div) { - return div.getAttribute("disabled") == null; - })) { - addHandle(booleans, function (elem, name, isXML) { - var val; - if (!isXML) { - return elem[name] === true ? name.toLowerCase() : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; - } - }); - } - - return Sizzle; - - })(window); - - - - jQuery.find = Sizzle; - jQuery.expr = Sizzle.selectors; - jQuery.expr[":"] = jQuery.expr.pseudos; - jQuery.unique = Sizzle.uniqueSort; - jQuery.text = Sizzle.getText; - jQuery.isXMLDoc = Sizzle.isXML; - jQuery.contains = Sizzle.contains; - - - - var rneedsContext = jQuery.expr.match.needsContext; - - var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - - var risSimple = /^.[^:#\[\.,]*$/; - - // Implement the identical functionality for filter and not - function winnow(elements, qualifier, not) { - if (jQuery.isFunction(qualifier)) { - return jQuery.grep(elements, function (elem, i) { - /* jshint -W018 */ - return !!qualifier.call(elem, i, elem) !== not; - }); - - } - - if (qualifier.nodeType) { - return jQuery.grep(elements, function (elem) { - return (elem === qualifier) !== not; - }); - - } - - if (typeof qualifier === "string") { - if (risSimple.test(qualifier)) { - return jQuery.filter(qualifier, elements, not); - } - - qualifier = jQuery.filter(qualifier, elements); - } - - return jQuery.grep(elements, function (elem) { - return (jQuery.inArray(elem, qualifier) >= 0) !== not; - }); - } - - jQuery.filter = function (expr, elems, not) { - var elem = elems[0]; - - if (not) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector(elem, expr) ? [elem] : [] : - jQuery.find.matches(expr, jQuery.grep(elems, function (elem) { - return elem.nodeType === 1; - })); - }; - - jQuery.fn.extend({ - find: function (selector) { - var i, - ret = [], - self = this, - len = self.length; - - if (typeof selector !== "string") { - return this.pushStack(jQuery(selector).filter(function () { - for (i = 0; i < len; i++) { - if (jQuery.contains(self[i], this)) { - return true; - } - } - })); - } - - for (i = 0; i < len; i++) { - jQuery.find(selector, self[i], ret); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function (selector) { - return this.pushStack(winnow(this, selector || [], false)); - }, - not: function (selector) { - return this.pushStack(winnow(this, selector || [], true)); - }, - is: function (selector) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test(selector) ? - jQuery(selector) : - selector || [], - false - ).length; - } - }); - - - // Initialize a jQuery object - - - // A central reference to the root jQuery(document) - var rootjQuery, - - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - // A simple way to check for HTML strings - // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function (selector, context) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if (!selector) { - return this; - } - - // Handle HTML strings - if (typeof selector === "string") { - if (selector.charAt(0) === "<" && selector.charAt(selector.length - 1) === ">" && selector.length >= 3) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [null, selector, null]; - - } else { - match = rquickExpr.exec(selector); - } - - // Match html or make sure no context is specified for #id - if (match && (match[1] || !context)) { - - // HANDLE: $(html) -> $(array) - if (match[1]) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge(this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - )); - - // HANDLE: $(html, props) - if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { - for (match in context) { - // Properties of context are called as methods if possible - if (jQuery.isFunction(this[match])) { - this[match](context[match]); - - // ...and otherwise set as attributes - } else { - this.attr(match, context[match]); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById(match[2]); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if (elem && elem.parentNode) { - // Handle the case where IE and Opera return items - // by name instead of ID - if (elem.id !== match[2]) { - return rootjQuery.find(selector); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if (!context || context.jquery) { - return (context || rootjQuery).find(selector); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor(context).find(selector); - } - - // HANDLE: $(DOMElement) - } else if (selector.nodeType) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if (jQuery.isFunction(selector)) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready(selector) : - // Execute immediately if ready is not present - selector(jQuery); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray(selector, this); - }; - - // Give the init function the jQuery prototype for later instantiation - init.prototype = jQuery.fn; - - // Initialize central reference - rootjQuery = jQuery(document); - - - var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - - jQuery.extend({ - dir: function (elem, dir, until) { - var matched = [], - cur = elem[dir]; - - while (cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery(cur).is(until))) { - if (cur.nodeType === 1) { - matched.push(cur); - } - cur = cur[dir]; - } - return matched; - }, - - sibling: function (n, elem) { - var r = []; - - for (; n; n = n.nextSibling) { - if (n.nodeType === 1 && n !== elem) { - r.push(n); - } - } - - return r; - } - }); - - jQuery.fn.extend({ - has: function (target) { - var i, - targets = jQuery(target, this), - len = targets.length; - - return this.filter(function () { - for (i = 0; i < len; i++) { - if (jQuery.contains(this, targets[i])) { - return true; - } - } - }); - }, - - closest: function (selectors, context) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test(selectors) || typeof selectors !== "string" ? - jQuery(selectors, context || this.context) : - 0; - - for (; i < l; i++) { - for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) { - // Always skip document fragments - if (cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors))) { - - matched.push(cur); - break; - } - } - } - - return this.pushStack(matched.length > 1 ? jQuery.unique(matched) : matched); - }, - - // Determine the position of an element within - // the matched set of elements - index: function (elem) { - - // No argument, return index in parent - if (!elem) { - return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1; - } - - // index in selector - if (typeof elem === "string") { - return jQuery.inArray(this[0], jQuery(elem)); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this); - }, - - add: function (selector, context) { - return this.pushStack( - jQuery.unique( - jQuery.merge(this.get(), jQuery(selector, context)) - ) - ); - }, - - addBack: function (selector) { - return this.add(selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } - }); - - function sibling(cur, dir) { - do { - cur = cur[dir]; - } while (cur && cur.nodeType !== 1); - - return cur; - } - - jQuery.each({ - parent: function (elem) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function (elem) { - return jQuery.dir(elem, "parentNode"); - }, - parentsUntil: function (elem, i, until) { - return jQuery.dir(elem, "parentNode", until); - }, - next: function (elem) { - return sibling(elem, "nextSibling"); - }, - prev: function (elem) { - return sibling(elem, "previousSibling"); - }, - nextAll: function (elem) { - return jQuery.dir(elem, "nextSibling"); - }, - prevAll: function (elem) { - return jQuery.dir(elem, "previousSibling"); - }, - nextUntil: function (elem, i, until) { - return jQuery.dir(elem, "nextSibling", until); - }, - prevUntil: function (elem, i, until) { - return jQuery.dir(elem, "previousSibling", until); - }, - siblings: function (elem) { - return jQuery.sibling((elem.parentNode || {}).firstChild, elem); - }, - children: function (elem) { - return jQuery.sibling(elem.firstChild); - }, - contents: function (elem) { - return jQuery.nodeName(elem, "iframe") ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge([], elem.childNodes); - } - }, function (name, fn) { - jQuery.fn[name] = function (until, selector) { - var ret = jQuery.map(this, fn, until); - - if (name.slice(-5) !== "Until") { - selector = until; - } - - if (selector && typeof selector === "string") { - ret = jQuery.filter(selector, ret); - } - - if (this.length > 1) { - // Remove duplicates - if (!guaranteedUnique[name]) { - ret = jQuery.unique(ret); - } - - // Reverse order for parents* and prev-derivatives - if (rparentsprev.test(name)) { - ret = ret.reverse(); - } - } - - return this.pushStack(ret); - }; - }); - var rnotwhite = (/\S+/g); - - - - // String to Object options format cache - var optionsCache = {}; - - // Convert String-formatted options into Object-formatted ones and store in cache - function createOptions(options) { - var object = optionsCache[options] = {}; - jQuery.each(options.match(rnotwhite) || [], function (_, flag) { - object[flag] = true; - }); - return object; - } - - /* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ - jQuery.Callbacks = function (options) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - (optionsCache[options] || createOptions(options)) : - jQuery.extend({}, options); - - var // Flag to know if list is currently firing - firing, - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // First callback to fire (used internally by add and fireWith) - firingStart, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function (data) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for (; list && firingIndex < firingLength; firingIndex++) { - if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if (list) { - if (stack) { - if (stack.length) { - fire(stack.shift()); - } - } else if (memory) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function () { - if (list) { - // First, we save the current length - var start = list.length; - (function add(args) { - jQuery.each(args, function (_, arg) { - var type = jQuery.type(arg); - if (type === "function") { - if (!options.unique || !self.has(arg)) { - list.push(arg); - } - } else if (arg && arg.length && type !== "string") { - // Inspect recursively - add(arg); - } - }); - })(arguments); - // Do we need to add the callbacks to the - // current firing batch? - if (firing) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if (memory) { - firingStart = start; - fire(memory); - } - } - return this; - }, - // Remove a callback from the list - remove: function () { - if (list) { - jQuery.each(arguments, function (_, arg) { - var index; - while ((index = jQuery.inArray(arg, list, index)) > -1) { - list.splice(index, 1); - // Handle firing indexes - if (firing) { - if (index <= firingLength) { - firingLength--; - } - if (index <= firingIndex) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function (fn) { - return fn ? jQuery.inArray(fn, list) > -1 : !!(list && list.length); - }, - // Remove all callbacks from the list - empty: function () { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function () { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function () { - return !list; - }, - // Lock the list in its current state - lock: function () { - stack = undefined; - if (!memory) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function () { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function (context, args) { - if (list && (!fired || stack)) { - args = args || []; - args = [context, args.slice ? args.slice() : args]; - if (firing) { - stack.push(args); - } else { - fire(args); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function () { - self.fireWith(this, arguments); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function () { - return !!fired; - } - }; - - return self; - }; - - - jQuery.extend({ - - Deferred: function (func) { - var tuples = [ - // action, add listener, listener list, final state - ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"], - ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"], - ["notify", "progress", jQuery.Callbacks("memory")] - ], - state = "pending", - promise = { - state: function () { - return state; - }, - always: function () { - deferred.done(arguments).fail(arguments); - return this; - }, - then: function ( /* fnDone, fnFail, fnProgress */) { - var fns = arguments; - return jQuery.Deferred(function (newDefer) { - jQuery.each(tuples, function (i, tuple) { - var fn = jQuery.isFunction(fns[i]) && fns[i]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[tuple[1]](function () { - var returned = fn && fn.apply(this, arguments); - if (returned && jQuery.isFunction(returned.promise)) { - returned.promise() - .done(newDefer.resolve) - .fail(newDefer.reject) - .progress(newDefer.notify); - } else { - newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function (obj) { - return obj != null ? jQuery.extend(obj, promise) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each(tuples, function (i, tuple) { - var list = tuple[2], - stateString = tuple[3]; - - // promise[ done | fail | progress ] = list.add - promise[tuple[1]] = list.add; - - // Handle state - if (stateString) { - list.add(function () { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[i ^ 1][2].disable, tuples[2][2].lock); - } - - // deferred[ resolve | reject | notify ] - deferred[tuple[0]] = function () { - deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments); - return this; - }; - deferred[tuple[0] + "With"] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise(deferred); - - // Call given func if any - if (func) { - func.call(deferred, deferred); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function (subordinate /* , ..., subordinateN */) { - var i = 0, - resolveValues = slice.call(arguments), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function (i, contexts, values) { - return function (value) { - contexts[i] = this; - values[i] = arguments.length > 1 ? slice.call(arguments) : value; - if (values === progressValues) { - deferred.notifyWith(contexts, values); - - } else if (!(--remaining)) { - deferred.resolveWith(contexts, values); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if (length > 1) { - progressValues = new Array(length); - progressContexts = new Array(length); - resolveContexts = new Array(length); - for (; i < length; i++) { - if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise)) { - resolveValues[i].promise() - .done(updateFunc(i, resolveContexts, resolveValues)) - .fail(deferred.reject) - .progress(updateFunc(i, progressContexts, progressValues)); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if (!remaining) { - deferred.resolveWith(resolveContexts, resolveValues); - } - - return deferred.promise(); - } - }); - - - // The deferred used on DOM ready - var readyList; - - jQuery.fn.ready = function (fn) { - // Add the callback - jQuery.ready.promise().done(fn); - - return this; - }; - - jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function (hold) { - if (hold) { - jQuery.readyWait++; - } else { - jQuery.ready(true); - } - }, - - // Handle when the DOM is ready - ready: function (wait) { - - // Abort if there are pending holds or we're already ready - if (wait === true ? --jQuery.readyWait : jQuery.isReady) { - return; - } - - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if (!document.body) { - return setTimeout(jQuery.ready); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if (wait !== true && --jQuery.readyWait > 0) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith(document, [jQuery]); - - // Trigger any bound ready events - if (jQuery.fn.triggerHandler) { - jQuery(document).triggerHandler("ready"); - jQuery(document).off("ready"); - } - } - }); - - /** - * Clean-up method for dom ready events - */ - function detach() { - if (document.addEventListener) { - document.removeEventListener("DOMContentLoaded", completed, false); - window.removeEventListener("load", completed, false); - - } else { - document.detachEvent("onreadystatechange", completed); - window.detachEvent("onload", completed); - } - } - - /** - * The ready event handler and self cleanup method - */ - function completed() { - // readyState === "complete" is good enough for us to call the dom ready in oldIE - if (document.addEventListener || event.type === "load" || document.readyState === "complete") { - detach(); - jQuery.ready(); - } - } - - jQuery.ready.promise = function (obj) { - if (!readyList) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if (document.readyState === "complete") { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout(jQuery.ready); - - // Standards-based browsers support DOMContentLoaded - } else if (document.addEventListener) { - // Use the handy event callback - document.addEventListener("DOMContentLoaded", completed, false); - - // A fallback to window.onload, that will always work - window.addEventListener("load", completed, false); - - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent("onreadystatechange", completed); - - // A fallback to window.onload, that will always work - window.attachEvent("onload", completed); - - // If IE and not a frame - // continually check to see if the document is ready - var top = false; - - try { - top = window.frameElement == null && document.documentElement; - } catch (e) { } - - if (top && top.doScroll) { - (function doScrollCheck() { - if (!jQuery.isReady) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch (e) { - return setTimeout(doScrollCheck, 50); - } - - // detach all dom ready events - detach(); - - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise(obj); - }; - - - var strundefined = typeof undefined; - - - - // Support: IE<9 - // Iteration over object's inherited properties before its own - var i; - for (i in jQuery(support)) { - break; - } - support.ownLast = i !== "0"; - - // Note: most support tests are defined in their respective modules. - // false until the test is run - support.inlineBlockNeedsLayout = false; - - // Execute ASAP in case we need to set body.style.zoom - jQuery(function () { - // Minified: var a,b,c,d - var val, div, body, container; - - body = document.getElementsByTagName("body")[0]; - if (!body || !body.style) { - // Return for frameset docs that don't have a body - return; - } - - // Setup - div = document.createElement("div"); - container = document.createElement("div"); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild(container).appendChild(div); - - if (typeof div.style.zoom !== strundefined) { - // Support: IE<8 - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; - - support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; - if (val) { - // Prevent IE 6 from affecting layout for positioned elements #11048 - // Prevent IE from shrinking the body in IE 7 mode #12869 - // Support: IE<8 - body.style.zoom = 1; - } - } - - body.removeChild(container); - }); - - - - - (function () { - var div = document.createElement("div"); - - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch (e) { - support.deleteExpando = false; - } - } - - // Null elements to avoid leaks in IE. - div = null; - })(); - - - /** - * Determines whether an object can have data - */ - jQuery.acceptData = function (elem) { - var noData = jQuery.noData[(elem.nodeName + " ").toLowerCase()], - nodeType = +elem.nodeType || 1; - - // Do not set data on non-element DOM nodes because it will not be cleared (#8335). - return nodeType !== 1 && nodeType !== 9 ? - false : - - // Nodes accept data unless otherwise specified; rejection can be conditional - !noData || noData !== true && elem.getAttribute("classid") === noData; - }; - - - var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - - function dataAttr(elem, key, data) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if (data === undefined && elem.nodeType === 1) { - - var name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase(); - - data = elem.getAttribute(name); - - if (typeof data === "string") { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test(data) ? jQuery.parseJSON(data) : - data; - } catch (e) { } - - // Make sure we set the data so it isn't changed later - jQuery.data(elem, key, data); - - } else { - data = undefined; - } - } - - return data; - } - - // checks a cache object for emptiness - function isEmptyDataObject(obj) { - var name; - for (name in obj) { - - // if the public data object is empty, the private is still empty - if (name === "data" && jQuery.isEmptyObject(obj[name])) { - continue; - } - if (name !== "toJSON") { - return false; - } - } - - return true; - } - - function internalData(elem, name, data, pvt /* Internal Use Only */) { - if (!jQuery.acceptData(elem)) { - return; - } - - var ret, thisCache, - internalKey = jQuery.expando, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[internalKey] : elem[internalKey] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ((!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string") { - return; - } - - if (!id) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if (isNode) { - id = elem[internalKey] = deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if (!cache[id]) { - // Avoid exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - cache[id] = isNode ? {} : { toJSON: jQuery.noop }; - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if (typeof name === "object" || typeof name === "function") { - if (pvt) { - cache[id] = jQuery.extend(cache[id], name); - } else { - cache[id].data = jQuery.extend(cache[id].data, name); - } - } - - thisCache = cache[id]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if (!pvt) { - if (!thisCache.data) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if (data !== undefined) { - thisCache[jQuery.camelCase(name)] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if (typeof name === "string") { - - // First Try to find as-is property data - ret = thisCache[name]; - - // Test for null|undefined property data - if (ret == null) { - - // Try to find the camelCased property - ret = thisCache[jQuery.camelCase(name)]; - } - } else { - ret = thisCache; - } - - return ret; - } - - function internalRemoveData(elem, name, pvt) { - if (!jQuery.acceptData(elem)) { - return; - } - - var thisCache, i, - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[jQuery.expando] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if (!cache[id]) { - return; - } - - if (name) { - - thisCache = pvt ? cache[id] : cache[id].data; - - if (thisCache) { - - // Support array or space separated string names for data keys - if (!jQuery.isArray(name)) { - - // try the string as a key before any manipulation - if (name in thisCache) { - name = [name]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase(name); - if (name in thisCache) { - name = [name]; - } else { - name = name.split(" "); - } - } - } else { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = name.concat(jQuery.map(name, jQuery.camelCase)); - } - - i = name.length; - while (i--) { - delete thisCache[name[i]]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if (pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache)) { - return; - } - } - } - - // See jQuery.data for more information - if (!pvt) { - delete cache[id].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if (!isEmptyDataObject(cache[id])) { - return; - } - } - - // Destroy the cache - if (isNode) { - jQuery.cleanData([elem], true); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - /* jshint eqeqeq: false */ - } else if (support.deleteExpando || cache != cache.window) { - /* jshint eqeqeq: true */ - delete cache[id]; - - // When all else fails, null - } else { - cache[id] = null; - } - } - - jQuery.extend({ - cache: {}, - - // The following elements (space-suffixed to avoid Object.prototype collisions) - // throw uncatchable exceptions if you attempt to set expando properties - noData: { - "applet ": true, - "embed ": true, - // ...but Flash objects (which have this classid) *can* handle expandos - "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" - }, - - hasData: function (elem) { - elem = elem.nodeType ? jQuery.cache[elem[jQuery.expando]] : elem[jQuery.expando]; - return !!elem && !isEmptyDataObject(elem); - }, - - data: function (elem, name, data) { - return internalData(elem, name, data); - }, - - removeData: function (elem, name) { - return internalRemoveData(elem, name); - }, - - // For internal use only. - _data: function (elem, name, data) { - return internalData(elem, name, data, true); - }, - - _removeData: function (elem, name) { - return internalRemoveData(elem, name, true); - } - }); - - jQuery.fn.extend({ - data: function (key, value) { - var i, name, data, - elem = this[0], - attrs = elem && elem.attributes; - - // Special expections of .data basically thwart jQuery.access, - // so implement the relevant behavior ourselves - - // Gets all values - if (key === undefined) { - if (this.length) { - data = jQuery.data(elem); - - if (elem.nodeType === 1 && !jQuery._data(elem, "parsedAttrs")) { - i = attrs.length; - while (i--) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if (attrs[i]) { - name = attrs[i].name; - if (name.indexOf("data-") === 0) { - name = jQuery.camelCase(name.slice(5)); - dataAttr(elem, name, data[name]); - } - } - } - jQuery._data(elem, "parsedAttrs", true); - } - } - - return data; - } - - // Sets multiple values - if (typeof key === "object") { - return this.each(function () { - jQuery.data(this, key); - }); - } - - return arguments.length > 1 ? - - // Sets one value - this.each(function () { - jQuery.data(this, key, value); - }) : - - // Gets one value - // Try to fetch any internally stored data first - elem ? dataAttr(elem, key, jQuery.data(elem, key)) : undefined; - }, - - removeData: function (key) { - return this.each(function () { - jQuery.removeData(this, key); - }); - } - }); - - - jQuery.extend({ - queue: function (elem, type, data) { - var queue; - - if (elem) { - type = (type || "fx") + "queue"; - queue = jQuery._data(elem, type); - - // Speed up dequeue by getting out quickly if this is just a lookup - if (data) { - if (!queue || jQuery.isArray(data)) { - queue = jQuery._data(elem, type, jQuery.makeArray(data)); - } else { - queue.push(data); - } - } - return queue || []; - } - }, - - dequeue: function (elem, type) { - type = type || "fx"; - - var queue = jQuery.queue(elem, type), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks(elem, type), - next = function () { - jQuery.dequeue(elem, type); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if (fn === "inprogress") { - fn = queue.shift(); - startLength--; - } - - if (fn) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if (type === "fx") { - queue.unshift("inprogress"); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call(elem, next, hooks); - } - - if (!startLength && hooks) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function (elem, type) { - var key = type + "queueHooks"; - return jQuery._data(elem, key) || jQuery._data(elem, key, { - empty: jQuery.Callbacks("once memory").add(function () { - jQuery._removeData(elem, type + "queue"); - jQuery._removeData(elem, key); - }) - }); - } - }); - - jQuery.fn.extend({ - queue: function (type, data) { - var setter = 2; - - if (typeof type !== "string") { - data = type; - type = "fx"; - setter--; - } - - if (arguments.length < setter) { - return jQuery.queue(this[0], type); - } - - return data === undefined ? - this : - this.each(function () { - var queue = jQuery.queue(this, type, data); - - // ensure a hooks for this queue - jQuery._queueHooks(this, type); - - if (type === "fx" && queue[0] !== "inprogress") { - jQuery.dequeue(this, type); - } - }); - }, - dequeue: function (type) { - return this.each(function () { - jQuery.dequeue(this, type); - }); - }, - clearQueue: function (type) { - return this.queue(type || "fx", []); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function (type, obj) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function () { - if (!(--count)) { - defer.resolveWith(elements, [elements]); - } - }; - - if (typeof type !== "string") { - obj = type; - type = undefined; - } - type = type || "fx"; - - while (i--) { - tmp = jQuery._data(elements[i], type + "queueHooks"); - if (tmp && tmp.empty) { - count++; - tmp.empty.add(resolve); - } - } - resolve(); - return defer.promise(obj); - } - }); - var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - - var cssExpand = ["Top", "Right", "Bottom", "Left"]; - - var isHidden = function (elem, el) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css(elem, "display") === "none" || !jQuery.contains(elem.ownerDocument, elem); - }; - - - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - var access = jQuery.access = function (elems, fn, key, value, chainable, emptyGet, raw) { - var i = 0, - length = elems.length, - bulk = key == null; - - // Sets many values - if (jQuery.type(key) === "object") { - chainable = true; - for (i in key) { - jQuery.access(elems, fn, i, key[i], true, emptyGet, raw); - } - - // Sets one value - } else if (value !== undefined) { - chainable = true; - - if (!jQuery.isFunction(value)) { - raw = true; - } - - if (bulk) { - // Bulk operations run against the entire set - if (raw) { - fn.call(elems, value); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function (elem, key, value) { - return bulk.call(jQuery(elem), value); - }; - } - } - - if (fn) { - for (; i < length; i++) { - fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key))); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call(elems) : - length ? fn(elems[0], key) : emptyGet; - }; - var rcheckableType = (/^(?:checkbox|radio)$/i); - - - - (function () { - // Minified: var a,b,c - var input = document.createElement("input"), - div = document.createElement("div"), - fragment = document.createDocumentFragment(); - - // Setup - div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; - - // IE strips leading whitespace when .innerHTML is used - support.leadingWhitespace = div.firstChild.nodeType === 3; - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - support.tbody = !div.getElementsByTagName("tbody").length; - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - support.htmlSerialize = !!div.getElementsByTagName("link").length; - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - support.html5Clone = - document.createElement("nav").cloneNode(true).outerHTML !== "<:nav></:nav>"; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - input.type = "checkbox"; - input.checked = true; - fragment.appendChild(input); - support.appendChecked = input.checked; - - // Make sure textarea (and checkbox) defaultValue is properly cloned - // Support: IE6-IE11+ - div.innerHTML = "<textarea>x</textarea>"; - support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue; - - // #11217 - WebKit loses check when the name is after the checked attribute - fragment.appendChild(div); - div.innerHTML = "<input type='radio' checked='checked' name='t'/>"; - - // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 - // old WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked; - - // Support: IE<9 - // Opera does not clone events (and typeof div.attachEvent === undefined). - // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() - support.noCloneEvent = true; - if (div.attachEvent) { - div.attachEvent("onclick", function () { - support.noCloneEvent = false; - }); - - div.cloneNode(true).click(); - } - - // Execute the test only if not already executed in another module. - if (support.deleteExpando == null) { - // Support: IE<9 - support.deleteExpando = true; - try { - delete div.test; - } catch (e) { - support.deleteExpando = false; - } - } - })(); - - - (function () { - var i, eventName, - div = document.createElement("div"); - - // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) - for (i in { submit: true, change: true, focusin: true }) { - eventName = "on" + i; - - if (!(support[i + "Bubbles"] = eventName in window)) { - // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) - div.setAttribute(eventName, "t"); - support[i + "Bubbles"] = div.attributes[eventName].expando === false; - } - } - - // Null elements to avoid leaks in IE. - div = null; - })(); - - - var rformElems = /^(?:input|select|textarea)$/i, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - - function returnTrue() { - return true; - } - - function returnFalse() { - return false; - } - - function safeActiveElement() { - try { - return document.activeElement; - } catch (err) { } - } - - /* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ - jQuery.event = { - - global: {}, - - add: function (elem, types, handler, data, selector) { - var tmp, events, t, handleObjIn, - special, eventHandle, handleObj, - handlers, type, namespaces, origType, - elemData = jQuery._data(elem); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if (!elemData) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if (handler.handler) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if (!handler.guid) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if (!(events = elemData.events)) { - events = elemData.events = {}; - } - if (!(eventHandle = elemData.handle)) { - eventHandle = elemData.handle = function (e) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply(eventHandle.elem, arguments) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - types = (types || "").match(rnotwhite) || [""]; - t = types.length; - while (t--) { - tmp = rtypenamespace.exec(types[t]) || []; - type = origType = tmp[1]; - namespaces = (tmp[2] || "").split(".").sort(); - - // There *must* be a type, no attaching namespace-only handlers - if (!type) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[type] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = (selector ? special.delegateType : special.bindType) || type; - - // Update special based on newly reset type - special = jQuery.event.special[type] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test(selector), - namespace: namespaces.join(".") - }, handleObjIn); - - // Init the event handler queue if we're the first - if (!(handlers = events[type])) { - handlers = events[type] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) { - // Bind the global event handler to the element - if (elem.addEventListener) { - elem.addEventListener(type, eventHandle, false); - - } else if (elem.attachEvent) { - elem.attachEvent("on" + type, eventHandle); - } - } - } - - if (special.add) { - special.add.call(elem, handleObj); - - if (!handleObj.handler.guid) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if (selector) { - handlers.splice(handlers.delegateCount++, 0, handleObj); - } else { - handlers.push(handleObj); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[type] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - // Detach an event or set of events from an element - remove: function (elem, types, handler, selector, mappedTypes) { - var j, handleObj, tmp, - origCount, t, events, - special, handlers, type, - namespaces, origType, - elemData = jQuery.hasData(elem) && jQuery._data(elem); - - if (!elemData || !(events = elemData.events)) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = (types || "").match(rnotwhite) || [""]; - t = types.length; - while (t--) { - tmp = rtypenamespace.exec(types[t]) || []; - type = origType = tmp[1]; - namespaces = (tmp[2] || "").split(".").sort(); - - // Unbind all events (on this namespace, if provided) for the element - if (!type) { - for (type in events) { - jQuery.event.remove(elem, type + types[t], handler, selector, true); - } - continue; - } - - special = jQuery.event.special[type] || {}; - type = (selector ? special.delegateType : special.bindType) || type; - handlers = events[type] || []; - tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)"); - - // Remove matching events - origCount = j = handlers.length; - while (j--) { - handleObj = handlers[j]; - - if ((mappedTypes || origType === handleObj.origType) && - (!handler || handler.guid === handleObj.guid) && - (!tmp || tmp.test(handleObj.namespace)) && - (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) { - handlers.splice(j, 1); - - if (handleObj.selector) { - handlers.delegateCount--; - } - if (special.remove) { - special.remove.call(elem, handleObj); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if (origCount && !handlers.length) { - if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) { - jQuery.removeEvent(elem, type, elemData.handle); - } - - delete events[type]; - } - } - - // Remove the expando if it's no longer used - if (jQuery.isEmptyObject(events)) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery._removeData(elem, "events"); - } - }, - - trigger: function (event, data, elem, onlyHandlers) { - var handle, ontype, cur, - bubbleType, special, tmp, i, - eventPath = [elem || document], - type = hasOwn.call(event, "type") ? event.type : event, - namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if (elem.nodeType === 3 || elem.nodeType === 8) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if (rfocusMorph.test(type + jQuery.event.triggered)) { - return; - } - - if (type.indexOf(".") >= 0) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[jQuery.expando] ? - event : - new jQuery.Event(type, typeof event === "object" && event); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if (!event.target) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [event] : - jQuery.makeArray(data, [event]); - - // Allow special events to draw outside the lines - special = jQuery.event.special[type] || {}; - if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if (!onlyHandlers && !special.noBubble && !jQuery.isWindow(elem)) { - - bubbleType = special.delegateType || type; - if (!rfocusMorph.test(bubbleType + type)) { - cur = cur.parentNode; - } - for (; cur; cur = cur.parentNode) { - eventPath.push(cur); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if (tmp === (elem.ownerDocument || document)) { - eventPath.push(tmp.defaultView || tmp.parentWindow || window); - } - } - - // Fire handlers on the event path - i = 0; - while ((cur = eventPath[i++]) && !event.isPropagationStopped()) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = (jQuery._data(cur, "events") || {})[event.type] && jQuery._data(cur, "handle"); - if (handle) { - handle.apply(cur, data); - } - - // Native handler - handle = ontype && cur[ontype]; - if (handle && handle.apply && jQuery.acceptData(cur)) { - event.result = handle.apply(cur, data); - if (event.result === false) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if (!onlyHandlers && !event.isDefaultPrevented()) { - - if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && - jQuery.acceptData(elem)) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - if (ontype && elem[type] && !jQuery.isWindow(elem)) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ontype]; - - if (tmp) { - elem[ontype] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - try { - elem[type](); - } catch (e) { - // IE<9 dies on focus/blur to hidden element (#1486,#12518) - // only reproducible on winXP IE8 native, not IE9 in IE8 mode - } - jQuery.event.triggered = undefined; - - if (tmp) { - elem[ontype] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function (event) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix(event); - - var i, ret, handleObj, matched, j, - handlerQueue = [], - args = slice.call(arguments), - handlers = (jQuery._data(this, "events") || {})[event.type] || [], - special = jQuery.event.special[event.type] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if (special.preDispatch && special.preDispatch.call(this, event) === false) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call(this, event, handlers); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) { - event.currentTarget = matched.elem; - - j = 0; - while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if (!event.namespace_re || event.namespace_re.test(handleObj.namespace)) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler) - .apply(matched.elem, args); - - if (ret !== undefined) { - if ((event.result = ret) === false) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if (special.postDispatch) { - special.postDispatch.call(this, event); - } - - return event.result; - }, - - handlers: function (event, handlers) { - var sel, handleObj, matches, i, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG <use> instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if (delegateCount && cur.nodeType && (!event.button || event.type !== "click")) { - - /* jshint eqeqeq: false */ - for (; cur != this; cur = cur.parentNode || this) { - /* jshint eqeqeq: true */ - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if (cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click")) { - matches = []; - for (i = 0; i < delegateCount; i++) { - handleObj = handlers[i]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if (matches[sel] === undefined) { - matches[sel] = handleObj.needsContext ? - jQuery(sel, this).index(cur) >= 0 : - jQuery.find(sel, this, null, [cur]).length; - } - if (matches[sel]) { - matches.push(handleObj); - } - } - if (matches.length) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if (delegateCount < handlers.length) { - handlerQueue.push({ elem: this, handlers: handlers.slice(delegateCount) }); - } - - return handlerQueue; - }, - - fix: function (event) { - if (event[jQuery.expando]) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[type]; - - if (!fixHook) { - this.fixHooks[type] = fixHook = - rmouseEvent.test(type) ? this.mouseHooks : - rkeyEvent.test(type) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat(fixHook.props) : this.props; - - event = new jQuery.Event(originalEvent); - - i = copy.length; - while (i--) { - prop = copy[i]; - event[prop] = originalEvent[prop]; - } - - // Support: IE<9 - // Fix target property (#1925) - if (!event.target) { - event.target = originalEvent.srcElement || document; - } - - // Support: Chrome 23+, Safari? - // Target should not be a text node (#504, #13143) - if (event.target.nodeType === 3) { - event.target = event.target.parentNode; - } - - // Support: IE<9 - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) - event.metaKey = !!event.metaKey; - - return fixHook.filter ? fixHook.filter(event, originalEvent) : event; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function (event, original) { - - // Add which for key events - if (event.which == null) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function (event, original) { - var body, eventDoc, doc, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if (event.pageX == null && original.clientX != null) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add relatedTarget, if necessary - if (!event.relatedTarget && fromElement) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if (!event.which && button !== undefined) { - event.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); - } - - return event; - } - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function () { - if (this !== safeActiveElement() && this.focus) { - try { - this.focus(); - return false; - } catch (e) { - // Support: IE<9 - // If we error on focus to hidden element (#1486, #12518), - // let .trigger() run the handlers - } - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function () { - if (this === safeActiveElement() && this.blur) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function () { - if (jQuery.nodeName(this, "input") && this.type === "checkbox" && this.click) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function (event) { - return jQuery.nodeName(event.target, "a"); - } - }, - - beforeunload: { - postDispatch: function (event) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if (event.result !== undefined && event.originalEvent) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function (type, elem, event, bubble) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if (bubble) { - jQuery.event.trigger(e, null, elem); - } else { - jQuery.event.dispatch.call(elem, e); - } - if (e.isDefaultPrevented()) { - event.preventDefault(); - } - } - }; - - jQuery.removeEvent = document.removeEventListener ? - function (elem, type, handle) { - if (elem.removeEventListener) { - elem.removeEventListener(type, handle, false); - } - } : - function (elem, type, handle) { - var name = "on" + type; - - if (elem.detachEvent) { - - // #8545, #7054, preventing memory leaks for custom events in IE6-8 - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if (typeof elem[name] === strundefined) { - elem[name] = null; - } - - elem.detachEvent(name, handle); - } - }; - - jQuery.Event = function (src, props) { - // Allow instantiation without the 'new' keyword - if (!(this instanceof jQuery.Event)) { - return new jQuery.Event(src, props); - } - - // Event object - if (src && src.type) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: IE < 9, Android < 4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if (props) { - jQuery.extend(this, props); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[jQuery.expando] = true; - }; - - // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding - // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html - jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function () { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - if (!e) { - return; - } - - // If preventDefault exists, run it on the original event - if (e.preventDefault) { - e.preventDefault(); - - // Support: IE - // Otherwise set the returnValue property of the original event to false - } else { - e.returnValue = false; - } - }, - stopPropagation: function () { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - if (!e) { - return; - } - // If stopPropagation exists, run it on the original event - if (e.stopPropagation) { - e.stopPropagation(); - } - - // Support: IE - // Set the cancelBubble property of the original event to true - e.cancelBubble = true; - }, - stopImmediatePropagation: function () { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if (e && e.stopImmediatePropagation) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } - }; - - // Create mouseenter/leave events using mouseover/out and event-time checks - jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" - }, function (orig, fix) { - jQuery.event.special[orig] = { - delegateType: fix, - bindType: fix, - - handle: function (event) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if (!related || (related !== target && !jQuery.contains(target, related))) { - event.type = handleObj.origType; - ret = handleObj.handler.apply(this, arguments); - event.type = fix; - } - return ret; - } - }; - }); - - // IE submit delegation - if (!support.submitBubbles) { - - jQuery.event.special.submit = { - setup: function () { - // Only need this for delegated form submit events - if (jQuery.nodeName(this, "form")) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add(this, "click._submit keypress._submit", function (e) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName(elem, "input") || jQuery.nodeName(elem, "button") ? elem.form : undefined; - if (form && !jQuery._data(form, "submitBubbles")) { - jQuery.event.add(form, "submit._submit", function (event) { - event._submit_bubble = true; - }); - jQuery._data(form, "submitBubbles", true); - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function (event) { - // If form was submitted by the user, bubble the event up the tree - if (event._submit_bubble) { - delete event._submit_bubble; - if (this.parentNode && !event.isTrigger) { - jQuery.event.simulate("submit", this.parentNode, event, true); - } - } - }, - - teardown: function () { - // Only need this for delegated form submit events - if (jQuery.nodeName(this, "form")) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove(this, "._submit"); - } - }; - } - - // IE change delegation and checkbox/radio fix - if (!support.changeBubbles) { - - jQuery.event.special.change = { - - setup: function () { - - if (rformElems.test(this.nodeName)) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if (this.type === "checkbox" || this.type === "radio") { - jQuery.event.add(this, "propertychange._change", function (event) { - if (event.originalEvent.propertyName === "checked") { - this._just_changed = true; - } - }); - jQuery.event.add(this, "click._change", function (event) { - if (this._just_changed && !event.isTrigger) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate("change", this, event, true); - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add(this, "beforeactivate._change", function (e) { - var elem = e.target; - - if (rformElems.test(elem.nodeName) && !jQuery._data(elem, "changeBubbles")) { - jQuery.event.add(elem, "change._change", function (event) { - if (this.parentNode && !event.isSimulated && !event.isTrigger) { - jQuery.event.simulate("change", this.parentNode, event, true); - } - }); - jQuery._data(elem, "changeBubbles", true); - } - }); - }, - - handle: function (event) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if (this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox")) { - return event.handleObj.handler.apply(this, arguments); - } - }, - - teardown: function () { - jQuery.event.remove(this, "._change"); - - return !rformElems.test(this.nodeName); - } - }; - } - - // Create "bubbling" focus and blur events - if (!support.focusinBubbles) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function (orig, fix) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function (event) { - jQuery.event.simulate(fix, event.target, jQuery.event.fix(event), true); - }; - - jQuery.event.special[fix] = { - setup: function () { - var doc = this.ownerDocument || this, - attaches = jQuery._data(doc, fix); - - if (!attaches) { - doc.addEventListener(orig, handler, true); - } - jQuery._data(doc, fix, (attaches || 0) + 1); - }, - teardown: function () { - var doc = this.ownerDocument || this, - attaches = jQuery._data(doc, fix) - 1; - - if (!attaches) { - doc.removeEventListener(orig, handler, true); - jQuery._removeData(doc, fix); - } else { - jQuery._data(doc, fix, attaches); - } - } - }; - }); - } - - jQuery.fn.extend({ - - on: function (types, selector, data, fn, /*INTERNAL*/ one) { - var type, origFn; - - // Types can be a map of types/handlers - if (typeof types === "object") { - // ( types-Object, selector, data ) - if (typeof selector !== "string") { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for (type in types) { - this.on(type, selector, data, types[type], one); - } - return this; - } - - if (data == null && fn == null) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if (fn == null) { - if (typeof selector === "string") { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if (fn === false) { - fn = returnFalse; - } else if (!fn) { - return this; - } - - if (one === 1) { - origFn = fn; - fn = function (event) { - // Can use an empty set, since event contains the info - jQuery().off(event); - return origFn.apply(this, arguments); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || (origFn.guid = jQuery.guid++); - } - return this.each(function () { - jQuery.event.add(this, types, fn, data, selector); - }); - }, - one: function (types, selector, data, fn) { - return this.on(types, selector, data, fn, 1); - }, - off: function (types, selector, fn) { - var handleObj, type; - if (types && types.preventDefault && types.handleObj) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery(types.delegateTarget).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if (typeof types === "object") { - // ( types-object [, selector] ) - for (type in types) { - this.off(type, selector, types[type]); - } - return this; - } - if (selector === false || typeof selector === "function") { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if (fn === false) { - fn = returnFalse; - } - return this.each(function () { - jQuery.event.remove(this, types, fn, selector); - }); - }, - - trigger: function (type, data) { - return this.each(function () { - jQuery.event.trigger(type, data, this); - }); - }, - triggerHandler: function (type, data) { - var elem = this[0]; - if (elem) { - return jQuery.event.trigger(type, data, elem, true); - } - } - }); - - - function createSafeFragment(document) { - var list = nodeNames.split("|"), - safeFrag = document.createDocumentFragment(); - - if (safeFrag.createElement) { - while (list.length) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; - } - - var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /<tbody/i, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /^$|\/(?:java|ecma)script/i, - rscriptTypeMasked = /^true\/(.*)/, - rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - option: [1, "<select multiple='multiple'>", "</select>"], - legend: [1, "<fieldset>", "</fieldset>"], - area: [1, "<map>", "</map>"], - param: [1, "<object>", "</object>"], - thead: [1, "<table>", "</table>"], - tr: [2, "<table><tbody>", "</tbody></table>"], - col: [2, "<table><tbody></tbody><colgroup>", "</colgroup></table>"], - td: [3, "<table><tbody><tr>", "</tr></tbody></table>"], - - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: support.htmlSerialize ? [0, "", ""] : [1, "X<div>", "</div>"] - }, - safeFragment = createSafeFragment(document), - fragmentDiv = safeFragment.appendChild(document.createElement("div")); - - wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - - function getAll(context, tag) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName(tag || "*") : - typeof context.querySelectorAll !== strundefined ? context.querySelectorAll(tag || "*") : - undefined; - - if (!found) { - for (found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++) { - if (!tag || jQuery.nodeName(elem, tag)) { - found.push(elem); - } else { - jQuery.merge(found, getAll(elem, tag)); - } - } - } - - return tag === undefined || tag && jQuery.nodeName(context, tag) ? - jQuery.merge([context], found) : - found; - } - - // Used in buildFragment, fixes the defaultChecked property - function fixDefaultChecked(elem) { - if (rcheckableType.test(elem.type)) { - elem.defaultChecked = elem.checked; - } - } - - // Support: IE<8 - // Manipulating tables requires a tbody - function manipulationTarget(elem, content) { - return jQuery.nodeName(elem, "table") && - jQuery.nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr") ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild(elem.ownerDocument.createElement("tbody")) : - elem; - } - - // Replace/restore the type attribute of script elements for safe DOM manipulation - function disableScript(elem) { - elem.type = (jQuery.find.attr(elem, "type") !== null) + "/" + elem.type; - return elem; - } - function restoreScript(elem) { - var match = rscriptTypeMasked.exec(elem.type); - if (match) { - elem.type = match[1]; - } else { - elem.removeAttribute("type"); - } - return elem; - } - - // Mark scripts as having already been evaluated - function setGlobalEval(elems, refElements) { - var elem, - i = 0; - for (; (elem = elems[i]) != null; i++) { - jQuery._data(elem, "globalEval", !refElements || jQuery._data(refElements[i], "globalEval")); - } - } - - function cloneCopyEvent(src, dest) { - - if (dest.nodeType !== 1 || !jQuery.hasData(src)) { - return; - } - - var type, i, l, - oldData = jQuery._data(src), - curData = jQuery._data(dest, oldData), - events = oldData.events; - - if (events) { - delete curData.handle; - curData.events = {}; - - for (type in events) { - for (i = 0, l = events[type].length; i < l; i++) { - jQuery.event.add(dest, type, events[type][i]); - } - } - } - - // make the cloned public data object a copy from the original - if (curData.data) { - curData.data = jQuery.extend({}, curData.data); - } - } - - function fixCloneNodeIssues(src, dest) { - var nodeName, e, data; - - // We do not need to do anything for non-Elements - if (dest.nodeType !== 1) { - return; - } - - nodeName = dest.nodeName.toLowerCase(); - - // IE6-8 copies events bound via attachEvent when using cloneNode. - if (!support.noCloneEvent && dest[jQuery.expando]) { - data = jQuery._data(dest); - - for (e in data.events) { - jQuery.removeEvent(dest, e, data.handle); - } - - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute(jQuery.expando); - } - - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if (nodeName === "script" && dest.text !== src.text) { - disableScript(dest).text = src.text; - restoreScript(dest); - - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if (nodeName === "object") { - if (dest.parentNode) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if (support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML))) { - dest.innerHTML = src.innerHTML; - } - - } else if (nodeName === "input" && rcheckableType.test(src.type)) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if (dest.value !== src.value) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if (nodeName === "option") { - dest.defaultSelected = dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if (nodeName === "input" || nodeName === "textarea") { - dest.defaultValue = src.defaultValue; - } - } - - jQuery.extend({ - clone: function (elem, dataAndEvents, deepDataAndEvents) { - var destElements, node, clone, i, srcElements, - inPage = jQuery.contains(elem.ownerDocument, elem); - - if (support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test("<" + elem.nodeName + ">")) { - clone = elem.cloneNode(true); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild(clone = fragmentDiv.firstChild); - } - - if ((!support.noCloneEvent || !support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll(clone); - srcElements = getAll(elem); - - // Fix all IE cloning issues - for (i = 0; (node = srcElements[i]) != null; ++i) { - // Ensure that the destination node is not null; Fixes #9587 - if (destElements[i]) { - fixCloneNodeIssues(node, destElements[i]); - } - } - } - - // Copy the events from the original to the clone - if (dataAndEvents) { - if (deepDataAndEvents) { - srcElements = srcElements || getAll(elem); - destElements = destElements || getAll(clone); - - for (i = 0; (node = srcElements[i]) != null; i++) { - cloneCopyEvent(node, destElements[i]); - } - } else { - cloneCopyEvent(elem, clone); - } - } - - // Preserve script evaluation history - destElements = getAll(clone, "script"); - if (destElements.length > 0) { - setGlobalEval(destElements, !inPage && getAll(elem, "script")); - } - - destElements = srcElements = node = null; - - // Return the cloned set - return clone; - }, - - buildFragment: function (elems, context, scripts, selection) { - var j, elem, contains, - tmp, tag, tbody, wrap, - l = elems.length, - - // Ensure a safe fragment - safe = createSafeFragment(context), - - nodes = [], - i = 0; - - for (; i < l; i++) { - elem = elems[i]; - - if (elem || elem === 0) { - - // Add nodes directly - if (jQuery.type(elem) === "object") { - jQuery.merge(nodes, elem.nodeType ? [elem] : elem); - - // Convert non-html into a text node - } else if (!rhtml.test(elem)) { - nodes.push(context.createTextNode(elem)); - - // Convert html into DOM nodes - } else { - tmp = tmp || safe.appendChild(context.createElement("div")); - - // Deserialize a standard representation - tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase(); - wrap = wrapMap[tag] || wrapMap._default; - - tmp.innerHTML = wrap[1] + elem.replace(rxhtmlTag, "<$1></$2>") + wrap[2]; - - // Descend through wrappers to the right content - j = wrap[0]; - while (j--) { - tmp = tmp.lastChild; - } - - // Manually add leading whitespace removed by IE - if (!support.leadingWhitespace && rleadingWhitespace.test(elem)) { - nodes.push(context.createTextNode(rleadingWhitespace.exec(elem)[0])); - } - - // Remove IE's autoinserted <tbody> from table fragments - if (!support.tbody) { - - // String was a <table>, *may* have spurious <tbody> - elem = tag === "table" && !rtbody.test(elem) ? - tmp.firstChild : - - // String was a bare <thead> or <tfoot> - wrap[1] === "<table>" && !rtbody.test(elem) ? - tmp : - 0; - - j = elem && elem.childNodes.length; - while (j--) { - if (jQuery.nodeName((tbody = elem.childNodes[j]), "tbody") && !tbody.childNodes.length) { - elem.removeChild(tbody); - } - } - } - - jQuery.merge(nodes, tmp.childNodes); - - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; - - // Fix #12392 for oldIE - while (tmp.firstChild) { - tmp.removeChild(tmp.firstChild); - } - - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; - } - } - } - - // Fix #11356: Clear elements from fragment - if (tmp) { - safe.removeChild(tmp); - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if (!support.appendChecked) { - jQuery.grep(getAll(nodes, "input"), fixDefaultChecked); - } - - i = 0; - while ((elem = nodes[i++])) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if (selection && jQuery.inArray(elem, selection) !== -1) { - continue; - } - - contains = jQuery.contains(elem.ownerDocument, elem); - - // Append to fragment - tmp = getAll(safe.appendChild(elem), "script"); - - // Preserve script evaluation history - if (contains) { - setGlobalEval(tmp); - } - - // Capture executables - if (scripts) { - j = 0; - while ((elem = tmp[j++])) { - if (rscriptType.test(elem.type || "")) { - scripts.push(elem); - } - } - } - } - - tmp = null; - - return safe; - }, - - cleanData: function (elems, /* internal */ acceptData) { - var elem, type, id, data, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = support.deleteExpando, - special = jQuery.event.special; - - for (; (elem = elems[i]) != null; i++) { - if (acceptData || jQuery.acceptData(elem)) { - - id = elem[internalKey]; - data = id && cache[id]; - - if (data) { - if (data.events) { - for (type in data.events) { - if (special[type]) { - jQuery.event.remove(elem, type); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent(elem, type, data.handle); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if (cache[id]) { - - delete cache[id]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if (deleteExpando) { - delete elem[internalKey]; - - } else if (typeof elem.removeAttribute !== strundefined) { - elem.removeAttribute(internalKey); - - } else { - elem[internalKey] = null; - } - - deletedIds.push(id); - } - } - } - } - } - }); - - jQuery.fn.extend({ - text: function (value) { - return access(this, function (value) { - return value === undefined ? - jQuery.text(this) : - this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(value)); - }, null, value, arguments.length); - }, - - append: function () { - return this.domManip(arguments, function (elem) { - if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { - var target = manipulationTarget(this, elem); - target.appendChild(elem); - } - }); - }, - - prepend: function () { - return this.domManip(arguments, function (elem) { - if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { - var target = manipulationTarget(this, elem); - target.insertBefore(elem, target.firstChild); - } - }); - }, - - before: function () { - return this.domManip(arguments, function (elem) { - if (this.parentNode) { - this.parentNode.insertBefore(elem, this); - } - }); - }, - - after: function () { - return this.domManip(arguments, function (elem) { - if (this.parentNode) { - this.parentNode.insertBefore(elem, this.nextSibling); - } - }); - }, - - remove: function (selector, keepData /* Internal Use Only */) { - var elem, - elems = selector ? jQuery.filter(selector, this) : this, - i = 0; - - for (; (elem = elems[i]) != null; i++) { - - if (!keepData && elem.nodeType === 1) { - jQuery.cleanData(getAll(elem)); - } - - if (elem.parentNode) { - if (keepData && jQuery.contains(elem.ownerDocument, elem)) { - setGlobalEval(getAll(elem, "script")); - } - elem.parentNode.removeChild(elem); - } - } - - return this; - }, - - empty: function () { - var elem, - i = 0; - - for (; (elem = this[i]) != null; i++) { - // Remove element nodes and prevent memory leaks - if (elem.nodeType === 1) { - jQuery.cleanData(getAll(elem, false)); - } - - // Remove any remaining nodes - while (elem.firstChild) { - elem.removeChild(elem.firstChild); - } - - // If this is a select, ensure that it displays empty (#12336) - // Support: IE<9 - if (elem.options && jQuery.nodeName(elem, "select")) { - elem.options.length = 0; - } - } - - return this; - }, - - clone: function (dataAndEvents, deepDataAndEvents) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function () { - return jQuery.clone(this, dataAndEvents, deepDataAndEvents); - }); - }, - - html: function (value) { - return access(this, function (value) { - var elem = this[0] || {}, - i = 0, - l = this.length; - - if (value === undefined) { - return elem.nodeType === 1 ? - elem.innerHTML.replace(rinlinejQuery, "") : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if (typeof value === "string" && !rnoInnerhtml.test(value) && - (support.htmlSerialize || !rnoshimcache.test(value)) && - (support.leadingWhitespace || !rleadingWhitespace.test(value)) && - !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) { - - value = value.replace(rxhtmlTag, "<$1></$2>"); - - try { - for (; i < l; i++) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if (elem.nodeType === 1) { - jQuery.cleanData(getAll(elem, false)); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch (e) { } - } - - if (elem) { - this.empty().append(value); - } - }, null, value, arguments.length); - }, - - replaceWith: function () { - var arg = arguments[0]; - - // Make the changes, replacing each context element with the new content - this.domManip(arguments, function (elem) { - arg = this.parentNode; - - jQuery.cleanData(getAll(this)); - - if (arg) { - arg.replaceChild(elem, this); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function (selector) { - return this.remove(selector, true); - }, - - domManip: function (args, callback) { - - // Flatten any nested arrays - args = concat.apply([], args); - - var first, node, hasScripts, - scripts, doc, fragment, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[0], - isFunction = jQuery.isFunction(value); - - // We can't cloneNode fragments that contain checked, in WebKit - if (isFunction || - (l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test(value))) { - return this.each(function (index) { - var self = set.eq(index); - if (isFunction) { - args[0] = value.call(this, index, self.html()); - } - self.domManip(args, callback); - }); - } - - if (l) { - fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this); - first = fragment.firstChild; - - if (fragment.childNodes.length === 1) { - fragment = first; - } - - if (first) { - scripts = jQuery.map(getAll(fragment, "script"), disableScript); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for (; i < l; i++) { - node = fragment; - - if (i !== iNoClone) { - node = jQuery.clone(node, true, true); - - // Keep references to cloned scripts for later restoration - if (hasScripts) { - jQuery.merge(scripts, getAll(node, "script")); - } - } - - callback.call(this[i], node, i); - } - - if (hasScripts) { - doc = scripts[scripts.length - 1].ownerDocument; - - // Reenable scripts - jQuery.map(scripts, restoreScript); - - // Evaluate executable scripts on first document insertion - for (i = 0; i < hasScripts; i++) { - node = scripts[i]; - if (rscriptType.test(node.type || "") && - !jQuery._data(node, "globalEval") && jQuery.contains(doc, node)) { - - if (node.src) { - // Optional AJAX dependency, but won't run scripts if not present - if (jQuery._evalUrl) { - jQuery._evalUrl(node.src); - } - } else { - jQuery.globalEval((node.text || node.textContent || node.innerHTML || "").replace(rcleanScript, "")); - } - } - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - } - } - - return this; - } - }); - - jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" - }, function (name, original) { - jQuery.fn[name] = function (selector) { - var elems, - i = 0, - ret = [], - insert = jQuery(selector), - last = insert.length - 1; - - for (; i <= last; i++) { - elems = i === last ? this : this.clone(true); - jQuery(insert[i])[original](elems); - - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - push.apply(ret, elems.get()); - } - - return this.pushStack(ret); - }; - }); - - - var iframe, - elemdisplay = {}; - - /** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ - // Called only from within defaultDisplay - function actualDisplay(name, doc) { - var style, - elem = jQuery(doc.createElement(name)).appendTo(doc.body), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && (style = window.getDefaultComputedStyle(elem[0])) ? - - // Use of this method is a temporary fix (more like optmization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css(elem[0], "display"); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; - } - - /** - * Try to determine the default display value of an element - * @param {String} nodeName - */ - function defaultDisplay(nodeName) { - var doc = document, - display = elemdisplay[nodeName]; - - if (!display) { - display = actualDisplay(nodeName, doc); - - // If the simple way fails, read from inside an iframe - if (display === "none" || !display) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery("<iframe frameborder='0' width='0' height='0'/>")).appendTo(doc.documentElement); - - // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse - doc = (iframe[0].contentWindow || iframe[0].contentDocument).document; - - // Support: IE - doc.write(); - doc.close(); - - display = actualDisplay(nodeName, doc); - iframe.detach(); - } - - // Store the correct default display - elemdisplay[nodeName] = display; - } - - return display; - } - - - (function () { - var shrinkWrapBlocksVal; - - support.shrinkWrapBlocks = function () { - if (shrinkWrapBlocksVal != null) { - return shrinkWrapBlocksVal; - } - - // Will be changed later if needed. - shrinkWrapBlocksVal = false; - - // Minified: var b,c,d - var div, body, container; - - body = document.getElementsByTagName("body")[0]; - if (!body || !body.style) { - // Test fired too early or in an unsupported environment, exit. - return; - } - - // Setup - div = document.createElement("div"); - container = document.createElement("div"); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild(container).appendChild(div); - - // Support: IE6 - // Check if elements with layout shrink-wrap their children - if (typeof div.style.zoom !== strundefined) { - // Reset CSS: box-sizing; display; margin; border - div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;" + - "padding:1px;width:1px;zoom:1"; - div.appendChild(document.createElement("div")).style.width = "5px"; - shrinkWrapBlocksVal = div.offsetWidth !== 3; - } - - body.removeChild(container); - - return shrinkWrapBlocksVal; - }; - - })(); - var rmargin = (/^margin/); - - var rnumnonpx = new RegExp("^(" + pnum + ")(?!px)[a-z%]+$", "i"); - - - - var getStyles, curCSS, - rposition = /^(top|right|bottom|left)$/; - - if (window.getComputedStyle) { - getStyles = function (elem) { - return elem.ownerDocument.defaultView.getComputedStyle(elem, null); - }; - - curCSS = function (elem, name, computed) { - var width, minWidth, maxWidth, ret, - style = elem.style; - - computed = computed || getStyles(elem); - - // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - ret = computed ? computed.getPropertyValue(name) || computed[name] : undefined; - - if (computed) { - - if (ret === "" && !jQuery.contains(elem.ownerDocument, elem)) { - ret = jQuery.style(elem, name); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right - // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if (rnumnonpx.test(ret) && rmargin.test(name)) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - // Support: IE - // IE returns zIndex value as an integer. - return ret === undefined ? - ret : - ret + ""; - }; - } else if (document.documentElement.currentStyle) { - getStyles = function (elem) { - return elem.currentStyle; - }; - - curCSS = function (elem, name, computed) { - var left, rs, rsLeft, ret, - style = elem.style; - - computed = computed || getStyles(elem); - ret = computed ? computed[name] : undefined; - - // Avoid setting ret to empty string here - // so we don't default to auto - if (ret == null && style && style[name]) { - ret = style[name]; - } - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - // but not position css attributes, as those are proportional to the parent element instead - // and we can't measure the parent instead because it might trigger a "stacking dolls" problem - if (rnumnonpx.test(ret) && !rposition.test(name)) { - - // Remember the original values - left = style.left; - rs = elem.runtimeStyle; - rsLeft = rs && rs.left; - - // Put in the new values to get a computed value out - if (rsLeft) { - rs.left = elem.currentStyle.left; - } - style.left = name === "fontSize" ? "1em" : ret; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - if (rsLeft) { - rs.left = rsLeft; - } - } - - // Support: IE - // IE returns zIndex value as an integer. - return ret === undefined ? - ret : - ret + "" || "auto"; - }; - } - - - - - function addGetHookIf(conditionFn, hookFn) { - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function () { - var condition = conditionFn(); - - if (condition == null) { - // The test was not ready at this point; screw the hook this time - // but check again when needed next time. - return; - } - - if (condition) { - // Hook not needed (or it's not possible to use it due to missing dependency), - // remove it. - // Since there are no other hooks for marginRight, remove the whole object. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - - return (this.get = hookFn).apply(this, arguments); - } - }; - } - - - (function () { - // Minified: var b,c,d,e,f,g, h,i - var div, style, a, pixelPositionVal, boxSizingReliableVal, - reliableHiddenOffsetsVal, reliableMarginRightVal; - - // Setup - div = document.createElement("div"); - div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; - a = div.getElementsByTagName("a")[0]; - style = a && a.style; - - // Finish early in limited (non-browser) environments - if (!style) { - return; - } - - style.cssText = "float:left;opacity:.5"; - - // Support: IE<9 - // Make sure that element opacity exists (as opposed to filter) - support.opacity = style.opacity === "0.5"; - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - support.cssFloat = !!style.cssFloat; - - div.style.backgroundClip = "content-box"; - div.cloneNode(true).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" || - style.WebkitBoxSizing === ""; - - jQuery.extend(support, { - reliableHiddenOffsets: function () { - if (reliableHiddenOffsetsVal == null) { - computeStyleTests(); - } - return reliableHiddenOffsetsVal; - }, - - boxSizingReliable: function () { - if (boxSizingReliableVal == null) { - computeStyleTests(); - } - return boxSizingReliableVal; - }, - - pixelPosition: function () { - if (pixelPositionVal == null) { - computeStyleTests(); - } - return pixelPositionVal; - }, - - // Support: Android 2.3 - reliableMarginRight: function () { - if (reliableMarginRightVal == null) { - computeStyleTests(); - } - return reliableMarginRightVal; - } - }); - - function computeStyleTests() { - // Minified: var b,c,d,j - var div, body, container, contents; - - body = document.getElementsByTagName("body")[0]; - if (!body || !body.style) { - // Test fired too early or in an unsupported environment, exit. - return; - } - - // Setup - div = document.createElement("div"); - container = document.createElement("div"); - container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; - body.appendChild(container).appendChild(div); - - div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + - "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + - "border:1px;padding:1px;width:4px;position:absolute"; - - // Support: IE<9 - // Assume reasonable values in the absence of getComputedStyle - pixelPositionVal = boxSizingReliableVal = false; - reliableMarginRightVal = true; - - // Check for getComputedStyle so that this code is not run in IE<9. - if (window.getComputedStyle) { - pixelPositionVal = (window.getComputedStyle(div, null) || {}).top !== "1%"; - boxSizingReliableVal = - (window.getComputedStyle(div, null) || { width: "4px" }).width === "4px"; - - // Support: Android 2.3 - // Div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container (#3333) - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - contents = div.appendChild(document.createElement("div")); - - // Reset CSS: box-sizing; display; margin; border; padding - contents.style.cssText = div.style.cssText = - // Support: Firefox<29, Android 2.3 - // Vendor-prefix box-sizing - "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + - "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; - contents.style.marginRight = contents.style.width = "0"; - div.style.width = "1px"; - - reliableMarginRightVal = - !parseFloat((window.getComputedStyle(contents, null) || {}).marginRight); - } - - // Support: IE8 - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; - contents = div.getElementsByTagName("td"); - contents[0].style.cssText = "margin:0;border:0;padding:0;display:none"; - reliableHiddenOffsetsVal = contents[0].offsetHeight === 0; - if (reliableHiddenOffsetsVal) { - contents[0].style.display = ""; - contents[1].style.display = "none"; - reliableHiddenOffsetsVal = contents[0].offsetHeight === 0; - } - - body.removeChild(container); - } - - })(); - - - // A method for quickly swapping in/out CSS properties to get correct calculations. - jQuery.swap = function (elem, options, callback, args) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for (name in options) { - old[name] = elem.style[name]; - elem.style[name] = options[name]; - } - - ret = callback.apply(elem, args || []); - - // Revert the old values - for (name in options) { - elem.style[name] = old[name]; - } - - return ret; - }; - - - var - ralpha = /alpha\([^)]*\)/i, - ropacity = /opacity\s*=\s*([^)]*)/, - - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rnumsplit = new RegExp("^(" + pnum + ")(.*)$", "i"), - rrelNum = new RegExp("^([+-])=(" + pnum + ")", "i"), - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = ["Webkit", "O", "Moz", "ms"]; - - - // return a css property mapped to a potentially vendor prefixed property - function vendorPropName(style, name) { - - // shortcut for names that are not vendor prefixed - if (name in style) { - return name; - } - - // check for vendor prefixed names - var capName = name.charAt(0).toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while (i--) { - name = cssPrefixes[i] + capName; - if (name in style) { - return name; - } - } - - return origName; - } - - function showHide(elements, show) { - var display, elem, hidden, - values = [], - index = 0, - length = elements.length; - - for (; index < length; index++) { - elem = elements[index]; - if (!elem.style) { - continue; - } - - values[index] = jQuery._data(elem, "olddisplay"); - display = elem.style.display; - if (show) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if (!values[index] && display === "none") { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if (elem.style.display === "" && isHidden(elem)) { - values[index] = jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName)); - } - } else { - hidden = isHidden(elem); - - if (display && display !== "none" || !hidden) { - jQuery._data(elem, "olddisplay", hidden ? display : jQuery.css(elem, "display")); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for (index = 0; index < length; index++) { - elem = elements[index]; - if (!elem.style) { - continue; - } - if (!show || elem.style.display === "none" || elem.style.display === "") { - elem.style.display = show ? values[index] || "" : "none"; - } - } - - return elements; - } - - function setPositiveNumber(elem, value, subtract) { - var matches = rnumsplit.exec(value); - return matches ? - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max(0, matches[1] - (subtract || 0)) + (matches[2] || "px") : - value; - } - - function augmentWidthOrHeight(elem, name, extra, isBorderBox, styles) { - var i = extra === (isBorderBox ? "border" : "content") ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for (; i < 4; i += 2) { - // both box models exclude margin, so add it if we want it - if (extra === "margin") { - val += jQuery.css(elem, extra + cssExpand[i], true, styles); - } - - if (isBorderBox) { - // border-box includes padding, so remove it if we want content - if (extra === "content") { - val -= jQuery.css(elem, "padding" + cssExpand[i], true, styles); - } - - // at this point, extra isn't border nor margin, so remove border - if (extra !== "margin") { - val -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles); - } - } else { - // at this point, extra isn't content, so add padding - val += jQuery.css(elem, "padding" + cssExpand[i], true, styles); - - // at this point, extra isn't content nor padding, so add border - if (extra !== "padding") { - val += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles); - } - } - } - - return val; - } - - function getWidthOrHeight(elem, name, extra) { - - // Start with offset property, which is equivalent to the border-box value - var valueIsBorderBox = true, - val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - styles = getStyles(elem), - isBorderBox = support.boxSizing && jQuery.css(elem, "boxSizing", false, styles) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if (val <= 0 || val == null) { - // Fall back to computed then uncomputed css if necessary - val = curCSS(elem, name, styles); - if (val < 0 || val == null) { - val = elem.style[name]; - } - - // Computed unit is not pixels. Stop here and return. - if (rnumnonpx.test(val)) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && (support.boxSizingReliable() || val === elem.style[name]); - - // Normalize "", auto, and prepare for extra - val = parseFloat(val) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return (val + - augmentWidthOrHeight( - elem, - name, - extra || (isBorderBox ? "border" : "content"), - valueIsBorderBox, - styles - ) - ) + "px"; - } - - jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function (elem, computed) { - if (computed) { - // We should always get a number back from opacity - var ret = curCSS(elem, "opacity"); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": support.cssFloat ? "cssFloat" : "styleFloat" - }, - - // Get and set the style property on a DOM Node - style: function (elem, name, value, extra) { - // Don't set styles on text and comment nodes - if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase(name), - style = elem.style; - - name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(style, origName)); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; - - // Check if we're setting a value - if (value !== undefined) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if (type === "string" && (ret = rrelNum.exec(value))) { - value = (ret[1] + 1) * ret[2] + parseFloat(jQuery.css(elem, name)); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set. See: #7116 - if (value == null || value !== value) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if (type === "number" && !jQuery.cssNumber[origName]) { - value += "px"; - } - - // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, - // but it would mean to define eight (for every problematic property) identical functions - if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0) { - style[name] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) { - - // Support: IE - // Swallow errors from 'invalid' CSS values (#5509) - try { - style[name] = value; - } catch (e) { } - } - - } else { - // If a hook was provided get the non-computed value from there - if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) { - return ret; - } - - // Otherwise just get the value from the style object - return style[name]; - } - }, - - css: function (elem, name, extra, styles) { - var num, val, hooks, - origName = jQuery.camelCase(name); - - // Make sure that we're working with the right name - name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName)); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName]; - - // If a hook was provided get the computed value from there - if (hooks && "get" in hooks) { - val = hooks.get(elem, true, extra); - } - - // Otherwise, if a way to get the computed value exists, use that - if (val === undefined) { - val = curCSS(elem, name, styles); - } - - //convert "normal" to computed value - if (val === "normal" && name in cssNormalTransform) { - val = cssNormalTransform[name]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if (extra === "" || extra) { - num = parseFloat(val); - return extra === true || jQuery.isNumeric(num) ? num || 0 : val; - } - return val; - } - }); - - jQuery.each(["height", "width"], function (i, name) { - jQuery.cssHooks[name] = { - get: function (elem, computed, extra) { - if (computed) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - return rdisplayswap.test(jQuery.css(elem, "display")) && elem.offsetWidth === 0 ? - jQuery.swap(elem, cssShow, function () { - return getWidthOrHeight(elem, name, extra); - }) : - getWidthOrHeight(elem, name, extra); - } - }, - - set: function (elem, value, extra) { - var styles = extra && getStyles(elem); - return setPositiveNumber(elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - support.boxSizing && jQuery.css(elem, "boxSizing", false, styles) === "border-box", - styles - ) : 0 - ); - } - }; - }); - - if (!support.opacity) { - jQuery.cssHooks.opacity = { - get: function (elem, computed) { - // IE uses filters for opacity - return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? - (0.01 * parseFloat(RegExp.$1)) + "" : - computed ? "1" : ""; - }, - - set: function (elem, value) { - var style = elem.style, - currentStyle = elem.currentStyle, - opacity = jQuery.isNumeric(value) ? "alpha(opacity=" + value * 100 + ")" : "", - filter = currentStyle && currentStyle.filter || style.filter || ""; - - // IE has trouble with opacity if it does not have layout - // Force it by setting the zoom level - style.zoom = 1; - - // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 - // if value === "", then remove inline opacity #12685 - if ((value >= 1 || value === "") && - jQuery.trim(filter.replace(ralpha, "")) === "" && - style.removeAttribute) { - - // Setting style.filter to null, "" & " " still leave "filter:" in the cssText - // if "filter:" is present at all, clearType is disabled, we want to avoid this - // style.removeAttribute is IE Only, but so apparently is this code path... - style.removeAttribute("filter"); - - // if there is no filter style applied in a css rule or unset inline opacity, we are done - if (value === "" || currentStyle && !currentStyle.filter) { - return; - } - } - - // otherwise, set new filter values - style.filter = ralpha.test(filter) ? - filter.replace(ralpha, opacity) : - filter + " " + opacity; - } - }; - } - - jQuery.cssHooks.marginRight = addGetHookIf(support.reliableMarginRight, - function (elem, computed) { - if (computed) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap(elem, { "display": "inline-block" }, - curCSS, [elem, "marginRight"]); - } - } - ); - - // These hooks are used by animate to expand properties - jQuery.each({ - margin: "", - padding: "", - border: "Width" - }, function (prefix, suffix) { - jQuery.cssHooks[prefix + suffix] = { - expand: function (value) { - var i = 0, - expanded = {}, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [value]; - - for (; i < 4; i++) { - expanded[prefix + cssExpand[i] + suffix] = - parts[i] || parts[i - 2] || parts[0]; - } - - return expanded; - } - }; - - if (!rmargin.test(prefix)) { - jQuery.cssHooks[prefix + suffix].set = setPositiveNumber; - } - }); - - jQuery.fn.extend({ - css: function (name, value) { - return access(this, function (elem, name, value) { - var styles, len, - map = {}, - i = 0; - - if (jQuery.isArray(name)) { - styles = getStyles(elem); - len = name.length; - - for (; i < len; i++) { - map[name[i]] = jQuery.css(elem, name[i], false, styles); - } - - return map; - } - - return value !== undefined ? - jQuery.style(elem, name, value) : - jQuery.css(elem, name); - }, name, value, arguments.length > 1); - }, - show: function () { - return showHide(this, true); - }, - hide: function () { - return showHide(this); - }, - toggle: function (state) { - if (typeof state === "boolean") { - return state ? this.show() : this.hide(); - } - - return this.each(function () { - if (isHidden(this)) { - jQuery(this).show(); - } else { - jQuery(this).hide(); - } - }); - } - }); - - - function Tween(elem, options, prop, end, easing) { - return new Tween.prototype.init(elem, options, prop, end, easing); - } - jQuery.Tween = Tween; - - Tween.prototype = { - constructor: Tween, - init: function (elem, options, prop, end, easing, unit) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || (jQuery.cssNumber[prop] ? "" : "px"); - }, - cur: function () { - var hooks = Tween.propHooks[this.prop]; - - return hooks && hooks.get ? - hooks.get(this) : - Tween.propHooks._default.get(this); - }, - run: function (percent) { - var eased, - hooks = Tween.propHooks[this.prop]; - - if (this.options.duration) { - this.pos = eased = jQuery.easing[this.easing]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = (this.end - this.start) * eased + this.start; - - if (this.options.step) { - this.options.step.call(this.elem, this.now, this); - } - - if (hooks && hooks.set) { - hooks.set(this); - } else { - Tween.propHooks._default.set(this); - } - return this; - } - }; - - Tween.prototype.init.prototype = Tween.prototype; - - Tween.propHooks = { - _default: { - get: function (tween) { - var result; - - if (tween.elem[tween.prop] != null && - (!tween.elem.style || tween.elem.style[tween.prop] == null)) { - return tween.elem[tween.prop]; - } - - // passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css(tween.elem, tween.prop, ""); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function (tween) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if (jQuery.fx.step[tween.prop]) { - jQuery.fx.step[tween.prop](tween); - } else if (tween.elem.style && (tween.elem.style[jQuery.cssProps[tween.prop]] != null || jQuery.cssHooks[tween.prop])) { - jQuery.style(tween.elem, tween.prop, tween.now + tween.unit); - } else { - tween.elem[tween.prop] = tween.now; - } - } - } - }; - - // Support: IE <=9 - // Panic based approach to setting things on disconnected nodes - - Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function (tween) { - if (tween.elem.nodeType && tween.elem.parentNode) { - tween.elem[tween.prop] = tween.now; - } - } - }; - - jQuery.easing = { - linear: function (p) { - return p; - }, - swing: function (p) { - return 0.5 - Math.cos(p * Math.PI) / 2; - } - }; - - jQuery.fx = Tween.prototype.init; - - // Back Compat <1.8 extension point - jQuery.fx.step = {}; - - - - - var - fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp("^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i"), - rrun = /queueHooks$/, - animationPrefilters = [defaultPrefilter], - tweeners = { - "*": [function (prop, value) { - var tween = this.createTween(prop, value), - target = tween.cur(), - parts = rfxnum.exec(value), - unit = parts && parts[3] || (jQuery.cssNumber[prop] ? "" : "px"), - - // Starting value computation is required for potential unit mismatches - start = (jQuery.cssNumber[prop] || unit !== "px" && +target) && - rfxnum.exec(jQuery.css(tween.elem, prop)), - scale = 1, - maxIterations = 20; - - if (start && start[3] !== unit) { - // Trust units reported by jQuery.css - unit = unit || start[3]; - - // Make sure we update the tween properties later on - parts = parts || []; - - // Iteratively approximate from a nonzero starting point - start = +target || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style(tween.elem, prop, start + unit); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while (scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations); - } - - // Update tween properties - if (parts) { - start = tween.start = +start || +target || 0; - tween.unit = unit; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[1] ? - start + (parts[1] + 1) * parts[2] : - +parts[2]; - } - - return tween; - }] - }; - - // Animations created synchronously will run synchronously - function createFxNow() { - setTimeout(function () { - fxNow = undefined; - }); - return (fxNow = jQuery.now()); - } - - // Generate parameters to create a standard animation - function genFx(type, includeWidth) { - var which, - attrs = { height: type }, - i = 0; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for (; i < 4; i += 2 - includeWidth) { - which = cssExpand[i]; - attrs["margin" + which] = attrs["padding" + which] = type; - } - - if (includeWidth) { - attrs.opacity = attrs.width = type; - } - - return attrs; - } - - function createTween(value, prop, animation) { - var tween, - collection = (tweeners[prop] || []).concat(tweeners["*"]), - index = 0, - length = collection.length; - for (; index < length; index++) { - if ((tween = collection[index].call(animation, prop, value))) { - - // we're done with this property - return tween; - } - } - } - - function defaultPrefilter(elem, props, opts) { - /* jshint validthis: true */ - var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHidden(elem), - dataShow = jQuery._data(elem, "fxshow"); - - // handle queue: false promises - if (!opts.queue) { - hooks = jQuery._queueHooks(elem, "fx"); - if (hooks.unqueued == null) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function () { - if (!hooks.unqueued) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function () { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function () { - hooks.unqueued--; - if (!jQuery.queue(elem, "fx").length) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if (elem.nodeType === 1 && ("height" in props || "width" in props)) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE does not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [style.overflow, style.overflowX, style.overflowY]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - display = jQuery.css(elem, "display"); - - // Test default display if display is currently "none" - checkDisplay = display === "none" ? - jQuery._data(elem, "olddisplay") || defaultDisplay(elem.nodeName) : display; - - if (checkDisplay === "inline" && jQuery.css(elem, "float") === "none") { - - // inline-level elements accept inline-block; - // block-level elements need to be inline with layout - if (!support.inlineBlockNeedsLayout || defaultDisplay(elem.nodeName) === "inline") { - style.display = "inline-block"; - } else { - style.zoom = 1; - } - } - } - - if (opts.overflow) { - style.overflow = "hidden"; - if (!support.shrinkWrapBlocks()) { - anim.always(function () { - style.overflow = opts.overflow[0]; - style.overflowX = opts.overflow[1]; - style.overflowY = opts.overflow[2]; - }); - } - } - - // show/hide pass - for (prop in props) { - value = props[prop]; - if (rfxtypes.exec(value)) { - delete props[prop]; - toggle = toggle || value === "toggle"; - if (value === (hidden ? "hide" : "show")) { - - // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden - if (value === "show" && dataShow && dataShow[prop] !== undefined) { - hidden = true; - } else { - continue; - } - } - orig[prop] = dataShow && dataShow[prop] || jQuery.style(elem, prop); - - // Any non-fx value stops us from restoring the original display value - } else { - display = undefined; - } - } - - if (!jQuery.isEmptyObject(orig)) { - if (dataShow) { - if ("hidden" in dataShow) { - hidden = dataShow.hidden; - } - } else { - dataShow = jQuery._data(elem, "fxshow", {}); - } - - // store state if its toggle - enables .stop().toggle() to "reverse" - if (toggle) { - dataShow.hidden = !hidden; - } - if (hidden) { - jQuery(elem).show(); - } else { - anim.done(function () { - jQuery(elem).hide(); - }); - } - anim.done(function () { - var prop; - jQuery._removeData(elem, "fxshow"); - for (prop in orig) { - jQuery.style(elem, prop, orig[prop]); - } - }); - for (prop in orig) { - tween = createTween(hidden ? dataShow[prop] : 0, prop, anim); - - if (!(prop in dataShow)) { - dataShow[prop] = tween.start; - if (hidden) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - - // If this is a noop like .hide().hide(), restore an overwritten display value - } else if ((display === "none" ? defaultDisplay(elem.nodeName) : display) === "inline") { - style.display = display; - } - } - - function propFilter(props, specialEasing) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for (index in props) { - name = jQuery.camelCase(index); - easing = specialEasing[name]; - value = props[index]; - if (jQuery.isArray(value)) { - easing = value[1]; - value = props[index] = value[0]; - } - - if (index !== name) { - props[name] = value; - delete props[index]; - } - - hooks = jQuery.cssHooks[name]; - if (hooks && "expand" in hooks) { - value = hooks.expand(value); - delete props[name]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for (index in value) { - if (!(index in props)) { - props[index] = value[index]; - specialEasing[index] = easing; - } - } - } else { - specialEasing[name] = easing; - } - } - } - - function Animation(elem, properties, options) { - var result, - stopped, - index = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always(function () { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function () { - if (stopped) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max(0, animation.startTime + animation.duration - currentTime), - // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for (; index < length; index++) { - animation.tweens[index].run(percent); - } - - deferred.notifyWith(elem, [animation, percent, remaining]); - - if (percent < 1 && length) { - return remaining; - } else { - deferred.resolveWith(elem, [animation]); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend({}, properties), - opts: jQuery.extend(true, { specialEasing: {} }, options), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function (prop, end) { - var tween = jQuery.Tween(elem, animation.opts, prop, end, - animation.opts.specialEasing[prop] || animation.opts.easing); - animation.tweens.push(tween); - return tween; - }, - stop: function (gotoEnd) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if (stopped) { - return this; - } - stopped = true; - for (; index < length; index++) { - animation.tweens[index].run(1); - } - - // resolve when we played the last frame - // otherwise, reject - if (gotoEnd) { - deferred.resolveWith(elem, [animation, gotoEnd]); - } else { - deferred.rejectWith(elem, [animation, gotoEnd]); - } - return this; - } - }), - props = animation.props; - - propFilter(props, animation.opts.specialEasing); - - for (; index < length; index++) { - result = animationPrefilters[index].call(animation, elem, props, animation.opts); - if (result) { - return result; - } - } - - jQuery.map(props, createTween, animation); - - if (jQuery.isFunction(animation.opts.start)) { - animation.opts.start.call(elem, animation); - } - - jQuery.fx.timer( - jQuery.extend(tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - }) - ); - - // attach callbacks from options - return animation.progress(animation.opts.progress) - .done(animation.opts.done, animation.opts.complete) - .fail(animation.opts.fail) - .always(animation.opts.always); - } - - jQuery.Animation = jQuery.extend(Animation, { - tweener: function (props, callback) { - if (jQuery.isFunction(props)) { - callback = props; - props = ["*"]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for (; index < length; index++) { - prop = props[index]; - tweeners[prop] = tweeners[prop] || []; - tweeners[prop].unshift(callback); - } - }, - - prefilter: function (callback, prepend) { - if (prepend) { - animationPrefilters.unshift(callback); - } else { - animationPrefilters.push(callback); - } - } - }); - - jQuery.speed = function (speed, easing, fn) { - var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { - complete: fn || !fn && easing || - jQuery.isFunction(speed) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction(easing) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if (opt.queue == null || opt.queue === true) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function () { - if (jQuery.isFunction(opt.old)) { - opt.old.call(this); - } - - if (opt.queue) { - jQuery.dequeue(this, opt.queue); - } - }; - - return opt; - }; - - jQuery.fn.extend({ - fadeTo: function (speed, to, easing, callback) { - - // show any hidden elements after setting opacity to 0 - return this.filter(isHidden).css("opacity", 0).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback); - }, - animate: function (prop, speed, easing, callback) { - var empty = jQuery.isEmptyObject(prop), - optall = jQuery.speed(speed, easing, callback), - doAnimation = function () { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation(this, jQuery.extend({}, prop), optall); - - // Empty animations, or finishing resolves immediately - if (empty || jQuery._data(this, "finish")) { - anim.stop(true); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each(doAnimation) : - this.queue(optall.queue, doAnimation); - }, - stop: function (type, clearQueue, gotoEnd) { - var stopQueue = function (hooks) { - var stop = hooks.stop; - delete hooks.stop; - stop(gotoEnd); - }; - - if (typeof type !== "string") { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if (clearQueue && type !== false) { - this.queue(type || "fx", []); - } - - return this.each(function () { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = jQuery._data(this); - - if (index) { - if (data[index] && data[index].stop) { - stopQueue(data[index]); - } - } else { - for (index in data) { - if (data[index] && data[index].stop && rrun.test(index)) { - stopQueue(data[index]); - } - } - } - - for (index = timers.length; index--;) { - if (timers[index].elem === this && (type == null || timers[index].queue === type)) { - timers[index].anim.stop(gotoEnd); - dequeue = false; - timers.splice(index, 1); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if (dequeue || !gotoEnd) { - jQuery.dequeue(this, type); - } - }); - }, - finish: function (type) { - if (type !== false) { - type = type || "fx"; - } - return this.each(function () { - var index, - data = jQuery._data(this), - queue = data[type + "queue"], - hooks = data[type + "queueHooks"], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // enable finishing flag on private data - data.finish = true; - - // empty the queue first - jQuery.queue(this, type, []); - - if (hooks && hooks.stop) { - hooks.stop.call(this, true); - } - - // look for any active animations, and finish them - for (index = timers.length; index--;) { - if (timers[index].elem === this && timers[index].queue === type) { - timers[index].anim.stop(true); - timers.splice(index, 1); - } - } - - // look for any animations in the old queue and finish them - for (index = 0; index < length; index++) { - if (queue[index] && queue[index].finish) { - queue[index].finish.call(this); - } - } - - // turn off finishing flag - delete data.finish; - }); - } - }); - - jQuery.each(["toggle", "show", "hide"], function (i, name) { - var cssFn = jQuery.fn[name]; - jQuery.fn[name] = function (speed, easing, callback) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply(this, arguments) : - this.animate(genFx(name, true), speed, easing, callback); - }; - }); - - // Generate shortcuts for custom animations - jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } - }, function (name, props) { - jQuery.fn[name] = function (speed, easing, callback) { - return this.animate(props, speed, easing, callback); - }; - }); - - jQuery.timers = []; - jQuery.fx.tick = function () { - var timer, - timers = jQuery.timers, - i = 0; - - fxNow = jQuery.now(); - - for (; i < timers.length; i++) { - timer = timers[i]; - // Checks the timer has not already been removed - if (!timer() && timers[i] === timer) { - timers.splice(i--, 1); - } - } - - if (!timers.length) { - jQuery.fx.stop(); - } - fxNow = undefined; - }; - - jQuery.fx.timer = function (timer) { - jQuery.timers.push(timer); - if (timer()) { - jQuery.fx.start(); - } else { - jQuery.timers.pop(); - } - }; - - jQuery.fx.interval = 13; - - jQuery.fx.start = function () { - if (!timerId) { - timerId = setInterval(jQuery.fx.tick, jQuery.fx.interval); - } - }; - - jQuery.fx.stop = function () { - clearInterval(timerId); - timerId = null; - }; - - jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 - }; - - - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - jQuery.fn.delay = function (time, type) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue(type, function (next, hooks) { - var timeout = setTimeout(next, time); - hooks.stop = function () { - clearTimeout(timeout); - }; - }); - }; - - - (function () { - // Minified: var a,b,c,d,e - var input, div, select, a, opt; - - // Setup - div = document.createElement("div"); - div.setAttribute("className", "t"); - div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; - a = div.getElementsByTagName("a")[0]; - - // First batch of tests. - select = document.createElement("select"); - opt = select.appendChild(document.createElement("option")); - input = div.getElementsByTagName("input")[0]; - - a.style.cssText = "top:1px"; - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - support.getSetAttribute = div.className !== "t"; - - // Get the style information from getAttribute - // (IE uses .cssText instead) - support.style = /top/.test(a.getAttribute("style")); - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - support.hrefNormalized = a.getAttribute("href") === "/a"; - - // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) - support.checkOn = !!input.value; - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - support.optSelected = opt.selected; - - // Tests for enctype support on a form (#6743) - support.enctype = !!document.createElement("form").enctype; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Support: IE8 only - // Check if we can trust getAttribute("value") - input = document.createElement("input"); - input.setAttribute("value", ""); - support.input = input.getAttribute("value") === ""; - - // Check if an input maintains its value after becoming a radio - input.value = "t"; - input.setAttribute("type", "radio"); - support.radioValue = input.value === "t"; - })(); - - - var rreturn = /\r/g; - - jQuery.fn.extend({ - val: function (value) { - var hooks, ret, isFunction, - elem = this[0]; - - if (!arguments.length) { - if (elem) { - hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()]; - - if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction(value); - - return this.each(function (i) { - var val; - - if (this.nodeType !== 1) { - return; - } - - if (isFunction) { - val = value.call(this, i, jQuery(this).val()); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if (val == null) { - val = ""; - } else if (typeof val === "number") { - val += ""; - } else if (jQuery.isArray(val)) { - val = jQuery.map(val, function (value) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()]; - - // If set returns undefined, fall back to normal setting - if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined) { - this.value = val; - } - }); - } - }); - - jQuery.extend({ - valHooks: { - option: { - get: function (elem) { - var val = jQuery.find.attr(elem, "value"); - return val != null ? - val : - // Support: IE10-11+ - // option.text throws exceptions (#14686, #14858) - jQuery.trim(jQuery.text(elem)); - } - }, - select: { - get: function (elem) { - var value, option, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one" || index < 0, - values = one ? null : [], - max = one ? index + 1 : options.length, - i = index < 0 ? - max : - one ? index : 0; - - // Loop through all the selected options - for (; i < max; i++) { - option = options[i]; - - // oldIE doesn't update selected after form reset (#2551) - if ((option.selected || i === index) && - // Don't return options that are disabled or in a disabled optgroup - (support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, "optgroup"))) { - - // Get the specific value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if (one) { - return value; - } - - // Multi-Selects return an array - values.push(value); - } - } - - return values; - }, - - set: function (elem, value) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray(value), - i = options.length; - - while (i--) { - option = options[i]; - - if (jQuery.inArray(jQuery.valHooks.option.get(option), values) >= 0) { - - // Support: IE6 - // When new option element is added to select box we need to - // force reflow of newly added node in order to workaround delay - // of initialization properties - try { - option.selected = optionSet = true; - - } catch (_) { - - // Will be executed only in IE6 - option.scrollHeight; - } - - } else { - option.selected = false; - } - } - - // Force browsers to behave consistently when non-matching value is set - if (!optionSet) { - elem.selectedIndex = -1; - } - - return options; - } - } - } - }); - - // Radios and checkboxes getter/setter - jQuery.each(["radio", "checkbox"], function () { - jQuery.valHooks[this] = { - set: function (elem, value) { - if (jQuery.isArray(value)) { - return (elem.checked = jQuery.inArray(jQuery(elem).val(), value) >= 0); - } - } - }; - if (!support.checkOn) { - jQuery.valHooks[this].get = function (elem) { - // Support: Webkit - // "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - }; - } - }); - - - - - var nodeHook, boolHook, - attrHandle = jQuery.expr.attrHandle, - ruseDefault = /^(?:checked|selected)$/i, - getSetAttribute = support.getSetAttribute, - getSetInput = support.input; - - jQuery.fn.extend({ - attr: function (name, value) { - return access(this, jQuery.attr, name, value, arguments.length > 1); - }, - - removeAttr: function (name) { - return this.each(function () { - jQuery.removeAttr(this, name); - }); - } - }); - - jQuery.extend({ - attr: function (elem, name, value) { - var hooks, ret, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if (!elem || nType === 3 || nType === 8 || nType === 2) { - return; - } - - // Fallback to prop when attributes are not supported - if (typeof elem.getAttribute === strundefined) { - return jQuery.prop(elem, name, value); - } - - // All attributes are lowercase - // Grab necessary hook if one is defined - if (nType !== 1 || !jQuery.isXMLDoc(elem)) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[name] || - (jQuery.expr.match.bool.test(name) ? boolHook : nodeHook); - } - - if (value !== undefined) { - - if (value === null) { - jQuery.removeAttr(elem, name); - - } else if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) { - return ret; - - } else { - elem.setAttribute(name, value + ""); - return value; - } - - } else if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) { - return ret; - - } else { - ret = jQuery.find.attr(elem, name); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; - } - }, - - removeAttr: function (elem, value) { - var name, propName, - i = 0, - attrNames = value && value.match(rnotwhite); - - if (attrNames && elem.nodeType === 1) { - while ((name = attrNames[i++])) { - propName = jQuery.propFix[name] || name; - - // Boolean attributes get special treatment (#10870) - if (jQuery.expr.match.bool.test(name)) { - // Set corresponding property to false - if (getSetInput && getSetAttribute || !ruseDefault.test(name)) { - elem[propName] = false; - // Support: IE<9 - // Also clear defaultChecked/defaultSelected (if appropriate) - } else { - elem[jQuery.camelCase("default-" + name)] = - elem[propName] = false; - } - - // See #9699 for explanation of this approach (setting first, then removal) - } else { - jQuery.attr(elem, name, ""); - } - - elem.removeAttribute(getSetAttribute ? name : propName); - } - } - }, - - attrHooks: { - type: { - set: function (elem, value) { - if (!support.radioValue && value === "radio" && jQuery.nodeName(elem, "input")) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute("type", value); - if (val) { - elem.value = val; - } - return value; - } - } - } - } - }); - - // Hook for boolean attributes - boolHook = { - set: function (elem, value, name) { - if (value === false) { - // Remove boolean attributes when set to false - jQuery.removeAttr(elem, name); - } else if (getSetInput && getSetAttribute || !ruseDefault.test(name)) { - // IE<8 needs the *property* name - elem.setAttribute(!getSetAttribute && jQuery.propFix[name] || name, name); - - // Use defaultChecked and defaultSelected for oldIE - } else { - elem[jQuery.camelCase("default-" + name)] = elem[name] = true; - } - - return name; - } - }; - - // Retrieve booleans specially - jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), function (i, name) { - - var getter = attrHandle[name] || jQuery.find.attr; - - attrHandle[name] = getSetInput && getSetAttribute || !ruseDefault.test(name) ? - function (elem, name, isXML) { - var ret, handle; - if (!isXML) { - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[name]; - attrHandle[name] = ret; - ret = getter(elem, name, isXML) != null ? - name.toLowerCase() : - null; - attrHandle[name] = handle; - } - return ret; - } : - function (elem, name, isXML) { - if (!isXML) { - return elem[jQuery.camelCase("default-" + name)] ? - name.toLowerCase() : - null; - } - }; - }); - - // fix oldIE attroperties - if (!getSetInput || !getSetAttribute) { - jQuery.attrHooks.value = { - set: function (elem, value, name) { - if (jQuery.nodeName(elem, "input")) { - // Does not return so that setAttribute is also used - elem.defaultValue = value; - } else { - // Use nodeHook if defined (#1954); otherwise setAttribute is fine - return nodeHook && nodeHook.set(elem, value, name); - } - } - }; - } - - // IE6/7 do not support getting/setting some attributes with get/setAttribute - if (!getSetAttribute) { - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = { - set: function (elem, value, name) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode(name); - if (!ret) { - elem.setAttributeNode( - (ret = elem.ownerDocument.createAttribute(name)) - ); - } - - ret.value = value += ""; - - // Break association with cloned elements by also using setAttribute (#9646) - if (name === "value" || value === elem.getAttribute(name)) { - return value; - } - } - }; - - // Some attributes are constructed with empty-string values when not defined - attrHandle.id = attrHandle.name = attrHandle.coords = - function (elem, name, isXML) { - var ret; - if (!isXML) { - return (ret = elem.getAttributeNode(name)) && ret.value !== "" ? - ret.value : - null; - } - }; - - // Fixing value retrieval on a button requires this module - jQuery.valHooks.button = { - get: function (elem, name) { - var ret = elem.getAttributeNode(name); - if (ret && ret.specified) { - return ret.value; - } - }, - set: nodeHook.set - }; - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - set: function (elem, value, name) { - nodeHook.set(elem, value === "" ? false : value, name); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each(["width", "height"], function (i, name) { - jQuery.attrHooks[name] = { - set: function (elem, value) { - if (value === "") { - elem.setAttribute(name, "auto"); - return value; - } - } - }; - }); - } - - if (!support.style) { - jQuery.attrHooks.style = { - get: function (elem) { - // Return undefined in the case of empty string - // Note: IE uppercases css property names, but if we were to .toLowerCase() - // .cssText, that would destroy case senstitivity in URL's, like in "background" - return elem.style.cssText || undefined; - }, - set: function (elem, value) { - return (elem.style.cssText = value + ""); - } - }; - } - - - - - var rfocusable = /^(?:input|select|textarea|button|object)$/i, - rclickable = /^(?:a|area)$/i; - - jQuery.fn.extend({ - prop: function (name, value) { - return access(this, jQuery.prop, name, value, arguments.length > 1); - }, - - removeProp: function (name) { - name = jQuery.propFix[name] || name; - return this.each(function () { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[name] = undefined; - delete this[name]; - } catch (e) { } - }); - } - }); - - jQuery.extend({ - propFix: { - "for": "htmlFor", - "class": "className" - }, - - prop: function (elem, name, value) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if (!elem || nType === 3 || nType === 8 || nType === 2) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc(elem); - - if (notxml) { - // Fix name and attach hooks - name = jQuery.propFix[name] || name; - hooks = jQuery.propHooks[name]; - } - - if (value !== undefined) { - return hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined ? - ret : - (elem[name] = value); - - } else { - return hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null ? - ret : - elem[name]; - } - }, - - propHooks: { - tabIndex: { - get: function (elem) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr(elem, "tabindex"); - - return tabindex ? - parseInt(tabindex, 10) : - rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href ? - 0 : - -1; - } - } - } - }); - - // Some attributes require a special call on IE - // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx - if (!support.hrefNormalized) { - // href/src property should get the full normalized URL (#10299/#12915) - jQuery.each(["href", "src"], function (i, name) { - jQuery.propHooks[name] = { - get: function (elem) { - return elem.getAttribute(name, 4); - } - }; - }); - } - - // Support: Safari, IE9+ - // mis-reports the default selected property of an option - // Accessing the parent's selectedIndex property fixes it - if (!support.optSelected) { - jQuery.propHooks.selected = { - get: function (elem) { - var parent = elem.parentNode; - - if (parent) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if (parent.parentNode) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }; - } - - jQuery.each([ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" - ], function () { - jQuery.propFix[this.toLowerCase()] = this; - }); - - // IE6/7 call enctype encoding - if (!support.enctype) { - jQuery.propFix.enctype = "encoding"; - } - - - - - var rclass = /[\t\r\n\f]/g; - - jQuery.fn.extend({ - addClass: function (value) { - var classes, elem, cur, clazz, j, finalValue, - i = 0, - len = this.length, - proceed = typeof value === "string" && value; - - if (jQuery.isFunction(value)) { - return this.each(function (j) { - jQuery(this).addClass(value.call(this, j, this.className)); - }); - } - - if (proceed) { - // The disjunction here is for better compressibility (see removeClass) - classes = (value || "").match(rnotwhite) || []; - - for (; i < len; i++) { - elem = this[i]; - cur = elem.nodeType === 1 && (elem.className ? - (" " + elem.className + " ").replace(rclass, " ") : - " " - ); - - if (cur) { - j = 0; - while ((clazz = classes[j++])) { - if (cur.indexOf(" " + clazz + " ") < 0) { - cur += clazz + " "; - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = jQuery.trim(cur); - if (elem.className !== finalValue) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - removeClass: function (value) { - var classes, elem, cur, clazz, j, finalValue, - i = 0, - len = this.length, - proceed = arguments.length === 0 || typeof value === "string" && value; - - if (jQuery.isFunction(value)) { - return this.each(function (j) { - jQuery(this).removeClass(value.call(this, j, this.className)); - }); - } - if (proceed) { - classes = (value || "").match(rnotwhite) || []; - - for (; i < len; i++) { - elem = this[i]; - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && (elem.className ? - (" " + elem.className + " ").replace(rclass, " ") : - "" - ); - - if (cur) { - j = 0; - while ((clazz = classes[j++])) { - // Remove *all* instances - while (cur.indexOf(" " + clazz + " ") >= 0) { - cur = cur.replace(" " + clazz + " ", " "); - } - } - - // only assign if different to avoid unneeded rendering. - finalValue = value ? jQuery.trim(cur) : ""; - if (elem.className !== finalValue) { - elem.className = finalValue; - } - } - } - } - - return this; - }, - - toggleClass: function (value, stateVal) { - var type = typeof value; - - if (typeof stateVal === "boolean" && type === "string") { - return stateVal ? this.addClass(value) : this.removeClass(value); - } - - if (jQuery.isFunction(value)) { - return this.each(function (i) { - jQuery(this).toggleClass(value.call(this, i, this.className, stateVal), stateVal); - }); - } - - return this.each(function () { - if (type === "string") { - // toggle individual class names - var className, - i = 0, - self = jQuery(this), - classNames = value.match(rnotwhite) || []; - - while ((className = classNames[i++])) { - // check each className given, space separated list - if (self.hasClass(className)) { - self.removeClass(className); - } else { - self.addClass(className); - } - } - - // Toggle whole class name - } else if (type === strundefined || type === "boolean") { - if (this.className) { - // store className if set - jQuery._data(this, "__className__", this.className); - } - - // If the element has a class name or if we're passed "false", - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - this.className = this.className || value === false ? "" : jQuery._data(this, "__className__") || ""; - } - }); - }, - - hasClass: function (selector) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for (; i < l; i++) { - if (this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf(className) >= 0) { - return true; - } - } - - return false; - } - }); - - - - - // Return jQuery for attributes-only inclusion - - - jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function (i, name) { - - // Handle event binding - jQuery.fn[name] = function (data, fn) { - return arguments.length > 0 ? - this.on(name, null, data, fn) : - this.trigger(name); - }; - }); - - jQuery.fn.extend({ - hover: function (fnOver, fnOut) { - return this.mouseenter(fnOver).mouseleave(fnOut || fnOver); - }, - - bind: function (types, data, fn) { - return this.on(types, null, data, fn); - }, - unbind: function (types, fn) { - return this.off(types, null, fn); - }, - - delegate: function (selector, types, data, fn) { - return this.on(types, selector, data, fn); - }, - undelegate: function (selector, types, fn) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn); - } - }); - - - var nonce = jQuery.now(); - - var rquery = (/\?/); - - - - var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g; - - jQuery.parseJSON = function (data) { - // Attempt to parse using the native JSON parser first - if (window.JSON && window.JSON.parse) { - // Support: Android 2.3 - // Workaround failure to string-cast null input - return window.JSON.parse(data + ""); - } - - var requireNonComma, - depth = null, - str = jQuery.trim(data + ""); - - // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains - // after removing valid tokens - return str && !jQuery.trim(str.replace(rvalidtokens, function (token, comma, open, close) { - - // Force termination if we see a misplaced comma - if (requireNonComma && comma) { - depth = 0; - } - - // Perform no more replacements after returning to outermost depth - if (depth === 0) { - return token; - } - - // Commas must not follow "[", "{", or "," - requireNonComma = open || comma; - - // Determine new depth - // array/object open ("[" or "{"): depth += true - false (increment) - // array/object close ("]" or "}"): depth += false - true (decrement) - // other cases ("," or primitive): depth += true - true (numeric cast) - depth += !close - !open; - - // Remove this token - return ""; - })) ? - (Function("return " + str))() : - jQuery.error("Invalid JSON: " + data); - }; - - - // Cross-browser xml parsing - jQuery.parseXML = function (data) { - var xml, tmp; - if (!data || typeof data !== "string") { - return null; - } - try { - if (window.DOMParser) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString(data, "text/xml"); - } else { // IE - xml = new ActiveXObject("Microsoft.XMLDOM"); - xml.async = "false"; - xml.loadXML(data); - } - } catch (e) { - xml = undefined; - } - if (!xml || !xml.documentElement || xml.getElementsByTagName("parsererror").length) { - jQuery.error("Invalid XML: " + data); - } - return xml; - }; - - - var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rts = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat("*"); - - // #8138, IE may throw an exception when accessing - // a field from window.location if document.domain has been set - try { - ajaxLocation = location.href; - } catch (e) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement("a"); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; - } - - // Segment location into parts - ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || []; - - // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport - function addToPrefiltersOrTransports(structure) { - - // dataTypeExpression is optional and defaults to "*" - return function (dataTypeExpression, func) { - - if (typeof dataTypeExpression !== "string") { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match(rnotwhite) || []; - - if (jQuery.isFunction(func)) { - // For each dataType in the dataTypeExpression - while ((dataType = dataTypes[i++])) { - // Prepend if requested - if (dataType.charAt(0) === "+") { - dataType = dataType.slice(1) || "*"; - (structure[dataType] = structure[dataType] || []).unshift(func); - - // Otherwise append - } else { - (structure[dataType] = structure[dataType] || []).push(func); - } - } - } - }; - } - - // Base inspection function for prefilters and transports - function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) { - - var inspected = {}, - seekingTransport = (structure === transports); - - function inspect(dataType) { - var selected; - inspected[dataType] = true; - jQuery.each(structure[dataType] || [], function (_, prefilterOrFactory) { - var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR); - if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) { - options.dataTypes.unshift(dataTypeOrTransport); - inspect(dataTypeOrTransport); - return false; - } else if (seekingTransport) { - return !(selected = dataTypeOrTransport); - } - }); - return selected; - } - - return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*"); - } - - // A special extend for ajax options - // that takes "flat" options (not to be deep extended) - // Fixes #9887 - function ajaxExtend(target, src) { - var deep, key, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for (key in src) { - if (src[key] !== undefined) { - (flatOptions[key] ? target : (deep || (deep = {})))[key] = src[key]; - } - } - if (deep) { - jQuery.extend(true, target, deep); - } - - return target; - } - - /* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ - function ajaxHandleResponses(s, jqXHR, responses) { - var firstDataType, ct, finalDataType, type, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while (dataTypes[0] === "*") { - dataTypes.shift(); - if (ct === undefined) { - ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); - } - } - - // Check if we're dealing with a known content-type - if (ct) { - for (type in contents) { - if (contents[type] && contents[type].test(ct)) { - dataTypes.unshift(type); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if (dataTypes[0] in responses) { - finalDataType = dataTypes[0]; - } else { - // Try convertible dataTypes - for (type in responses) { - if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) { - finalDataType = type; - break; - } - if (!firstDataType) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if (finalDataType) { - if (finalDataType !== dataTypes[0]) { - dataTypes.unshift(finalDataType); - } - return responses[finalDataType]; - } - } - - /* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ - function ajaxConvert(s, response, jqXHR, isSuccess) { - var conv2, current, conv, tmp, prev, - converters = {}, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if (dataTypes[1]) { - for (conv in s.converters) { - converters[conv.toLowerCase()] = s.converters[conv]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while (current) { - - if (s.responseFields[current]) { - jqXHR[s.responseFields[current]] = response; - } - - // Apply the dataFilter if provided - if (!prev && isSuccess && s.dataFilter) { - response = s.dataFilter(response, s.dataType); - } - - prev = current; - current = dataTypes.shift(); - - if (current) { - - // There's only work to do if current dataType is non-auto - if (current === "*") { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if (prev !== "*" && prev !== current) { - - // Seek a direct converter - conv = converters[prev + " " + current] || converters["* " + current]; - - // If none found, seek a pair - if (!conv) { - for (conv2 in converters) { - - // If conv2 outputs current - tmp = conv2.split(" "); - if (tmp[1] === current) { - - // If prev can be converted to accepted input - conv = converters[prev + " " + tmp[0]] || - converters["* " + tmp[0]]; - if (conv) { - // Condense equivalence converters - if (conv === true) { - conv = converters[conv2]; - - // Otherwise, insert the intermediate dataType - } else if (converters[conv2] !== true) { - current = tmp[0]; - dataTypes.unshift(tmp[1]); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if (conv !== true) { - - // Unless errors are allowed to bubble, catch and return them - if (conv && s["throws"]) { - response = conv(response); - } else { - try { - response = conv(response); - } catch (e) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - } - } - - return { state: "success", data: response }; - } - - jQuery.extend({ - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: ajaxLocation, - type: "GET", - isLocal: rlocalProtocol.test(ajaxLocParts[1]), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function (target, settings) { - return settings ? - - // Building a settings object - ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) : - - // Extending ajaxSettings - ajaxExtend(jQuery.ajaxSettings, target); - }, - - ajaxPrefilter: addToPrefiltersOrTransports(prefilters), - ajaxTransport: addToPrefiltersOrTransports(transports), - - // Main method - ajax: function (url, options) { - - // If url is an object, simulate pre-1.5 signature - if (typeof url === "object") { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var // Cross-domain detection vars - parts, - // Loop variable - i, - // URL without anti-cache param - cacheURL, - // Response headers as string - responseHeadersString, - // timeout handle - timeoutTimer, - - // To know if global events are to be dispatched - fireGlobals, - - transport, - // Response headers - responseHeaders, - // Create the final options object - s = jQuery.ajaxSetup({}, options), - // Callbacks context - callbackContext = s.context || s, - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ? - jQuery(callbackContext) : - jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks("once memory"), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function (key) { - var match; - if (state === 2) { - if (!responseHeaders) { - responseHeaders = {}; - while ((match = rheaders.exec(responseHeadersString))) { - responseHeaders[match[1].toLowerCase()] = match[2]; - } - } - match = responseHeaders[key.toLowerCase()]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function () { - return state === 2 ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function (name, value) { - var lname = name.toLowerCase(); - if (!state) { - name = requestHeadersNames[lname] = requestHeadersNames[lname] || name; - requestHeaders[name] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function (type) { - if (!state) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function (map) { - var code; - if (map) { - if (state < 2) { - for (code in map) { - // Lazy-add the new callback in a way that preserves old ones - statusCode[code] = [statusCode[code], map[code]]; - } - } else { - // Execute the appropriate callbacks - jqXHR.always(map[jqXHR.status]); - } - } - return this; - }, - - // Cancel the request - abort: function (statusText) { - var finalText = statusText || strAbort; - if (transport) { - transport.abort(finalText); - } - done(0, finalText); - return this; - } - }; - - // Attach deferreds - deferred.promise(jqXHR).complete = completeDeferred.add; - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ((url || s.url || ajaxLocation) + "").replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//"); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().match(rnotwhite) || [""]; - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if (s.crossDomain == null) { - parts = rurl.exec(s.url.toLowerCase()); - s.crossDomain = !!(parts && - (parts[1] !== ajaxLocParts[1] || parts[2] !== ajaxLocParts[2] || - (parts[3] || (parts[1] === "http:" ? "80" : "443")) !== - (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? "80" : "443"))) - ); - } - - // Convert data if not already a string - if (s.data && s.processData && typeof s.data !== "string") { - s.data = jQuery.param(s.data, s.traditional); - } - - // Apply prefilters - inspectPrefiltersOrTransports(prefilters, s, options, jqXHR); - - // If request was aborted inside a prefilter, stop there - if (state === 2) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Watch for a new set of requests - if (fireGlobals && jQuery.active++ === 0) { - jQuery.event.trigger("ajaxStart"); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test(s.type); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - cacheURL = s.url; - - // More options handling for requests with no content - if (!s.hasContent) { - - // If data is available, append data to url - if (s.data) { - cacheURL = (s.url += (rquery.test(cacheURL) ? "&" : "?") + s.data); - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add anti-cache in url if needed - if (s.cache === false) { - s.url = rts.test(cacheURL) ? - - // If there is already a '_' parameter, set its value - cacheURL.replace(rts, "$1_=" + nonce++) : - - // Otherwise add one to the end - cacheURL + (rquery.test(cacheURL) ? "&" : "?") + "_=" + nonce++; - } - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if (s.ifModified) { - if (jQuery.lastModified[cacheURL]) { - jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[cacheURL]); - } - if (jQuery.etag[cacheURL]) { - jqXHR.setRequestHeader("If-None-Match", jQuery.etag[cacheURL]); - } - } - - // Set the correct header, if data is being sent - if (s.data && s.hasContent && s.contentType !== false || options.contentType) { - jqXHR.setRequestHeader("Content-Type", s.contentType); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? - s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") : - s.accepts["*"] - ); - - // Check for headers option - for (i in s.headers) { - jqXHR.setRequestHeader(i, s.headers[i]); - } - - // Allow custom headers/mimetypes and early abort - if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) { - // Abort if not done already and return - return jqXHR.abort(); - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for (i in { success: 1, error: 1, complete: 1 }) { - jqXHR[i](s[i]); - } - - // Get transport - transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR); - - // If no transport, we auto-abort - if (!transport) { - done(-1, "No Transport"); - } else { - jqXHR.readyState = 1; - - // Send global event - if (fireGlobals) { - globalEventContext.trigger("ajaxSend", [jqXHR, s]); - } - // Timeout - if (s.async && s.timeout > 0) { - timeoutTimer = setTimeout(function () { - jqXHR.abort("timeout"); - }, s.timeout); - } - - try { - state = 1; - transport.send(requestHeaders, done); - } catch (e) { - // Propagate exception as error if not done - if (state < 2) { - done(-1, e); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - // Callback for when everything is done - function done(status, nativeStatusText, responses, headers) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if (state === 2) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if (timeoutTimer) { - clearTimeout(timeoutTimer); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if (responses) { - response = ajaxHandleResponses(s, jqXHR, responses); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert(s, response, jqXHR, isSuccess); - - // If successful, handle type chaining - if (isSuccess) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if (s.ifModified) { - modified = jqXHR.getResponseHeader("Last-Modified"); - if (modified) { - jQuery.lastModified[cacheURL] = modified; - } - modified = jqXHR.getResponseHeader("etag"); - if (modified) { - jQuery.etag[cacheURL] = modified; - } - } - - // if no content - if (status === 204 || s.type === "HEAD") { - statusText = "nocontent"; - - // if not modified - } else if (status === 304) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if (status || !statusText) { - statusText = "error"; - if (status < 0) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = (nativeStatusText || statusText) + ""; - - // Success/Error - if (isSuccess) { - deferred.resolveWith(callbackContext, [success, statusText, jqXHR]); - } else { - deferred.rejectWith(callbackContext, [jqXHR, statusText, error]); - } - - // Status-dependent callbacks - jqXHR.statusCode(statusCode); - statusCode = undefined; - - if (fireGlobals) { - globalEventContext.trigger(isSuccess ? "ajaxSuccess" : "ajaxError", - [jqXHR, s, isSuccess ? success : error]); - } - - // Complete - completeDeferred.fireWith(callbackContext, [jqXHR, statusText]); - - if (fireGlobals) { - globalEventContext.trigger("ajaxComplete", [jqXHR, s]); - // Handle the global AJAX counter - if (!(--jQuery.active)) { - jQuery.event.trigger("ajaxStop"); - } - } - } - - return jqXHR; - }, - - getJSON: function (url, data, callback) { - return jQuery.get(url, data, callback, "json"); - }, - - getScript: function (url, callback) { - return jQuery.get(url, undefined, callback, "script"); - } - }); - - jQuery.each(["get", "post"], function (i, method) { - jQuery[method] = function (url, data, callback, type) { - // shift arguments if data argument was omitted - if (jQuery.isFunction(data)) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - url: url, - type: method, - dataType: type, - data: data, - success: callback - }); - }; - }); - - // Attach a bunch of functions for handling common AJAX events - jQuery.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function (i, type) { - jQuery.fn[type] = function (fn) { - return this.on(type, fn); - }; - }); - - - jQuery._evalUrl = function (url) { - return jQuery.ajax({ - url: url, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); - }; - - - jQuery.fn.extend({ - wrapAll: function (html) { - if (jQuery.isFunction(html)) { - return this.each(function (i) { - jQuery(this).wrapAll(html.call(this, i)); - }); - } - - if (this[0]) { - // The elements to wrap the target around - var wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true); - - if (this[0].parentNode) { - wrap.insertBefore(this[0]); - } - - wrap.map(function () { - var elem = this; - - while (elem.firstChild && elem.firstChild.nodeType === 1) { - elem = elem.firstChild; - } - - return elem; - }).append(this); - } - - return this; - }, - - wrapInner: function (html) { - if (jQuery.isFunction(html)) { - return this.each(function (i) { - jQuery(this).wrapInner(html.call(this, i)); - }); - } - - return this.each(function () { - var self = jQuery(this), - contents = self.contents(); - - if (contents.length) { - contents.wrapAll(html); - - } else { - self.append(html); - } - }); - }, - - wrap: function (html) { - var isFunction = jQuery.isFunction(html); - - return this.each(function (i) { - jQuery(this).wrapAll(isFunction ? html.call(this, i) : html); - }); - }, - - unwrap: function () { - return this.parent().each(function () { - if (!jQuery.nodeName(this, "body")) { - jQuery(this).replaceWith(this.childNodes); - } - }).end(); - } - }); - - - jQuery.expr.filters.hidden = function (elem) { - // Support: Opera <= 12.12 - // Opera reports offsetWidths and offsetHeights less than zero on some elements - return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 || - (!support.reliableHiddenOffsets() && - ((elem.style && elem.style.display) || jQuery.css(elem, "display")) === "none"); - }; - - jQuery.expr.filters.visible = function (elem) { - return !jQuery.expr.filters.hidden(elem); - }; - - - - - var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - - function buildParams(prefix, obj, traditional, add) { - var name; - - if (jQuery.isArray(obj)) { - // Serialize array item. - jQuery.each(obj, function (i, v) { - if (traditional || rbracket.test(prefix)) { - // Treat each array item as a scalar. - add(prefix, v); - - } else { - // Item is non-scalar (array or object), encode its numeric index. - buildParams(prefix + "[" + (typeof v === "object" ? i : "") + "]", v, traditional, add); - } - }); - - } else if (!traditional && jQuery.type(obj) === "object") { - // Serialize object item. - for (name in obj) { - buildParams(prefix + "[" + name + "]", obj[name], traditional, add); - } - - } else { - // Serialize scalar item. - add(prefix, obj); - } - } - - // Serialize an array of form elements or a set of - // key/values into a query string - jQuery.param = function (a, traditional) { - var prefix, - s = [], - add = function (key, value) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction(value) ? value() : (value == null ? "" : value); - s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if (traditional === undefined) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) { - // Serialize the form elements - jQuery.each(a, function () { - add(this.name, this.value); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for (prefix in a) { - buildParams(prefix, a[prefix], traditional, add); - } - } - - // Return the resulting serialization - return s.join("&").replace(r20, "+"); - }; - - jQuery.fn.extend({ - serialize: function () { - return jQuery.param(this.serializeArray()); - }, - serializeArray: function () { - return this.map(function () { - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop(this, "elements"); - return elements ? jQuery.makeArray(elements) : this; - }) - .filter(function () { - var type = this.type; - // Use .is(":disabled") so that fieldset[disabled] works - return this.name && !jQuery(this).is(":disabled") && - rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && - (this.checked || !rcheckableType.test(type)); - }) - .map(function (i, elem) { - var val = jQuery(this).val(); - - return val == null ? - null : - jQuery.isArray(val) ? - jQuery.map(val, function (val) { - return { name: elem.name, value: val.replace(rCRLF, "\r\n") }; - }) : - { name: elem.name, value: val.replace(rCRLF, "\r\n") }; - }).get(); - } - }); - - - // Create the request object - // (This is still attached to ajaxSettings for backward compatibility) - jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ? - // Support: IE6+ - function () { - - // XHR cannot access local files, always use ActiveX for that case - return !this.isLocal && - - // Support: IE7-8 - // oldIE XHR does not support non-RFC2616 methods (#13240) - // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx - // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9 - // Although this check for six methods instead of eight - // since IE also does not support "trace" and "connect" - /^(get|post|head|put|delete|options)$/i.test(this.type) && - - createStandardXHR() || createActiveXHR(); - } : - // For all other browsers, use the standard XMLHttpRequest object - createStandardXHR; - - var xhrId = 0, - xhrCallbacks = {}, - xhrSupported = jQuery.ajaxSettings.xhr(); - - // Support: IE<10 - // Open requests must be manually aborted on unload (#5280) - if (window.ActiveXObject) { - jQuery(window).on("unload", function () { - for (var key in xhrCallbacks) { - xhrCallbacks[key](undefined, true); - } - }); - } - - // Determine support properties - support.cors = !!xhrSupported && ("withCredentials" in xhrSupported); - xhrSupported = support.ajax = !!xhrSupported; - - // Create transport if the browser can provide an xhr - if (xhrSupported) { - - jQuery.ajaxTransport(function (options) { - // Cross domain only allowed if supported through XMLHttpRequest - if (!options.crossDomain || support.cors) { - - var callback; - - return { - send: function (headers, complete) { - var i, - xhr = options.xhr(), - id = ++xhrId; - - // Open the socket - xhr.open(options.type, options.url, options.async, options.username, options.password); - - // Apply custom fields if provided - if (options.xhrFields) { - for (i in options.xhrFields) { - xhr[i] = options.xhrFields[i]; - } - } - - // Override mime type if needed - if (options.mimeType && xhr.overrideMimeType) { - xhr.overrideMimeType(options.mimeType); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if (!options.crossDomain && !headers["X-Requested-With"]) { - headers["X-Requested-With"] = "XMLHttpRequest"; - } - - // Set headers - for (i in headers) { - // Support: IE<9 - // IE's ActiveXObject throws a 'Type Mismatch' exception when setting - // request header to a null-value. - // - // To keep consistent with other XHR implementations, cast the value - // to string and ignore `undefined`. - if (headers[i] !== undefined) { - xhr.setRequestHeader(i, headers[i] + ""); - } - } - - // Do send the request - // This may raise an exception which is actually - // handled in jQuery.ajax (so no try/catch here) - xhr.send((options.hasContent && options.data) || null); - - // Listener - callback = function (_, isAbort) { - var status, statusText, responses; - - // Was never called and is aborted or complete - if (callback && (isAbort || xhr.readyState === 4)) { - // Clean up - delete xhrCallbacks[id]; - callback = undefined; - xhr.onreadystatechange = jQuery.noop; - - // Abort manually if needed - if (isAbort) { - if (xhr.readyState !== 4) { - xhr.abort(); - } - } else { - responses = {}; - status = xhr.status; - - // Support: IE<10 - // Accessing binary-data responseText throws an exception - // (#11426) - if (typeof xhr.responseText === "string") { - responses.text = xhr.responseText; - } - - // Firefox throws an exception when accessing - // statusText for faulty cross-domain requests - try { - statusText = xhr.statusText; - } catch (e) { - // We normalize with Webkit giving an empty statusText - statusText = ""; - } - - // Filter status for non standard behaviors - - // If the request is local and we have data: assume a success - // (success with no data won't get notified, that's the best we - // can do given current implementations) - if (!status && options.isLocal && !options.crossDomain) { - status = responses.text ? 200 : 404; - // IE - #1450: sometimes returns 1223 when it should be 204 - } else if (status === 1223) { - status = 204; - } - } - } - - // Call complete if needed - if (responses) { - complete(status, statusText, responses, xhr.getAllResponseHeaders()); - } - }; - - if (!options.async) { - // if we're in sync mode we fire the callback - callback(); - } else if (xhr.readyState === 4) { - // (IE6 & IE7) if it's in cache and has been - // retrieved directly we need to fire the callback - setTimeout(callback); - } else { - // Add to the list of active xhr callbacks - xhr.onreadystatechange = xhrCallbacks[id] = callback; - } - }, - - abort: function () { - if (callback) { - callback(undefined, true); - } - } - }; - } - }); - } - - // Functions to create xhrs - function createStandardXHR() { - try { - return new window.XMLHttpRequest(); - } catch (e) { } - } - - function createActiveXHR() { - try { - return new window.ActiveXObject("Microsoft.XMLHTTP"); - } catch (e) { } - } - - - - - // Install script dataType - jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /(?:java|ecma)script/ - }, - converters: { - "text script": function (text) { - jQuery.globalEval(text); - return text; - } - } - }); - - // Handle cache's special case and global - jQuery.ajaxPrefilter("script", function (s) { - if (s.cache === undefined) { - s.cache = false; - } - if (s.crossDomain) { - s.type = "GET"; - s.global = false; - } - }); - - // Bind script tag hack transport - jQuery.ajaxTransport("script", function (s) { - - // This transport only deals with cross domain requests - if (s.crossDomain) { - - var script, - head = document.head || jQuery("head")[0] || document.documentElement; - - return { - - send: function (_, callback) { - - script = document.createElement("script"); - - script.async = true; - - if (s.scriptCharset) { - script.charset = s.scriptCharset; - } - - script.src = s.url; - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function (_, isAbort) { - - if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) { - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - // Remove the script - if (script.parentNode) { - script.parentNode.removeChild(script); - } - - // Dereference the script - script = null; - - // Callback if not abort - if (!isAbort) { - callback(200, "success"); - } - } - }; - - // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending - // Use native DOM manipulation to avoid our domManip AJAX trickery - head.insertBefore(script, head.firstChild); - }, - - abort: function () { - if (script) { - script.onload(undefined, true); - } - } - }; - } - }); - - - - - var oldCallbacks = [], - rjsonp = /(=)\?(?=&|$)|\?\?/; - - // Default jsonp settings - jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function () { - var callback = oldCallbacks.pop() || (jQuery.expando + "_" + (nonce++)); - this[callback] = true; - return callback; - } - }); - - // Detect, normalize options and install callbacks for jsonp requests - jQuery.ajaxPrefilter("json jsonp", function (s, originalSettings, jqXHR) { - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && (rjsonp.test(s.url) ? - "url" : - typeof s.data === "string" && !(s.contentType || "").indexOf("application/x-www-form-urlencoded") && rjsonp.test(s.data) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if (jsonProp || s.dataTypes[0] === "jsonp") { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction(s.jsonpCallback) ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if (jsonProp) { - s[jsonProp] = s[jsonProp].replace(rjsonp, "$1" + callbackName); - } else if (s.jsonp !== false) { - s.url += (rquery.test(s.url) ? "&" : "?") + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function () { - if (!responseContainer) { - jQuery.error(callbackName + " was not called"); - } - return responseContainer[0]; - }; - - // force json dataType - s.dataTypes[0] = "json"; - - // Install callback - overwritten = window[callbackName]; - window[callbackName] = function () { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function () { - // Restore preexisting value - window[callbackName] = overwritten; - - // Save back as free - if (s[callbackName]) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push(callbackName); - } - - // Call if it was a function and we have a response - if (responseContainer && jQuery.isFunction(overwritten)) { - overwritten(responseContainer[0]); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } - }); - - - - - // data: string of html - // context (optional): If specified, the fragment will be created in this context, defaults to document - // keepScripts (optional): If true, will include scripts passed in the html string - jQuery.parseHTML = function (data, context, keepScripts) { - if (!data || typeof data !== "string") { - return null; - } - if (typeof context === "boolean") { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec(data), - scripts = !keepScripts && []; - - // Single tag - if (parsed) { - return [context.createElement(parsed[1])]; - } - - parsed = jQuery.buildFragment([data], context, scripts); - - if (scripts && scripts.length) { - jQuery(scripts).remove(); - } - - return jQuery.merge([], parsed.childNodes); - }; - - - // Keep a copy of the old load method - var _load = jQuery.fn.load; - - /** - * Load a url into a page - */ - jQuery.fn.load = function (url, params, callback) { - if (typeof url !== "string" && _load) { - return _load.apply(this, arguments); - } - - var selector, response, type, - self = this, - off = url.indexOf(" "); - - if (off >= 0) { - selector = jQuery.trim(url.slice(off, url.length)); - url = url.slice(0, off); - } - - // If it's a function - if (jQuery.isFunction(params)) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if (params && typeof params === "object") { - type = "POST"; - } - - // If we have elements to modify, make the request - if (self.length > 0) { - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params - }).done(function (responseText) { - - // Save response for use in complete callback - response = arguments; - - self.html(selector ? - - // If a selector was specified, locate the right elements in a dummy div - // Exclude scripts to avoid IE 'Permission Denied' errors - jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) : - - // Otherwise use the full result - responseText); - - }).complete(callback && function (jqXHR, status) { - self.each(callback, response || [jqXHR.responseText, status, jqXHR]); - }); - } - - return this; - }; - - - - - jQuery.expr.filters.animated = function (elem) { - return jQuery.grep(jQuery.timers, function (fn) { - return elem === fn.elem; - }).length; - }; - - - - - - var docElem = window.document.documentElement; - - /** - * Gets a window from an element - */ - function getWindow(elem) { - return jQuery.isWindow(elem) ? - elem : - elem.nodeType === 9 ? - elem.defaultView || elem.parentWindow : - false; - } - - jQuery.offset = { - setOffset: function (elem, options, i) { - var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, - position = jQuery.css(elem, "position"), - curElem = jQuery(elem), - props = {}; - - // set position first, in-case top/left are set even on static elem - if (position === "static") { - elem.style.position = "relative"; - } - - curOffset = curElem.offset(); - curCSSTop = jQuery.css(elem, "top"); - curCSSLeft = jQuery.css(elem, "left"); - calculatePosition = (position === "absolute" || position === "fixed") && - jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1; - - // need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if (calculatePosition) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - } else { - curTop = parseFloat(curCSSTop) || 0; - curLeft = parseFloat(curCSSLeft) || 0; - } - - if (jQuery.isFunction(options)) { - options = options.call(elem, i, curOffset); - } - - if (options.top != null) { - props.top = (options.top - curOffset.top) + curTop; - } - if (options.left != null) { - props.left = (options.left - curOffset.left) + curLeft; - } - - if ("using" in options) { - options.using.call(elem, props); - } else { - curElem.css(props); - } - } - }; - - jQuery.fn.extend({ - offset: function (options) { - if (arguments.length) { - return options === undefined ? - this : - this.each(function (i) { - jQuery.offset.setOffset(this, options, i); - }); - } - - var docElem, win, - box = { top: 0, left: 0 }, - elem = this[0], - doc = elem && elem.ownerDocument; - - if (!doc) { - return; - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if (!jQuery.contains(docElem, elem)) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if (typeof elem.getBoundingClientRect !== strundefined) { - box = elem.getBoundingClientRect(); - } - win = getWindow(doc); - return { - top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0), - left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0) - }; - }, - - position: function () { - if (!this[0]) { - return; - } - - var offsetParent, offset, - parentOffset = { top: 0, left: 0 }, - elem = this[0]; - - // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent - if (jQuery.css(elem, "position") === "fixed") { - // we assume that getBoundingClientRect is available when computed position is fixed - offset = elem.getBoundingClientRect(); - } else { - // Get *real* offsetParent - offsetParent = this.offsetParent(); - - // Get correct offsets - offset = this.offset(); - if (!jQuery.nodeName(offsetParent[0], "html")) { - parentOffset = offsetParent.offset(); - } - - // Add offsetParent borders - parentOffset.top += jQuery.css(offsetParent[0], "borderTopWidth", true); - parentOffset.left += jQuery.css(offsetParent[0], "borderLeftWidth", true); - } - - // Subtract parent offsets and element margins - // note: when an element has margin: auto the offsetLeft and marginLeft - // are the same in Safari causing offset.left to incorrectly be 0 - return { - top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true), - left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true) - }; - }, - - offsetParent: function () { - return this.map(function () { - var offsetParent = this.offsetParent || docElem; - - while (offsetParent && (!jQuery.nodeName(offsetParent, "html") && jQuery.css(offsetParent, "position") === "static")) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || docElem; - }); - } - }); - - // Create scrollLeft and scrollTop methods - jQuery.each({ scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function (method, prop) { - var top = /Y/.test(prop); - - jQuery.fn[method] = function (val) { - return access(this, function (elem, method, val) { - var win = getWindow(elem); - - if (val === undefined) { - return win ? (prop in win) ? win[prop] : - win.document.documentElement[method] : - elem[method]; - } - - if (win) { - win.scrollTo( - !top ? val : jQuery(win).scrollLeft(), - top ? val : jQuery(win).scrollTop() - ); - - } else { - elem[method] = val; - } - }, method, val, arguments.length, null); - }; - }); - - // Add the top/left cssHooks using jQuery.fn.position - // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 - // getComputedStyle returns percent when specified for top/left/bottom/right - // rather than make the css module depend on the offset module, we just check for it here - jQuery.each(["top", "left"], function (i, prop) { - jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition, - function (elem, computed) { - if (computed) { - computed = curCSS(elem, prop); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test(computed) ? - jQuery(elem).position()[prop] + "px" : - computed; - } - } - ); - }); - - - // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods - jQuery.each({ Height: "height", Width: "width" }, function (name, type) { - jQuery.each({ padding: "inner" + name, content: type, "": "outer" + name }, function (defaultExtra, funcName) { - // margin is only for outerHeight, outerWidth - jQuery.fn[funcName] = function (margin, value) { - var chainable = arguments.length && (defaultExtra || typeof margin !== "boolean"), - extra = defaultExtra || (margin === true || value === true ? "margin" : "border"); - - return access(this, function (elem, type, value) { - var doc; - - if (jQuery.isWindow(elem)) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement["client" + name]; - } - - // Get document width or height - if (elem.nodeType === 9) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest - // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. - return Math.max( - elem.body["scroll" + name], doc["scroll" + name], - elem.body["offset" + name], doc["offset" + name], - doc["client" + name] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css(elem, type, extra) : - - // Set width or height on the element - jQuery.style(elem, type, value, extra); - }, type, chainable ? margin : undefined, chainable, null); - }; - }); - }); - - - // The number of elements contained in the matched element set - jQuery.fn.size = function () { - return this.length; - }; - - jQuery.fn.andSelf = jQuery.fn.addBack; - - - - - // Register as a named AMD module, since jQuery can be concatenated with other - // files that may use define, but not via a proper concatenation script that - // understands anonymous AMD modules. A named AMD is safest and most robust - // way to register. Lowercase jquery is used because AMD module names are - // derived from file names, and jQuery is normally delivered in a lowercase - // file name. Do this after creating the global so that if an AMD module wants - // to call noConflict to hide this version of jQuery, it will work. - - // Note that for maximum portability, libraries that are not jQuery should - // declare themselves as anonymous modules, and avoid setting a global if an - // AMD loader is present. jQuery is a special case. For more information, see - // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon - - if (typeof define === "function" && define.amd) { - define("jquery", [], function () { - return jQuery; - }); - } - - - - - var - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$; - - jQuery.noConflict = function (deep) { - if (window.$ === jQuery) { - window.$ = _$; - } - - if (deep && window.jQuery === jQuery) { - window.jQuery = _jQuery; - } - - return jQuery; - }; - - // Expose jQuery and $ identifiers, even in - // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) - // and CommonJS for browser emulators (#13566) - if (typeof noGlobal === strundefined) { - window.jQuery = window.$ = jQuery; - } - - - - - return jQuery; - -})); \ No newline at end of file diff --git a/websocket/third-party-socketio/public/socket.io-1.3.7.js b/websocket/third-party-socketio/public/socket.io-1.3.7.js deleted file mode 100644 index e43c4ad0..00000000 --- a/websocket/third-party-socketio/public/socket.io-1.3.7.js +++ /dev/null @@ -1,3 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(_dereq_,module,exports){module.exports=_dereq_("./lib/")},{"./lib/":2}],2:[function(_dereq_,module,exports){var url=_dereq_("./url");var parser=_dereq_("socket.io-parser");var Manager=_dereq_("./manager");var debug=_dereq_("debug")("socket.io-client");module.exports=exports=lookup;var cache=exports.managers={};function lookup(uri,opts){if(typeof uri=="object"){opts=uri;uri=undefined}opts=opts||{};var parsed=url(uri);var source=parsed.source;var id=parsed.id;var io;if(opts.forceNew||opts["force new connection"]||false===opts.multiplex){debug("ignoring socket cache for %s",source);io=Manager(source,opts)}else{if(!cache[id]){debug("new io instance for %s",source);cache[id]=Manager(source,opts)}io=cache[id]}return io.socket(parsed.path)}exports.protocol=parser.protocol;exports.connect=lookup;exports.Manager=_dereq_("./manager");exports.Socket=_dereq_("./socket")},{"./manager":3,"./socket":5,"./url":6,debug:10,"socket.io-parser":44}],3:[function(_dereq_,module,exports){var url=_dereq_("./url");var eio=_dereq_("engine.io-client");var Socket=_dereq_("./socket");var Emitter=_dereq_("component-emitter");var parser=_dereq_("socket.io-parser");var on=_dereq_("./on");var bind=_dereq_("component-bind");var object=_dereq_("object-component");var debug=_dereq_("debug")("socket.io-client:manager");var indexOf=_dereq_("indexof");var Backoff=_dereq_("backo2");module.exports=Manager;function Manager(uri,opts){if(!(this instanceof Manager))return new Manager(uri,opts);if(uri&&"object"==typeof uri){opts=uri;uri=undefined}opts=opts||{};opts.path=opts.path||"/socket.io";this.nsps={};this.subs=[];this.opts=opts;this.reconnection(opts.reconnection!==false);this.reconnectionAttempts(opts.reconnectionAttempts||Infinity);this.reconnectionDelay(opts.reconnectionDelay||1e3);this.reconnectionDelayMax(opts.reconnectionDelayMax||5e3);this.randomizationFactor(opts.randomizationFactor||.5);this.backoff=new Backoff({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()});this.timeout(null==opts.timeout?2e4:opts.timeout);this.readyState="closed";this.uri=uri;this.connected=[];this.encoding=false;this.packetBuffer=[];this.encoder=new parser.Encoder;this.decoder=new parser.Decoder;this.autoConnect=opts.autoConnect!==false;if(this.autoConnect)this.open()}Manager.prototype.emitAll=function(){this.emit.apply(this,arguments);for(var nsp in this.nsps){this.nsps[nsp].emit.apply(this.nsps[nsp],arguments)}};Manager.prototype.updateSocketIds=function(){for(var nsp in this.nsps){this.nsps[nsp].id=this.engine.id}};Emitter(Manager.prototype);Manager.prototype.reconnection=function(v){if(!arguments.length)return this._reconnection;this._reconnection=!!v;return this};Manager.prototype.reconnectionAttempts=function(v){if(!arguments.length)return this._reconnectionAttempts;this._reconnectionAttempts=v;return this};Manager.prototype.reconnectionDelay=function(v){if(!arguments.length)return this._reconnectionDelay;this._reconnectionDelay=v;this.backoff&&this.backoff.setMin(v);return this};Manager.prototype.randomizationFactor=function(v){if(!arguments.length)return this._randomizationFactor;this._randomizationFactor=v;this.backoff&&this.backoff.setJitter(v);return this};Manager.prototype.reconnectionDelayMax=function(v){if(!arguments.length)return this._reconnectionDelayMax;this._reconnectionDelayMax=v;this.backoff&&this.backoff.setMax(v);return this};Manager.prototype.timeout=function(v){if(!arguments.length)return this._timeout;this._timeout=v;return this};Manager.prototype.maybeReconnectOnOpen=function(){if(!this.reconnecting&&this._reconnection&&this.backoff.attempts===0){this.reconnect()}};Manager.prototype.open=Manager.prototype.connect=function(fn){debug("readyState %s",this.readyState);if(~this.readyState.indexOf("open"))return this;debug("opening %s",this.uri);this.engine=eio(this.uri,this.opts);var socket=this.engine;var self=this;this.readyState="opening";this.skipReconnect=false;var openSub=on(socket,"open",function(){self.onopen();fn&&fn()});var errorSub=on(socket,"error",function(data){debug("connect_error");self.cleanup();self.readyState="closed";self.emitAll("connect_error",data);if(fn){var err=new Error("Connection error");err.data=data;fn(err)}else{self.maybeReconnectOnOpen()}});if(false!==this._timeout){var timeout=this._timeout;debug("connect attempt will timeout after %d",timeout);var timer=setTimeout(function(){debug("connect attempt timed out after %d",timeout);openSub.destroy();socket.close();socket.emit("error","timeout");self.emitAll("connect_timeout",timeout)},timeout);this.subs.push({destroy:function(){clearTimeout(timer)}})}this.subs.push(openSub);this.subs.push(errorSub);return this};Manager.prototype.onopen=function(){debug("open");this.cleanup();this.readyState="open";this.emit("open");var socket=this.engine;this.subs.push(on(socket,"data",bind(this,"ondata")));this.subs.push(on(this.decoder,"decoded",bind(this,"ondecoded")));this.subs.push(on(socket,"error",bind(this,"onerror")));this.subs.push(on(socket,"close",bind(this,"onclose")))};Manager.prototype.ondata=function(data){this.decoder.add(data)};Manager.prototype.ondecoded=function(packet){this.emit("packet",packet)};Manager.prototype.onerror=function(err){debug("error",err);this.emitAll("error",err)};Manager.prototype.socket=function(nsp){var socket=this.nsps[nsp];if(!socket){socket=new Socket(this,nsp);this.nsps[nsp]=socket;var self=this;socket.on("connect",function(){socket.id=self.engine.id;if(!~indexOf(self.connected,socket)){self.connected.push(socket)}})}return socket};Manager.prototype.destroy=function(socket){var index=indexOf(this.connected,socket);if(~index)this.connected.splice(index,1);if(this.connected.length)return;this.close()};Manager.prototype.packet=function(packet){debug("writing packet %j",packet);var self=this;if(!self.encoding){self.encoding=true;this.encoder.encode(packet,function(encodedPackets){for(var i=0;i<encodedPackets.length;i++){self.engine.write(encodedPackets[i])}self.encoding=false;self.processPacketQueue()})}else{self.packetBuffer.push(packet)}};Manager.prototype.processPacketQueue=function(){if(this.packetBuffer.length>0&&!this.encoding){var pack=this.packetBuffer.shift();this.packet(pack)}};Manager.prototype.cleanup=function(){var sub;while(sub=this.subs.shift())sub.destroy();this.packetBuffer=[];this.encoding=false;this.decoder.destroy()};Manager.prototype.close=Manager.prototype.disconnect=function(){this.skipReconnect=true;this.backoff.reset();this.readyState="closed";this.engine&&this.engine.close()};Manager.prototype.onclose=function(reason){debug("close");this.cleanup();this.backoff.reset();this.readyState="closed";this.emit("close",reason);if(this._reconnection&&!this.skipReconnect){this.reconnect()}};Manager.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var self=this;if(this.backoff.attempts>=this._reconnectionAttempts){debug("reconnect failed");this.backoff.reset();this.emitAll("reconnect_failed");this.reconnecting=false}else{var delay=this.backoff.duration();debug("will wait %dms before reconnect attempt",delay);this.reconnecting=true;var timer=setTimeout(function(){if(self.skipReconnect)return;debug("attempting reconnect");self.emitAll("reconnect_attempt",self.backoff.attempts);self.emitAll("reconnecting",self.backoff.attempts);if(self.skipReconnect)return;self.open(function(err){if(err){debug("reconnect attempt error");self.reconnecting=false;self.reconnect();self.emitAll("reconnect_error",err.data)}else{debug("reconnect success");self.onreconnect()}})},delay);this.subs.push({destroy:function(){clearTimeout(timer)}})}};Manager.prototype.onreconnect=function(){var attempt=this.backoff.attempts;this.reconnecting=false;this.backoff.reset();this.updateSocketIds();this.emitAll("reconnect",attempt)}},{"./on":4,"./socket":5,"./url":6,backo2:7,"component-bind":8,"component-emitter":9,debug:10,"engine.io-client":11,indexof:40,"object-component":41,"socket.io-parser":44}],4:[function(_dereq_,module,exports){module.exports=on;function on(obj,ev,fn){obj.on(ev,fn);return{destroy:function(){obj.removeListener(ev,fn)}}}},{}],5:[function(_dereq_,module,exports){var parser=_dereq_("socket.io-parser");var Emitter=_dereq_("component-emitter");var toArray=_dereq_("to-array");var on=_dereq_("./on");var bind=_dereq_("component-bind");var debug=_dereq_("debug")("socket.io-client:socket");var hasBin=_dereq_("has-binary");module.exports=exports=Socket;var events={connect:1,connect_error:1,connect_timeout:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1};var emit=Emitter.prototype.emit;function Socket(io,nsp){this.io=io;this.nsp=nsp;this.json=this;this.ids=0;this.acks={};if(this.io.autoConnect)this.open();this.receiveBuffer=[];this.sendBuffer=[];this.connected=false;this.disconnected=true}Emitter(Socket.prototype);Socket.prototype.subEvents=function(){if(this.subs)return;var io=this.io;this.subs=[on(io,"open",bind(this,"onopen")),on(io,"packet",bind(this,"onpacket")),on(io,"close",bind(this,"onclose"))]};Socket.prototype.open=Socket.prototype.connect=function(){if(this.connected)return this;this.subEvents();this.io.open();if("open"==this.io.readyState)this.onopen();return this};Socket.prototype.send=function(){var args=toArray(arguments);args.unshift("message");this.emit.apply(this,args);return this};Socket.prototype.emit=function(ev){if(events.hasOwnProperty(ev)){emit.apply(this,arguments);return this}var args=toArray(arguments);var parserType=parser.EVENT;if(hasBin(args)){parserType=parser.BINARY_EVENT}var packet={type:parserType,data:args};if("function"==typeof args[args.length-1]){debug("emitting packet with ack id %d",this.ids);this.acks[this.ids]=args.pop();packet.id=this.ids++}if(this.connected){this.packet(packet)}else{this.sendBuffer.push(packet)}return this};Socket.prototype.packet=function(packet){packet.nsp=this.nsp;this.io.packet(packet)};Socket.prototype.onopen=function(){debug("transport is open - connecting");if("/"!=this.nsp){this.packet({type:parser.CONNECT})}};Socket.prototype.onclose=function(reason){debug("close (%s)",reason);this.connected=false;this.disconnected=true;delete this.id;this.emit("disconnect",reason)};Socket.prototype.onpacket=function(packet){if(packet.nsp!=this.nsp)return;switch(packet.type){case parser.CONNECT:this.onconnect();break;case parser.EVENT:this.onevent(packet);break;case parser.BINARY_EVENT:this.onevent(packet);break;case parser.ACK:this.onack(packet);break;case parser.BINARY_ACK:this.onack(packet);break;case parser.DISCONNECT:this.ondisconnect();break;case parser.ERROR:this.emit("error",packet.data);break}};Socket.prototype.onevent=function(packet){var args=packet.data||[];debug("emitting event %j",args);if(null!=packet.id){debug("attaching ack callback to event");args.push(this.ack(packet.id))}if(this.connected){emit.apply(this,args)}else{this.receiveBuffer.push(args)}};Socket.prototype.ack=function(id){var self=this;var sent=false;return function(){if(sent)return;sent=true;var args=toArray(arguments);debug("sending ack %j",args);var type=hasBin(args)?parser.BINARY_ACK:parser.ACK;self.packet({type:type,id:id,data:args})}};Socket.prototype.onack=function(packet){debug("calling ack %s with %j",packet.id,packet.data);var fn=this.acks[packet.id];fn.apply(this,packet.data);delete this.acks[packet.id]};Socket.prototype.onconnect=function(){this.connected=true;this.disconnected=false;this.emit("connect");this.emitBuffered()};Socket.prototype.emitBuffered=function(){var i;for(i=0;i<this.receiveBuffer.length;i++){emit.apply(this,this.receiveBuffer[i])}this.receiveBuffer=[];for(i=0;i<this.sendBuffer.length;i++){this.packet(this.sendBuffer[i])}this.sendBuffer=[]};Socket.prototype.ondisconnect=function(){debug("server disconnect (%s)",this.nsp);this.destroy();this.onclose("io server disconnect")};Socket.prototype.destroy=function(){if(this.subs){for(var i=0;i<this.subs.length;i++){this.subs[i].destroy()}this.subs=null}this.io.destroy(this)};Socket.prototype.close=Socket.prototype.disconnect=function(){if(this.connected){debug("performing disconnect (%s)",this.nsp);this.packet({type:parser.DISCONNECT})}this.destroy();if(this.connected){this.onclose("io client disconnect")}return this}},{"./on":4,"component-bind":8,"component-emitter":9,debug:10,"has-binary":36,"socket.io-parser":44,"to-array":48}],6:[function(_dereq_,module,exports){(function(global){var parseuri=_dereq_("parseuri");var debug=_dereq_("debug")("socket.io-client:url");module.exports=url;function url(uri,loc){var obj=uri;var loc=loc||global.location;if(null==uri)uri=loc.protocol+"//"+loc.host;if("string"==typeof uri){if("/"==uri.charAt(0)){if("/"==uri.charAt(1)){uri=loc.protocol+uri}else{uri=loc.hostname+uri}}if(!/^(https?|wss?):\/\//.test(uri)){debug("protocol-less url %s",uri);if("undefined"!=typeof loc){uri=loc.protocol+"//"+uri}else{uri="https://"+uri}}debug("parse %s",uri);obj=parseuri(uri)}if(!obj.port){if(/^(http|ws)$/.test(obj.protocol)){obj.port="80"}else if(/^(http|ws)s$/.test(obj.protocol)){obj.port="443"}}obj.path=obj.path||"/";obj.id=obj.protocol+"://"+obj.host+":"+obj.port;obj.href=obj.protocol+"://"+obj.host+(loc&&loc.port==obj.port?"":":"+obj.port);return obj}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{debug:10,parseuri:42}],7:[function(_dereq_,module,exports){module.exports=Backoff;function Backoff(opts){opts=opts||{};this.ms=opts.min||100;this.max=opts.max||1e4;this.factor=opts.factor||2;this.jitter=opts.jitter>0&&opts.jitter<=1?opts.jitter:0;this.attempts=0}Backoff.prototype.duration=function(){var ms=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var rand=Math.random();var deviation=Math.floor(rand*this.jitter*ms);ms=(Math.floor(rand*10)&1)==0?ms-deviation:ms+deviation}return Math.min(ms,this.max)|0};Backoff.prototype.reset=function(){this.attempts=0};Backoff.prototype.setMin=function(min){this.ms=min};Backoff.prototype.setMax=function(max){this.max=max};Backoff.prototype.setJitter=function(jitter){this.jitter=jitter}},{}],8:[function(_dereq_,module,exports){var slice=[].slice;module.exports=function(obj,fn){if("string"==typeof fn)fn=obj[fn];if("function"!=typeof fn)throw new Error("bind() requires a function");var args=slice.call(arguments,2);return function(){return fn.apply(obj,args.concat(slice.call(arguments)))}}},{}],9:[function(_dereq_,module,exports){module.exports=Emitter;function Emitter(obj){if(obj)return mixin(obj)}function mixin(obj){for(var key in Emitter.prototype){obj[key]=Emitter.prototype[key]}return obj}Emitter.prototype.on=Emitter.prototype.addEventListener=function(event,fn){this._callbacks=this._callbacks||{};(this._callbacks[event]=this._callbacks[event]||[]).push(fn);return this};Emitter.prototype.once=function(event,fn){var self=this;this._callbacks=this._callbacks||{};function on(){self.off(event,on);fn.apply(this,arguments)}on.fn=fn;this.on(event,on);return this};Emitter.prototype.off=Emitter.prototype.removeListener=Emitter.prototype.removeAllListeners=Emitter.prototype.removeEventListener=function(event,fn){this._callbacks=this._callbacks||{};if(0==arguments.length){this._callbacks={};return this}var callbacks=this._callbacks[event];if(!callbacks)return this;if(1==arguments.length){delete this._callbacks[event];return this}var cb;for(var i=0;i<callbacks.length;i++){cb=callbacks[i];if(cb===fn||cb.fn===fn){callbacks.splice(i,1);break}}return this};Emitter.prototype.emit=function(event){this._callbacks=this._callbacks||{};var args=[].slice.call(arguments,1),callbacks=this._callbacks[event];if(callbacks){callbacks=callbacks.slice(0);for(var i=0,len=callbacks.length;i<len;++i){callbacks[i].apply(this,args)}}return this};Emitter.prototype.listeners=function(event){this._callbacks=this._callbacks||{};return this._callbacks[event]||[]};Emitter.prototype.hasListeners=function(event){return!!this.listeners(event).length}},{}],10:[function(_dereq_,module,exports){module.exports=debug;function debug(name){if(!debug.enabled(name))return function(){};return function(fmt){fmt=coerce(fmt);var curr=new Date;var ms=curr-(debug[name]||curr);debug[name]=curr;fmt=name+" "+fmt+" +"+debug.humanize(ms);window.console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}}debug.names=[];debug.skips=[];debug.enable=function(name){try{localStorage.debug=name}catch(e){}var split=(name||"").split(/[\s,]+/),len=split.length;for(var i=0;i<len;i++){name=split[i].replace("*",".*?");if(name[0]==="-"){debug.skips.push(new RegExp("^"+name.substr(1)+"$"))}else{debug.names.push(new RegExp("^"+name+"$"))}}};debug.disable=function(){debug.enable("")};debug.humanize=function(ms){var sec=1e3,min=60*1e3,hour=60*min;if(ms>=hour)return(ms/hour).toFixed(1)+"h";if(ms>=min)return(ms/min).toFixed(1)+"m";if(ms>=sec)return(ms/sec|0)+"s";return ms+"ms"};debug.enabled=function(name){for(var i=0,len=debug.skips.length;i<len;i++){if(debug.skips[i].test(name)){return false}}for(var i=0,len=debug.names.length;i<len;i++){if(debug.names[i].test(name)){return true}}return false};function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}try{if(window.localStorage)debug.enable(localStorage.debug)}catch(e){}},{}],11:[function(_dereq_,module,exports){module.exports=_dereq_("./lib/")},{"./lib/":12}],12:[function(_dereq_,module,exports){module.exports=_dereq_("./socket");module.exports.parser=_dereq_("engine.io-parser")},{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){(function(global){var transports=_dereq_("./transports");var Emitter=_dereq_("component-emitter");var debug=_dereq_("debug")("engine.io-client:socket");var index=_dereq_("indexof");var parser=_dereq_("engine.io-parser");var parseuri=_dereq_("parseuri");var parsejson=_dereq_("parsejson");var parseqs=_dereq_("parseqs");module.exports=Socket;function noop(){}function Socket(uri,opts){if(!(this instanceof Socket))return new Socket(uri,opts);opts=opts||{};if(uri&&"object"==typeof uri){opts=uri;uri=null}if(uri){uri=parseuri(uri);opts.host=uri.host;opts.secure=uri.protocol=="https"||uri.protocol=="wss";opts.port=uri.port;if(uri.query)opts.query=uri.query}this.secure=null!=opts.secure?opts.secure:global.location&&"https:"==location.protocol;if(opts.host){var pieces=opts.host.split(":");opts.hostname=pieces.shift();if(pieces.length){opts.port=pieces.pop()}else if(!opts.port){opts.port=this.secure?"443":"80"}}this.agent=opts.agent||false;this.hostname=opts.hostname||(global.location?location.hostname:"localhost");this.port=opts.port||(global.location&&location.port?location.port:this.secure?443:80);this.query=opts.query||{};if("string"==typeof this.query)this.query=parseqs.decode(this.query);this.upgrade=false!==opts.upgrade;this.path=(opts.path||"/engine.io").replace(/\/$/,"")+"/";this.forceJSONP=!!opts.forceJSONP;this.jsonp=false!==opts.jsonp;this.forceBase64=!!opts.forceBase64;this.enablesXDR=!!opts.enablesXDR;this.timestampParam=opts.timestampParam||"t";this.timestampRequests=opts.timestampRequests;this.transports=opts.transports||["polling","websocket"];this.readyState="";this.writeBuffer=[];this.callbackBuffer=[];this.policyPort=opts.policyPort||843;this.rememberUpgrade=opts.rememberUpgrade||false;this.binaryType=null;this.onlyBinaryUpgrades=opts.onlyBinaryUpgrades;this.pfx=opts.pfx||null;this.key=opts.key||null;this.passphrase=opts.passphrase||null;this.cert=opts.cert||null;this.ca=opts.ca||null;this.ciphers=opts.ciphers||null;this.rejectUnauthorized=opts.rejectUnauthorized||null;this.open()}Socket.priorWebsocketSuccess=false;Emitter(Socket.prototype);Socket.protocol=parser.protocol;Socket.Socket=Socket;Socket.Transport=_dereq_("./transport");Socket.transports=_dereq_("./transports");Socket.parser=_dereq_("engine.io-parser");Socket.prototype.createTransport=function(name){debug('creating transport "%s"',name);var query=clone(this.query);query.EIO=parser.protocol;query.transport=name;if(this.id)query.sid=this.id;var transport=new transports[name]({agent:this.agent,hostname:this.hostname,port:this.port,secure:this.secure,path:this.path,query:query,forceJSONP:this.forceJSONP,jsonp:this.jsonp,forceBase64:this.forceBase64,enablesXDR:this.enablesXDR,timestampRequests:this.timestampRequests,timestampParam:this.timestampParam,policyPort:this.policyPort,socket:this,pfx:this.pfx,key:this.key,passphrase:this.passphrase,cert:this.cert,ca:this.ca,ciphers:this.ciphers,rejectUnauthorized:this.rejectUnauthorized});return transport};function clone(obj){var o={};for(var i in obj){if(obj.hasOwnProperty(i)){o[i]=obj[i]}}return o}Socket.prototype.open=function(){var transport;if(this.rememberUpgrade&&Socket.priorWebsocketSuccess&&this.transports.indexOf("websocket")!=-1){transport="websocket"}else if(0==this.transports.length){var self=this;setTimeout(function(){self.emit("error","No transports available")},0);return}else{transport=this.transports[0]}this.readyState="opening";var transport;try{transport=this.createTransport(transport)}catch(e){this.transports.shift();this.open();return}transport.open();this.setTransport(transport)};Socket.prototype.setTransport=function(transport){debug("setting transport %s",transport.name);var self=this;if(this.transport){debug("clearing existing transport %s",this.transport.name);this.transport.removeAllListeners()}this.transport=transport;transport.on("drain",function(){self.onDrain()}).on("packet",function(packet){self.onPacket(packet)}).on("error",function(e){self.onError(e)}).on("close",function(){self.onClose("transport close")})};Socket.prototype.probe=function(name){debug('probing transport "%s"',name);var transport=this.createTransport(name,{probe:1}),failed=false,self=this;Socket.priorWebsocketSuccess=false;function onTransportOpen(){if(self.onlyBinaryUpgrades){var upgradeLosesBinary=!this.supportsBinary&&self.transport.supportsBinary;failed=failed||upgradeLosesBinary}if(failed)return;debug('probe transport "%s" opened',name);transport.send([{type:"ping",data:"probe"}]);transport.once("packet",function(msg){if(failed)return;if("pong"==msg.type&&"probe"==msg.data){debug('probe transport "%s" pong',name);self.upgrading=true;self.emit("upgrading",transport);if(!transport)return;Socket.priorWebsocketSuccess="websocket"==transport.name;debug('pausing current transport "%s"',self.transport.name);self.transport.pause(function(){if(failed)return;if("closed"==self.readyState)return;debug("changing transport and sending upgrade packet");cleanup();self.setTransport(transport);transport.send([{type:"upgrade"}]);self.emit("upgrade",transport);transport=null;self.upgrading=false;self.flush()})}else{debug('probe transport "%s" failed',name);var err=new Error("probe error");err.transport=transport.name;self.emit("upgradeError",err)}})}function freezeTransport(){if(failed)return;failed=true;cleanup();transport.close();transport=null}function onerror(err){var error=new Error("probe error: "+err);error.transport=transport.name;freezeTransport();debug('probe transport "%s" failed because of error: %s',name,err);self.emit("upgradeError",error)}function onTransportClose(){onerror("transport closed")}function onclose(){onerror("socket closed")}function onupgrade(to){if(transport&&to.name!=transport.name){debug('"%s" works - aborting "%s"',to.name,transport.name);freezeTransport()}}function cleanup(){transport.removeListener("open",onTransportOpen);transport.removeListener("error",onerror);transport.removeListener("close",onTransportClose);self.removeListener("close",onclose);self.removeListener("upgrading",onupgrade)}transport.once("open",onTransportOpen);transport.once("error",onerror);transport.once("close",onTransportClose);this.once("close",onclose);this.once("upgrading",onupgrade);transport.open()};Socket.prototype.onOpen=function(){debug("socket open");this.readyState="open";Socket.priorWebsocketSuccess="websocket"==this.transport.name;this.emit("open");this.flush();if("open"==this.readyState&&this.upgrade&&this.transport.pause){debug("starting upgrade probes");for(var i=0,l=this.upgrades.length;i<l;i++){this.probe(this.upgrades[i])}}};Socket.prototype.onPacket=function(packet){if("opening"==this.readyState||"open"==this.readyState){debug('socket receive: type "%s", data "%s"',packet.type,packet.data);this.emit("packet",packet);this.emit("heartbeat");switch(packet.type){case"open":this.onHandshake(parsejson(packet.data));break;case"pong":this.setPing();break;case"error":var err=new Error("server error");err.code=packet.data;this.emit("error",err);break;case"message":this.emit("data",packet.data);this.emit("message",packet.data);break}}else{debug('packet received with socket readyState "%s"',this.readyState)}};Socket.prototype.onHandshake=function(data){this.emit("handshake",data);this.id=data.sid;this.transport.query.sid=data.sid;this.upgrades=this.filterUpgrades(data.upgrades);this.pingInterval=data.pingInterval;this.pingTimeout=data.pingTimeout;this.onOpen();if("closed"==this.readyState)return;this.setPing();this.removeListener("heartbeat",this.onHeartbeat);this.on("heartbeat",this.onHeartbeat)};Socket.prototype.onHeartbeat=function(timeout){clearTimeout(this.pingTimeoutTimer);var self=this;self.pingTimeoutTimer=setTimeout(function(){if("closed"==self.readyState)return;self.onClose("ping timeout")},timeout||self.pingInterval+self.pingTimeout)};Socket.prototype.setPing=function(){var self=this;clearTimeout(self.pingIntervalTimer);self.pingIntervalTimer=setTimeout(function(){debug("writing ping packet - expecting pong within %sms",self.pingTimeout);self.ping();self.onHeartbeat(self.pingTimeout)},self.pingInterval)};Socket.prototype.ping=function(){this.sendPacket("ping")};Socket.prototype.onDrain=function(){for(var i=0;i<this.prevBufferLen;i++){if(this.callbackBuffer[i]){this.callbackBuffer[i]()}}this.writeBuffer.splice(0,this.prevBufferLen);this.callbackBuffer.splice(0,this.prevBufferLen);this.prevBufferLen=0;if(this.writeBuffer.length==0){this.emit("drain")}else{this.flush()}};Socket.prototype.flush=function(){if("closed"!=this.readyState&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){debug("flushing %d packets in socket",this.writeBuffer.length);this.transport.send(this.writeBuffer);this.prevBufferLen=this.writeBuffer.length;this.emit("flush")}};Socket.prototype.write=Socket.prototype.send=function(msg,fn){this.sendPacket("message",msg,fn);return this};Socket.prototype.sendPacket=function(type,data,fn){if("closing"==this.readyState||"closed"==this.readyState){return}var packet={type:type,data:data};this.emit("packetCreate",packet);this.writeBuffer.push(packet);this.callbackBuffer.push(fn);this.flush()};Socket.prototype.close=function(){if("opening"==this.readyState||"open"==this.readyState){this.readyState="closing";var self=this;function close(){self.onClose("forced close");debug("socket closing - telling transport to close");self.transport.close()}function cleanupAndClose(){self.removeListener("upgrade",cleanupAndClose);self.removeListener("upgradeError",cleanupAndClose);close()}function waitForUpgrade(){self.once("upgrade",cleanupAndClose);self.once("upgradeError",cleanupAndClose)}if(this.writeBuffer.length){this.once("drain",function(){if(this.upgrading){waitForUpgrade()}else{close()}})}else if(this.upgrading){waitForUpgrade()}else{close()}}return this};Socket.prototype.onError=function(err){debug("socket error %j",err);Socket.priorWebsocketSuccess=false;this.emit("error",err);this.onClose("transport error",err)};Socket.prototype.onClose=function(reason,desc){if("opening"==this.readyState||"open"==this.readyState||"closing"==this.readyState){debug('socket close with reason: "%s"',reason);var self=this;clearTimeout(this.pingIntervalTimer);clearTimeout(this.pingTimeoutTimer);setTimeout(function(){self.writeBuffer=[];self.callbackBuffer=[];self.prevBufferLen=0},0);this.transport.removeAllListeners("close");this.transport.close();this.transport.removeAllListeners();this.readyState="closed";this.id=null;this.emit("close",reason,desc)}};Socket.prototype.filterUpgrades=function(upgrades){var filteredUpgrades=[];for(var i=0,j=upgrades.length;i<j;i++){if(~index(this.transports,upgrades[i]))filteredUpgrades.push(upgrades[i])}return filteredUpgrades}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./transport":14,"./transports":15,"component-emitter":9,debug:22,"engine.io-parser":25,indexof:40,parsejson:32,parseqs:33,parseuri:34}],14:[function(_dereq_,module,exports){var parser=_dereq_("engine.io-parser");var Emitter=_dereq_("component-emitter");module.exports=Transport;function Transport(opts){this.path=opts.path;this.hostname=opts.hostname;this.port=opts.port;this.secure=opts.secure;this.query=opts.query;this.timestampParam=opts.timestampParam;this.timestampRequests=opts.timestampRequests;this.readyState="";this.agent=opts.agent||false;this.socket=opts.socket;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized}Emitter(Transport.prototype);Transport.timestamps=0;Transport.prototype.onError=function(msg,desc){var err=new Error(msg);err.type="TransportError";err.description=desc;this.emit("error",err);return this};Transport.prototype.open=function(){if("closed"==this.readyState||""==this.readyState){this.readyState="opening";this.doOpen()}return this};Transport.prototype.close=function(){if("opening"==this.readyState||"open"==this.readyState){this.doClose();this.onClose()}return this};Transport.prototype.send=function(packets){if("open"==this.readyState){this.write(packets)}else{throw new Error("Transport not open")}};Transport.prototype.onOpen=function(){this.readyState="open";this.writable=true;this.emit("open")};Transport.prototype.onData=function(data){var packet=parser.decodePacket(data,this.socket.binaryType);this.onPacket(packet)};Transport.prototype.onPacket=function(packet){this.emit("packet",packet)};Transport.prototype.onClose=function(){this.readyState="closed";this.emit("close")}},{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest");var XHR=_dereq_("./polling-xhr");var JSONP=_dereq_("./polling-jsonp");var websocket=_dereq_("./websocket");exports.polling=polling;exports.websocket=websocket;function polling(opts){var xhr;var xd=false;var xs=false;var jsonp=false!==opts.jsonp;if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}xd=opts.hostname!=location.hostname||port!=opts.port;xs=opts.secure!=isSSL}opts.xdomain=xd;opts.xscheme=xs;xhr=new XMLHttpRequest(opts);if("open"in xhr&&!opts.forceJSONP){return new XHR(opts)}else{if(!jsonp)throw new Error("JSONP disabled");return new JSONP(opts)}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,xmlhttprequest:20}],16:[function(_dereq_,module,exports){(function(global){var Polling=_dereq_("./polling");var inherit=_dereq_("component-inherit");module.exports=JSONPPolling;var rNewline=/\n/g;var rEscapedNewline=/\\n/g;var callbacks;var index=0;function empty(){}function JSONPPolling(opts){Polling.call(this,opts); -this.query=this.query||{};if(!callbacks){if(!global.___eio)global.___eio=[];callbacks=global.___eio}this.index=callbacks.length;var self=this;callbacks.push(function(msg){self.onData(msg)});this.query.j=this.index;if(global.document&&global.addEventListener){global.addEventListener("beforeunload",function(){if(self.script)self.script.onerror=empty},false)}}inherit(JSONPPolling,Polling);JSONPPolling.prototype.supportsBinary=false;JSONPPolling.prototype.doClose=function(){if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}if(this.form){this.form.parentNode.removeChild(this.form);this.form=null;this.iframe=null}Polling.prototype.doClose.call(this)};JSONPPolling.prototype.doPoll=function(){var self=this;var script=document.createElement("script");if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}script.async=true;script.src=this.uri();script.onerror=function(e){self.onError("jsonp poll error",e)};var insertAt=document.getElementsByTagName("script")[0];insertAt.parentNode.insertBefore(script,insertAt);this.script=script;var isUAgecko="undefined"!=typeof navigator&&/gecko/i.test(navigator.userAgent);if(isUAgecko){setTimeout(function(){var iframe=document.createElement("iframe");document.body.appendChild(iframe);document.body.removeChild(iframe)},100)}};JSONPPolling.prototype.doWrite=function(data,fn){var self=this;if(!this.form){var form=document.createElement("form");var area=document.createElement("textarea");var id=this.iframeId="eio_iframe_"+this.index;var iframe;form.className="socketio";form.style.position="absolute";form.style.top="-1000px";form.style.left="-1000px";form.target=id;form.method="POST";form.setAttribute("accept-charset","utf-8");area.name="d";form.appendChild(area);document.body.appendChild(form);this.form=form;this.area=area}this.form.action=this.uri();function complete(){initIframe();fn()}function initIframe(){if(self.iframe){try{self.form.removeChild(self.iframe)}catch(e){self.onError("jsonp polling iframe removal error",e)}}try{var html='<iframe src="javascript:0" name="'+self.iframeId+'">';iframe=document.createElement(html)}catch(e){iframe=document.createElement("iframe");iframe.name=self.iframeId;iframe.src="javascript:0"}iframe.id=self.iframeId;self.form.appendChild(iframe);self.iframe=iframe}initIframe();data=data.replace(rEscapedNewline,"\\\n");this.area.value=data.replace(rNewline,"\\n");try{this.form.submit()}catch(e){}if(this.iframe.attachEvent){this.iframe.onreadystatechange=function(){if(self.iframe.readyState=="complete"){complete()}}}else{this.iframe.onload=complete}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_("xmlhttprequest");var Polling=_dereq_("./polling");var Emitter=_dereq_("component-emitter");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling-xhr");module.exports=XHR;module.exports.Request=Request;function empty(){}function XHR(opts){Polling.call(this,opts);if(global.location){var isSSL="https:"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}this.xd=opts.hostname!=global.location.hostname||port!=opts.port;this.xs=opts.secure!=isSSL}}inherit(XHR,Polling);XHR.prototype.supportsBinary=true;XHR.prototype.request=function(opts){opts=opts||{};opts.uri=this.uri();opts.xd=this.xd;opts.xs=this.xs;opts.agent=this.agent||false;opts.supportsBinary=this.supportsBinary;opts.enablesXDR=this.enablesXDR;opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;return new Request(opts)};XHR.prototype.doWrite=function(data,fn){var isBinary=typeof data!=="string"&&data!==undefined;var req=this.request({method:"POST",data:data,isBinary:isBinary});var self=this;req.on("success",fn);req.on("error",function(err){self.onError("xhr post error",err)});this.sendXhr=req};XHR.prototype.doPoll=function(){debug("xhr poll");var req=this.request();var self=this;req.on("data",function(data){self.onData(data)});req.on("error",function(err){self.onError("xhr poll error",err)});this.pollXhr=req};function Request(opts){this.method=opts.method||"GET";this.uri=opts.uri;this.xd=!!opts.xd;this.xs=!!opts.xs;this.async=false!==opts.async;this.data=undefined!=opts.data?opts.data:null;this.agent=opts.agent;this.isBinary=opts.isBinary;this.supportsBinary=opts.supportsBinary;this.enablesXDR=opts.enablesXDR;this.pfx=opts.pfx;this.key=opts.key;this.passphrase=opts.passphrase;this.cert=opts.cert;this.ca=opts.ca;this.ciphers=opts.ciphers;this.rejectUnauthorized=opts.rejectUnauthorized;this.create()}Emitter(Request.prototype);Request.prototype.create=function(){var opts={agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;var xhr=this.xhr=new XMLHttpRequest(opts);var self=this;try{debug("xhr open %s: %s",this.method,this.uri);xhr.open(this.method,this.uri,this.async);if(this.supportsBinary){xhr.responseType="arraybuffer"}if("POST"==this.method){try{if(this.isBinary){xhr.setRequestHeader("Content-type","application/octet-stream")}else{xhr.setRequestHeader("Content-type","text/plain;charset=UTF-8")}}catch(e){}}if("withCredentials"in xhr){xhr.withCredentials=true}if(this.hasXDR()){xhr.onload=function(){self.onLoad()};xhr.onerror=function(){self.onError(xhr.responseText)}}else{xhr.onreadystatechange=function(){if(4!=xhr.readyState)return;if(200==xhr.status||1223==xhr.status){self.onLoad()}else{setTimeout(function(){self.onError(xhr.status)},0)}}}debug("xhr data %s",this.data);xhr.send(this.data)}catch(e){setTimeout(function(){self.onError(e)},0);return}if(global.document){this.index=Request.requestsCount++;Request.requests[this.index]=this}};Request.prototype.onSuccess=function(){this.emit("success");this.cleanup()};Request.prototype.onData=function(data){this.emit("data",data);this.onSuccess()};Request.prototype.onError=function(err){this.emit("error",err);this.cleanup(true)};Request.prototype.cleanup=function(fromError){if("undefined"==typeof this.xhr||null===this.xhr){return}if(this.hasXDR()){this.xhr.onload=this.xhr.onerror=empty}else{this.xhr.onreadystatechange=empty}if(fromError){try{this.xhr.abort()}catch(e){}}if(global.document){delete Request.requests[this.index]}this.xhr=null};Request.prototype.onLoad=function(){var data;try{var contentType;try{contentType=this.xhr.getResponseHeader("Content-Type").split(";")[0]}catch(e){}if(contentType==="application/octet-stream"){data=this.xhr.response}else{if(!this.supportsBinary){data=this.xhr.responseText}else{data="ok"}}}catch(e){this.onError(e)}if(null!=data){this.onData(data)}};Request.prototype.hasXDR=function(){return"undefined"!==typeof global.XDomainRequest&&!this.xs&&this.enablesXDR};Request.prototype.abort=function(){this.cleanup()};if(global.document){Request.requestsCount=0;Request.requests={};if(global.attachEvent){global.attachEvent("onunload",unloadHandler)}else if(global.addEventListener){global.addEventListener("beforeunload",unloadHandler,false)}}function unloadHandler(){for(var i in Request.requests){if(Request.requests.hasOwnProperty(i)){Request.requests[i].abort()}}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./polling":18,"component-emitter":9,"component-inherit":21,debug:22,xmlhttprequest:20}],18:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parseqs=_dereq_("parseqs");var parser=_dereq_("engine.io-parser");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:polling");module.exports=Polling;var hasXHR2=function(){var XMLHttpRequest=_dereq_("xmlhttprequest");var xhr=new XMLHttpRequest({xdomain:false});return null!=xhr.responseType}();function Polling(opts){var forceBase64=opts&&opts.forceBase64;if(!hasXHR2||forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(Polling,Transport);Polling.prototype.name="polling";Polling.prototype.doOpen=function(){this.poll()};Polling.prototype.pause=function(onPause){var pending=0;var self=this;this.readyState="pausing";function pause(){debug("paused");self.readyState="paused";onPause()}if(this.polling||!this.writable){var total=0;if(this.polling){debug("we are currently polling - waiting to pause");total++;this.once("pollComplete",function(){debug("pre-pause polling complete");--total||pause()})}if(!this.writable){debug("we are currently writing - waiting to pause");total++;this.once("drain",function(){debug("pre-pause writing complete");--total||pause()})}}else{pause()}};Polling.prototype.poll=function(){debug("polling");this.polling=true;this.doPoll();this.emit("poll")};Polling.prototype.onData=function(data){var self=this;debug("polling got data %s",data);var callback=function(packet,index,total){if("opening"==self.readyState){self.onOpen()}if("close"==packet.type){self.onClose();return false}self.onPacket(packet)};parser.decodePayload(data,this.socket.binaryType,callback);if("closed"!=this.readyState){this.polling=false;this.emit("pollComplete");if("open"==this.readyState){this.poll()}else{debug('ignoring poll - transport state "%s"',this.readyState)}}};Polling.prototype.doClose=function(){var self=this;function close(){debug("writing close packet");self.write([{type:"close"}])}if("open"==this.readyState){debug("transport open - closing");close()}else{debug("transport not open - deferring close");this.once("open",close)}};Polling.prototype.write=function(packets){var self=this;this.writable=false;var callbackfn=function(){self.writable=true;self.emit("drain")};var self=this;parser.encodePayload(packets,this.supportsBinary,function(data){self.doWrite(data,callbackfn)})};Polling.prototype.uri=function(){var query=this.query||{};var schema=this.secure?"https":"http";var port="";if(false!==this.timestampRequests){query[this.timestampParam]=+new Date+"-"+Transport.timestamps++}if(!this.supportsBinary&&!query.sid){query.b64=1}query=parseqs.encode(query);if(this.port&&("https"==schema&&this.port!=443||"http"==schema&&this.port!=80)){port=":"+this.port}if(query.length){query="?"+query}return schema+"://"+this.hostname+port+this.path+query}},{"../transport":14,"component-inherit":21,debug:22,"engine.io-parser":25,parseqs:33,xmlhttprequest:20}],19:[function(_dereq_,module,exports){var Transport=_dereq_("../transport");var parser=_dereq_("engine.io-parser");var parseqs=_dereq_("parseqs");var inherit=_dereq_("component-inherit");var debug=_dereq_("debug")("engine.io-client:websocket");var WebSocket=_dereq_("ws");module.exports=WS;function WS(opts){var forceBase64=opts&&opts.forceBase64;if(forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(WS,Transport);WS.prototype.name="websocket";WS.prototype.supportsBinary=true;WS.prototype.doOpen=function(){if(!this.check()){return}var self=this;var uri=this.uri();var protocols=void 0;var opts={agent:this.agent};opts.pfx=this.pfx;opts.key=this.key;opts.passphrase=this.passphrase;opts.cert=this.cert;opts.ca=this.ca;opts.ciphers=this.ciphers;opts.rejectUnauthorized=this.rejectUnauthorized;this.ws=new WebSocket(uri,protocols,opts);if(this.ws.binaryType===undefined){this.supportsBinary=false}this.ws.binaryType="arraybuffer";this.addEventListeners()};WS.prototype.addEventListeners=function(){var self=this;this.ws.onopen=function(){self.onOpen()};this.ws.onclose=function(){self.onClose()};this.ws.onmessage=function(ev){self.onData(ev.data)};this.ws.onerror=function(e){self.onError("websocket error",e)}};if("undefined"!=typeof navigator&&/iPad|iPhone|iPod/i.test(navigator.userAgent)){WS.prototype.onData=function(data){var self=this;setTimeout(function(){Transport.prototype.onData.call(self,data)},0)}}WS.prototype.write=function(packets){var self=this;this.writable=false;for(var i=0,l=packets.length;i<l;i++){parser.encodePacket(packets[i],this.supportsBinary,function(data){try{self.ws.send(data)}catch(e){debug("websocket closed before onclose event")}})}function ondrain(){self.writable=true;self.emit("drain")}setTimeout(ondrain,0)};WS.prototype.onClose=function(){Transport.prototype.onClose.call(this)};WS.prototype.doClose=function(){if(typeof this.ws!=="undefined"){this.ws.close()}};WS.prototype.uri=function(){var query=this.query||{};var schema=this.secure?"wss":"ws";var port="";if(this.port&&("wss"==schema&&this.port!=443||"ws"==schema&&this.port!=80)){port=":"+this.port}if(this.timestampRequests){query[this.timestampParam]=+new Date}if(!this.supportsBinary){query.b64=1}query=parseqs.encode(query);if(query.length){query="?"+query}return schema+"://"+this.hostname+port+this.path+query};WS.prototype.check=function(){return!!WebSocket&&!("__initialize"in WebSocket&&this.name===WS.prototype.name)}},{"../transport":14,"component-inherit":21,debug:22,"engine.io-parser":25,parseqs:33,ws:35}],20:[function(_dereq_,module,exports){var hasCORS=_dereq_("has-cors");module.exports=function(opts){var xdomain=opts.xdomain;var xscheme=opts.xscheme;var enablesXDR=opts.enablesXDR;try{if("undefined"!=typeof XMLHttpRequest&&(!xdomain||hasCORS)){return new XMLHttpRequest}}catch(e){}try{if("undefined"!=typeof XDomainRequest&&!xscheme&&enablesXDR){return new XDomainRequest}}catch(e){}if(!xdomain){try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}},{"has-cors":38}],21:[function(_dereq_,module,exports){module.exports=function(a,b){var fn=function(){};fn.prototype=b.prototype;a.prototype=new fn;a.prototype.constructor=a}},{}],22:[function(_dereq_,module,exports){exports=module.exports=_dereq_("./debug");exports.log=log;exports.formatArgs=formatArgs;exports.save=save;exports.load=load;exports.useColors=useColors;exports.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"];function useColors(){return"WebkitAppearance"in document.documentElement.style||window.console&&(console.firebug||console.exception&&console.table)||navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31}exports.formatters.j=function(v){return JSON.stringify(v)};function formatArgs(){var args=arguments;var useColors=this.useColors;args[0]=(useColors?"%c":"")+this.namespace+(useColors?" %c":" ")+args[0]+(useColors?"%c ":" ")+"+"+exports.humanize(this.diff);if(!useColors)return args;var c="color: "+this.color;args=[args[0],c,"color: inherit"].concat(Array.prototype.slice.call(args,1));var index=0;var lastC=0;args[0].replace(/%[a-z%]/g,function(match){if("%%"===match)return;index++;if("%c"===match){lastC=index}});args.splice(lastC,0,c);return args}function log(){return"object"==typeof console&&"function"==typeof console.log&&Function.prototype.apply.call(console.log,console,arguments)}function save(namespaces){try{if(null==namespaces){localStorage.removeItem("debug")}else{localStorage.debug=namespaces}}catch(e){}}function load(){var r;try{r=localStorage.debug}catch(e){}return r}exports.enable(load())},{"./debug":23}],23:[function(_dereq_,module,exports){exports=module.exports=debug;exports.coerce=coerce;exports.disable=disable;exports.enable=enable;exports.enabled=enabled;exports.humanize=_dereq_("ms");exports.names=[];exports.skips=[];exports.formatters={};var prevColor=0;var prevTime;function selectColor(){return exports.colors[prevColor++%exports.colors.length]}function debug(namespace){function disabled(){}disabled.enabled=false;function enabled(){var self=enabled;var curr=+new Date;var ms=curr-(prevTime||curr);self.diff=ms;self.prev=prevTime;self.curr=curr;prevTime=curr;if(null==self.useColors)self.useColors=exports.useColors();if(null==self.color&&self.useColors)self.color=selectColor();var args=Array.prototype.slice.call(arguments);args[0]=exports.coerce(args[0]);if("string"!==typeof args[0]){args=["%o"].concat(args)}var index=0;args[0]=args[0].replace(/%([a-z%])/g,function(match,format){if(match==="%%")return match;index++;var formatter=exports.formatters[format];if("function"===typeof formatter){var val=args[index];match=formatter.call(self,val);args.splice(index,1);index--}return match});if("function"===typeof exports.formatArgs){args=exports.formatArgs.apply(self,args)}var logFn=enabled.log||exports.log||console.log.bind(console);logFn.apply(self,args)}enabled.enabled=true;var fn=exports.enabled(namespace)?enabled:disabled;fn.namespace=namespace;return fn}function enable(namespaces){exports.save(namespaces);var split=(namespaces||"").split(/[\s,]+/);var len=split.length;for(var i=0;i<len;i++){if(!split[i])continue;namespaces=split[i].replace(/\*/g,".*?");if(namespaces[0]==="-"){exports.skips.push(new RegExp("^"+namespaces.substr(1)+"$"))}else{exports.names.push(new RegExp("^"+namespaces+"$"))}}}function disable(){exports.enable("")}function enabled(name){var i,len;for(i=0,len=exports.skips.length;i<len;i++){if(exports.skips[i].test(name)){return false}}for(i=0,len=exports.names.length;i<len;i++){if(exports.names[i].test(name)){return true}}return false}function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}},{ms:24}],24:[function(_dereq_,module,exports){var s=1e3;var m=s*60;var h=m*60;var d=h*24;var y=d*365.25;module.exports=function(val,options){options=options||{};if("string"==typeof val)return parse(val);return options.long?long(val):short(val)};function parse(str){var match=/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);if(!match)return;var n=parseFloat(match[1]);var type=(match[2]||"ms").toLowerCase();switch(type){case"years":case"year":case"y":return n*y;case"days":case"day":case"d":return n*d;case"hours":case"hour":case"h":return n*h;case"minutes":case"minute":case"m":return n*m;case"seconds":case"second":case"s":return n*s;case"ms":return n}}function short(ms){if(ms>=d)return Math.round(ms/d)+"d";if(ms>=h)return Math.round(ms/h)+"h";if(ms>=m)return Math.round(ms/m)+"m";if(ms>=s)return Math.round(ms/s)+"s";return ms+"ms"}function long(ms){return plural(ms,d,"day")||plural(ms,h,"hour")||plural(ms,m,"minute")||plural(ms,s,"second")||ms+" ms"}function plural(ms,n,name){if(ms<n)return;if(ms<n*1.5)return Math.floor(ms/n)+" "+name;return Math.ceil(ms/n)+" "+name+"s"}},{}],25:[function(_dereq_,module,exports){(function(global){var keys=_dereq_("./keys");var hasBinary=_dereq_("has-binary");var sliceBuffer=_dereq_("arraybuffer.slice");var base64encoder=_dereq_("base64-arraybuffer");var after=_dereq_("after");var utf8=_dereq_("utf8");var isAndroid=navigator.userAgent.match(/Android/i);var isPhantomJS=/PhantomJS/i.test(navigator.userAgent);var dontSendBlobs=isAndroid||isPhantomJS;exports.protocol=3;var packets=exports.packets={open:0,close:1,ping:2,pong:3,message:4,upgrade:5,noop:6};var packetslist=keys(packets);var err={type:"error",data:"parser error"};var Blob=_dereq_("blob");exports.encodePacket=function(packet,supportsBinary,utf8encode,callback){if("function"==typeof supportsBinary){callback=supportsBinary;supportsBinary=false}if("function"==typeof utf8encode){callback=utf8encode;utf8encode=null}var data=packet.data===undefined?undefined:packet.data.buffer||packet.data;if(global.ArrayBuffer&&data instanceof ArrayBuffer){return encodeArrayBuffer(packet,supportsBinary,callback)}else if(Blob&&data instanceof global.Blob){return encodeBlob(packet,supportsBinary,callback)}if(data&&data.base64){return encodeBase64Object(packet,callback)}var encoded=packets[packet.type];if(undefined!==packet.data){encoded+=utf8encode?utf8.encode(String(packet.data)):String(packet.data)}return callback(""+encoded)};function encodeBase64Object(packet,callback){var message="b"+exports.packets[packet.type]+packet.data.data;return callback(message)}function encodeArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var data=packet.data;var contentArray=new Uint8Array(data);var resultBuffer=new Uint8Array(1+data.byteLength);resultBuffer[0]=packets[packet.type];for(var i=0;i<contentArray.length;i++){resultBuffer[i+1]=contentArray[i]}return callback(resultBuffer.buffer)}function encodeBlobAsArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var fr=new FileReader;fr.onload=function(){packet.data=fr.result;exports.encodePacket(packet,supportsBinary,true,callback)};return fr.readAsArrayBuffer(packet.data)}function encodeBlob(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}if(dontSendBlobs){return encodeBlobAsArrayBuffer(packet,supportsBinary,callback)}var length=new Uint8Array(1);length[0]=packets[packet.type];var blob=new Blob([length.buffer,packet.data]);return callback(blob)}exports.encodeBase64Packet=function(packet,callback){var message="b"+exports.packets[packet.type];if(Blob&&packet.data instanceof Blob){var fr=new FileReader;fr.onload=function(){var b64=fr.result.split(",")[1];callback(message+b64)};return fr.readAsDataURL(packet.data)}var b64data;try{b64data=String.fromCharCode.apply(null,new Uint8Array(packet.data))}catch(e){var typed=new Uint8Array(packet.data);var basic=new Array(typed.length);for(var i=0;i<typed.length;i++){basic[i]=typed[i]}b64data=String.fromCharCode.apply(null,basic)}message+=global.btoa(b64data);return callback(message)};exports.decodePacket=function(data,binaryType,utf8decode){if(typeof data=="string"||data===undefined){if(data.charAt(0)=="b"){return exports.decodeBase64Packet(data.substr(1),binaryType)}if(utf8decode){try{data=utf8.decode(data)}catch(e){return err}}var type=data.charAt(0);if(Number(type)!=type||!packetslist[type]){return err}if(data.length>1){return{type:packetslist[type],data:data.substring(1)}}else{return{type:packetslist[type]}}}var asArray=new Uint8Array(data);var type=asArray[0];var rest=sliceBuffer(data,1);if(Blob&&binaryType==="blob"){rest=new Blob([rest])}return{type:packetslist[type],data:rest}};exports.decodeBase64Packet=function(msg,binaryType){var type=packetslist[msg.charAt(0)];if(!global.ArrayBuffer){return{type:type,data:{base64:true,data:msg.substr(1)}}}var data=base64encoder.decode(msg.substr(1));if(binaryType==="blob"&&Blob){data=new Blob([data])}return{type:type,data:data}};exports.encodePayload=function(packets,supportsBinary,callback){if(typeof supportsBinary=="function"){callback=supportsBinary;supportsBinary=null}var isBinary=hasBinary(packets);if(supportsBinary&&isBinary){if(Blob&&!dontSendBlobs){return exports.encodePayloadAsBlob(packets,callback)}return exports.encodePayloadAsArrayBuffer(packets,callback)}if(!packets.length){return callback("0:")}function setLengthHeader(message){return message.length+":"+message}function encodeOne(packet,doneCallback){exports.encodePacket(packet,!isBinary?false:supportsBinary,true,function(message){doneCallback(null,setLengthHeader(message))})}map(packets,encodeOne,function(err,results){return callback(results.join(""))})};function map(ary,each,done){var result=new Array(ary.length);var next=after(ary.length,done);var eachWithIndex=function(i,el,cb){each(el,function(error,msg){result[i]=msg;cb(error,result)})};for(var i=0;i<ary.length;i++){eachWithIndex(i,ary[i],next)}}exports.decodePayload=function(data,binaryType,callback){if(typeof data!="string"){return exports.decodePayloadAsBinary(data,binaryType,callback)}if(typeof binaryType==="function"){callback=binaryType;binaryType=null}var packet;if(data==""){return callback(err,0,1)}var length="",n,msg;for(var i=0,l=data.length;i<l;i++){var chr=data.charAt(i);if(":"!=chr){length+=chr}else{if(""==length||length!=(n=Number(length))){return callback(err,0,1)}msg=data.substr(i+1,n);if(length!=msg.length){return callback(err,0,1)}if(msg.length){packet=exports.decodePacket(msg,binaryType,true);if(err.type==packet.type&&err.data==packet.data){return callback(err,0,1)}var ret=callback(packet,i+n,l);if(false===ret)return}i+=n;length=""}}if(length!=""){return callback(err,0,1)}};exports.encodePayloadAsArrayBuffer=function(packets,callback){if(!packets.length){return callback(new ArrayBuffer(0))}function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(data){return doneCallback(null,data)})}map(packets,encodeOne,function(err,encodedPackets){var totalLength=encodedPackets.reduce(function(acc,p){var len;if(typeof p==="string"){len=p.length}else{len=p.byteLength}return acc+len.toString().length+len+2},0);var resultArray=new Uint8Array(totalLength);var bufferIndex=0;encodedPackets.forEach(function(p){var isString=typeof p==="string";var ab=p;if(isString){var view=new Uint8Array(p.length);for(var i=0;i<p.length;i++){view[i]=p.charCodeAt(i)}ab=view.buffer}if(isString){resultArray[bufferIndex++]=0}else{resultArray[bufferIndex++]=1}var lenStr=ab.byteLength.toString();for(var i=0;i<lenStr.length;i++){resultArray[bufferIndex++]=parseInt(lenStr[i])}resultArray[bufferIndex++]=255;var view=new Uint8Array(ab);for(var i=0;i<view.length;i++){resultArray[bufferIndex++]=view[i]}});return callback(resultArray.buffer)})};exports.encodePayloadAsBlob=function(packets,callback){function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(encoded){var binaryIdentifier=new Uint8Array(1);binaryIdentifier[0]=1;if(typeof encoded==="string"){var view=new Uint8Array(encoded.length);for(var i=0;i<encoded.length;i++){view[i]=encoded.charCodeAt(i)}encoded=view.buffer;binaryIdentifier[0]=0}var len=encoded instanceof ArrayBuffer?encoded.byteLength:encoded.size;var lenStr=len.toString();var lengthAry=new Uint8Array(lenStr.length+1);for(var i=0;i<lenStr.length;i++){lengthAry[i]=parseInt(lenStr[i])}lengthAry[lenStr.length]=255;if(Blob){var blob=new Blob([binaryIdentifier.buffer,lengthAry.buffer,encoded]);doneCallback(null,blob)}})}map(packets,encodeOne,function(err,results){return callback(new Blob(results))})};exports.decodePayloadAsBinary=function(data,binaryType,callback){if(typeof binaryType==="function"){callback=binaryType;binaryType=null}var bufferTail=data;var buffers=[];var numberTooLong=false;while(bufferTail.byteLength>0){var tailArray=new Uint8Array(bufferTail);var isString=tailArray[0]===0;var msgLength="";for(var i=1;;i++){if(tailArray[i]==255)break;if(msgLength.length>310){numberTooLong=true;break}msgLength+=tailArray[i]}if(numberTooLong)return callback(err,0,1);bufferTail=sliceBuffer(bufferTail,2+msgLength.length);msgLength=parseInt(msgLength);var msg=sliceBuffer(bufferTail,0,msgLength);if(isString){try{msg=String.fromCharCode.apply(null,new Uint8Array(msg))}catch(e){var typed=new Uint8Array(msg);msg="";for(var i=0;i<typed.length;i++){msg+=String.fromCharCode(typed[i])}}}buffers.push(msg);bufferTail=sliceBuffer(bufferTail,msgLength)}var total=buffers.length;buffers.forEach(function(buffer,i){callback(exports.decodePacket(buffer,binaryType,true),i,total)})}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./keys":26,after:27,"arraybuffer.slice":28,"base64-arraybuffer":29,blob:30,"has-binary":36,utf8:31}],26:[function(_dereq_,module,exports){module.exports=Object.keys||function keys(obj){var arr=[];var has=Object.prototype.hasOwnProperty;for(var i in obj){if(has.call(obj,i)){arr.push(i)}}return arr}},{}],27:[function(_dereq_,module,exports){module.exports=after;function after(count,callback,err_cb){var bail=false;err_cb=err_cb||noop;proxy.count=count;return count===0?callback():proxy;function proxy(err,result){if(proxy.count<=0){throw new Error("after called too many times")}--proxy.count;if(err){bail=true;callback(err);callback=err_cb}else if(proxy.count===0&&!bail){callback(null,result)}}}function noop(){}},{}],28:[function(_dereq_,module,exports){module.exports=function(arraybuffer,start,end){var bytes=arraybuffer.byteLength;start=start||0;end=end||bytes;if(arraybuffer.slice){return arraybuffer.slice(start,end)}if(start<0){start+=bytes}if(end<0){end+=bytes}if(end>bytes){end=bytes}if(start>=bytes||start>=end||bytes===0){return new ArrayBuffer(0)}var abv=new Uint8Array(arraybuffer);var result=new Uint8Array(end-start);for(var i=start,ii=0;i<end;i++,ii++){result[ii]=abv[i]}return result.buffer}},{}],29:[function(_dereq_,module,exports){(function(chars){"use strict";exports.encode=function(arraybuffer){var bytes=new Uint8Array(arraybuffer),i,len=bytes.length,base64="";for(i=0;i<len;i+=3){base64+=chars[bytes[i]>>2];base64+=chars[(bytes[i]&3)<<4|bytes[i+1]>>4];base64+=chars[(bytes[i+1]&15)<<2|bytes[i+2]>>6];base64+=chars[bytes[i+2]&63]}if(len%3===2){base64=base64.substring(0,base64.length-1)+"="}else if(len%3===1){base64=base64.substring(0,base64.length-2)+"=="}return base64};exports.decode=function(base64){var bufferLength=base64.length*.75,len=base64.length,i,p=0,encoded1,encoded2,encoded3,encoded4;if(base64[base64.length-1]==="="){bufferLength--;if(base64[base64.length-2]==="="){bufferLength--}}var arraybuffer=new ArrayBuffer(bufferLength),bytes=new Uint8Array(arraybuffer);for(i=0;i<len;i+=4){encoded1=chars.indexOf(base64[i]);encoded2=chars.indexOf(base64[i+1]);encoded3=chars.indexOf(base64[i+2]);encoded4=chars.indexOf(base64[i+3]);bytes[p++]=encoded1<<2|encoded2>>4;bytes[p++]=(encoded2&15)<<4|encoded3>>2;bytes[p++]=(encoded3&3)<<6|encoded4&63}return arraybuffer}})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")},{}],30:[function(_dereq_,module,exports){(function(global){var BlobBuilder=global.BlobBuilder||global.WebKitBlobBuilder||global.MSBlobBuilder||global.MozBlobBuilder;var blobSupported=function(){try{var a=new Blob(["hi"]);return a.size===2}catch(e){return false}}();var blobSupportsArrayBufferView=blobSupported&&function(){try{var b=new Blob([new Uint8Array([1,2])]);return b.size===2}catch(e){return false}}();var blobBuilderSupported=BlobBuilder&&BlobBuilder.prototype.append&&BlobBuilder.prototype.getBlob;function mapArrayBufferViews(ary){for(var i=0;i<ary.length;i++){var chunk=ary[i];if(chunk.buffer instanceof ArrayBuffer){var buf=chunk.buffer;if(chunk.byteLength!==buf.byteLength){var copy=new Uint8Array(chunk.byteLength);copy.set(new Uint8Array(buf,chunk.byteOffset,chunk.byteLength));buf=copy.buffer}ary[i]=buf}}}function BlobBuilderConstructor(ary,options){options=options||{};var bb=new BlobBuilder;mapArrayBufferViews(ary);for(var i=0;i<ary.length;i++){bb.append(ary[i])}return options.type?bb.getBlob(options.type):bb.getBlob()}function BlobConstructor(ary,options){mapArrayBufferViews(ary);return new Blob(ary,options||{})}module.exports=function(){if(blobSupported){return blobSupportsArrayBufferView?global.Blob:BlobConstructor}else if(blobBuilderSupported){return BlobBuilderConstructor}else{return undefined}}()}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],31:[function(_dereq_,module,exports){(function(global){(function(root){var freeExports=typeof exports=="object"&&exports;var freeModule=typeof module=="object"&&module&&module.exports==freeExports&&module;var freeGlobal=typeof global=="object"&&global;if(freeGlobal.global===freeGlobal||freeGlobal.window===freeGlobal){root=freeGlobal}var stringFromCharCode=String.fromCharCode;function ucs2decode(string){var output=[];var counter=0;var length=string.length;var value;var extra;while(counter<length){value=string.charCodeAt(counter++);if(value>=55296&&value<=56319&&counter<length){extra=string.charCodeAt(counter++);if((extra&64512)==56320){output.push(((value&1023)<<10)+(extra&1023)+65536)}else{output.push(value);counter--}}else{output.push(value)}}return output}function ucs2encode(array){var length=array.length;var index=-1;var value;var output="";while(++index<length){value=array[index];if(value>65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value)}return output}function checkScalarValue(codePoint){if(codePoint>=55296&&codePoint<=57343){throw Error("Lone surrogate U+"+codePoint.toString(16).toUpperCase()+" is not a scalar value") -}}function createByte(codePoint,shift){return stringFromCharCode(codePoint>>shift&63|128)}function encodeCodePoint(codePoint){if((codePoint&4294967168)==0){return stringFromCharCode(codePoint)}var symbol="";if((codePoint&4294965248)==0){symbol=stringFromCharCode(codePoint>>6&31|192)}else if((codePoint&4294901760)==0){checkScalarValue(codePoint);symbol=stringFromCharCode(codePoint>>12&15|224);symbol+=createByte(codePoint,6)}else if((codePoint&4292870144)==0){symbol=stringFromCharCode(codePoint>>18&7|240);symbol+=createByte(codePoint,12);symbol+=createByte(codePoint,6)}symbol+=stringFromCharCode(codePoint&63|128);return symbol}function utf8encode(string){var codePoints=ucs2decode(string);var length=codePoints.length;var index=-1;var codePoint;var byteString="";while(++index<length){codePoint=codePoints[index];byteString+=encodeCodePoint(codePoint)}return byteString}function readContinuationByte(){if(byteIndex>=byteCount){throw Error("Invalid byte index")}var continuationByte=byteArray[byteIndex]&255;byteIndex++;if((continuationByte&192)==128){return continuationByte&63}throw Error("Invalid continuation byte")}function decodeSymbol(){var byte1;var byte2;var byte3;var byte4;var codePoint;if(byteIndex>byteCount){throw Error("Invalid byte index")}if(byteIndex==byteCount){return false}byte1=byteArray[byteIndex]&255;byteIndex++;if((byte1&128)==0){return byte1}if((byte1&224)==192){var byte2=readContinuationByte();codePoint=(byte1&31)<<6|byte2;if(codePoint>=128){return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&240)==224){byte2=readContinuationByte();byte3=readContinuationByte();codePoint=(byte1&15)<<12|byte2<<6|byte3;if(codePoint>=2048){checkScalarValue(codePoint);return codePoint}else{throw Error("Invalid continuation byte")}}if((byte1&248)==240){byte2=readContinuationByte();byte3=readContinuationByte();byte4=readContinuationByte();codePoint=(byte1&15)<<18|byte2<<12|byte3<<6|byte4;if(codePoint>=65536&&codePoint<=1114111){return codePoint}}throw Error("Invalid UTF-8 detected")}var byteArray;var byteCount;var byteIndex;function utf8decode(byteString){byteArray=ucs2decode(byteString);byteCount=byteArray.length;byteIndex=0;var codePoints=[];var tmp;while((tmp=decodeSymbol())!==false){codePoints.push(tmp)}return ucs2encode(codePoints)}var utf8={version:"2.0.0",encode:utf8encode,decode:utf8decode};if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){define(function(){return utf8})}else if(freeExports&&!freeExports.nodeType){if(freeModule){freeModule.exports=utf8}else{var object={};var hasOwnProperty=object.hasOwnProperty;for(var key in utf8){hasOwnProperty.call(utf8,key)&&(freeExports[key]=utf8[key])}}}else{root.utf8=utf8}})(this)}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],32:[function(_dereq_,module,exports){(function(global){var rvalidchars=/^[\],:{}\s]*$/;var rvalidescape=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;var rvalidtokens=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;var rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g;var rtrimLeft=/^\s+/;var rtrimRight=/\s+$/;module.exports=function parsejson(data){if("string"!=typeof data||!data){return null}data=data.replace(rtrimLeft,"").replace(rtrimRight,"");if(global.JSON&&JSON.parse){return JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return new Function("return "+data)()}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],33:[function(_dereq_,module,exports){exports.encode=function(obj){var str="";for(var i in obj){if(obj.hasOwnProperty(i)){if(str.length)str+="&";str+=encodeURIComponent(i)+"="+encodeURIComponent(obj[i])}}return str};exports.decode=function(qs){var qry={};var pairs=qs.split("&");for(var i=0,l=pairs.length;i<l;i++){var pair=pairs[i].split("=");qry[decodeURIComponent(pair[0])]=decodeURIComponent(pair[1])}return qry}},{}],34:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;var parts=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];module.exports=function parseuri(str){var src=str,b=str.indexOf("["),e=str.indexOf("]");if(b!=-1&&e!=-1){str=str.substring(0,b)+str.substring(b,e).replace(/:/g,";")+str.substring(e,str.length)}var m=re.exec(str||""),uri={},i=14;while(i--){uri[parts[i]]=m[i]||""}if(b!=-1&&e!=-1){uri.source=src;uri.host=uri.host.substring(1,uri.host.length-1).replace(/;/g,":");uri.authority=uri.authority.replace("[","").replace("]","").replace(/;/g,":");uri.ipv6uri=true}return uri}},{}],35:[function(_dereq_,module,exports){var global=function(){return this}();var WebSocket=global.WebSocket||global.MozWebSocket;module.exports=WebSocket?ws:null;function ws(uri,protocols,opts){var instance;if(protocols){instance=new WebSocket(uri,protocols)}else{instance=new WebSocket(uri)}return instance}if(WebSocket)ws.prototype=WebSocket.prototype},{}],36:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_("isarray");module.exports=hasBinary;function hasBinary(data){function _hasBinary(obj){if(!obj)return false;if(global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer||global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){return true}if(isArray(obj)){for(var i=0;i<obj.length;i++){if(_hasBinary(obj[i])){return true}}}else if(obj&&"object"==typeof obj){if(obj.toJSON){obj=obj.toJSON()}for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key)&&_hasBinary(obj[key])){return true}}}return false}return _hasBinary(data)}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{isarray:37}],37:[function(_dereq_,module,exports){module.exports=Array.isArray||function(arr){return Object.prototype.toString.call(arr)=="[object Array]"}},{}],38:[function(_dereq_,module,exports){var global=_dereq_("global");try{module.exports="XMLHttpRequest"in global&&"withCredentials"in new global.XMLHttpRequest}catch(err){module.exports=false}},{global:39}],39:[function(_dereq_,module,exports){module.exports=function(){return this}()},{}],40:[function(_dereq_,module,exports){var indexOf=[].indexOf;module.exports=function(arr,obj){if(indexOf)return arr.indexOf(obj);for(var i=0;i<arr.length;++i){if(arr[i]===obj)return i}return-1}},{}],41:[function(_dereq_,module,exports){var has=Object.prototype.hasOwnProperty;exports.keys=Object.keys||function(obj){var keys=[];for(var key in obj){if(has.call(obj,key)){keys.push(key)}}return keys};exports.values=function(obj){var vals=[];for(var key in obj){if(has.call(obj,key)){vals.push(obj[key])}}return vals};exports.merge=function(a,b){for(var key in b){if(has.call(b,key)){a[key]=b[key]}}return a};exports.length=function(obj){return exports.keys(obj).length};exports.isEmpty=function(obj){return 0==exports.length(obj)}},{}],42:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;var parts=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];module.exports=function parseuri(str){var m=re.exec(str||""),uri={},i=14;while(i--){uri[parts[i]]=m[i]||""}return uri}},{}],43:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_("isarray");var isBuf=_dereq_("./is-buffer");exports.deconstructPacket=function(packet){var buffers=[];var packetData=packet.data;function _deconstructPacket(data){if(!data)return data;if(isBuf(data)){var placeholder={_placeholder:true,num:buffers.length};buffers.push(data);return placeholder}else if(isArray(data)){var newData=new Array(data.length);for(var i=0;i<data.length;i++){newData[i]=_deconstructPacket(data[i])}return newData}else if("object"==typeof data&&!(data instanceof Date)){var newData={};for(var key in data){newData[key]=_deconstructPacket(data[key])}return newData}return data}var pack=packet;pack.data=_deconstructPacket(packetData);pack.attachments=buffers.length;return{packet:pack,buffers:buffers}};exports.reconstructPacket=function(packet,buffers){var curPlaceHolder=0;function _reconstructPacket(data){if(data&&data._placeholder){var buf=buffers[data.num];return buf}else if(isArray(data)){for(var i=0;i<data.length;i++){data[i]=_reconstructPacket(data[i])}return data}else if(data&&"object"==typeof data){for(var key in data){data[key]=_reconstructPacket(data[key])}return data}return data}packet.data=_reconstructPacket(packet.data);packet.attachments=undefined;return packet};exports.removeBlobs=function(data,callback){function _removeBlobs(obj,curKey,containingObject){if(!obj)return obj;if(global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){pendingBlobs++;var fileReader=new FileReader;fileReader.onload=function(){if(containingObject){containingObject[curKey]=this.result}else{bloblessData=this.result}if(!--pendingBlobs){callback(bloblessData)}};fileReader.readAsArrayBuffer(obj)}else if(isArray(obj)){for(var i=0;i<obj.length;i++){_removeBlobs(obj[i],i,obj)}}else if(obj&&"object"==typeof obj&&!isBuf(obj)){for(var key in obj){_removeBlobs(obj[key],key,obj)}}}var pendingBlobs=0;var bloblessData=data;_removeBlobs(bloblessData);if(!pendingBlobs){callback(bloblessData)}}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{"./is-buffer":45,isarray:46}],44:[function(_dereq_,module,exports){var debug=_dereq_("debug")("socket.io-parser");var json=_dereq_("json3");var isArray=_dereq_("isarray");var Emitter=_dereq_("component-emitter");var binary=_dereq_("./binary");var isBuf=_dereq_("./is-buffer");exports.protocol=4;exports.types=["CONNECT","DISCONNECT","EVENT","BINARY_EVENT","ACK","BINARY_ACK","ERROR"];exports.CONNECT=0;exports.DISCONNECT=1;exports.EVENT=2;exports.ACK=3;exports.ERROR=4;exports.BINARY_EVENT=5;exports.BINARY_ACK=6;exports.Encoder=Encoder;exports.Decoder=Decoder;function Encoder(){}Encoder.prototype.encode=function(obj,callback){debug("encoding packet %j",obj);if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){encodeAsBinary(obj,callback)}else{var encoding=encodeAsString(obj);callback([encoding])}};function encodeAsString(obj){var str="";var nsp=false;str+=obj.type;if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){str+=obj.attachments;str+="-"}if(obj.nsp&&"/"!=obj.nsp){nsp=true;str+=obj.nsp}if(null!=obj.id){if(nsp){str+=",";nsp=false}str+=obj.id}if(null!=obj.data){if(nsp)str+=",";str+=json.stringify(obj.data)}debug("encoded %j as %s",obj,str);return str}function encodeAsBinary(obj,callback){function writeEncoding(bloblessData){var deconstruction=binary.deconstructPacket(bloblessData);var pack=encodeAsString(deconstruction.packet);var buffers=deconstruction.buffers;buffers.unshift(pack);callback(buffers)}binary.removeBlobs(obj,writeEncoding)}function Decoder(){this.reconstructor=null}Emitter(Decoder.prototype);Decoder.prototype.add=function(obj){var packet;if("string"==typeof obj){packet=decodeString(obj);if(exports.BINARY_EVENT==packet.type||exports.BINARY_ACK==packet.type){this.reconstructor=new BinaryReconstructor(packet);if(this.reconstructor.reconPack.attachments===0){this.emit("decoded",packet)}}else{this.emit("decoded",packet)}}else if(isBuf(obj)||obj.base64){if(!this.reconstructor){throw new Error("got binary data when not reconstructing a packet")}else{packet=this.reconstructor.takeBinaryData(obj);if(packet){this.reconstructor=null;this.emit("decoded",packet)}}}else{throw new Error("Unknown type: "+obj)}};function decodeString(str){var p={};var i=0;p.type=Number(str.charAt(0));if(null==exports.types[p.type])return error();if(exports.BINARY_EVENT==p.type||exports.BINARY_ACK==p.type){var buf="";while(str.charAt(++i)!="-"){buf+=str.charAt(i);if(i==str.length)break}if(buf!=Number(buf)||str.charAt(i)!="-"){throw new Error("Illegal attachments")}p.attachments=Number(buf)}if("/"==str.charAt(i+1)){p.nsp="";while(++i){var c=str.charAt(i);if(","==c)break;p.nsp+=c;if(i==str.length)break}}else{p.nsp="/"}var next=str.charAt(i+1);if(""!==next&&Number(next)==next){p.id="";while(++i){var c=str.charAt(i);if(null==c||Number(c)!=c){--i;break}p.id+=str.charAt(i);if(i==str.length)break}p.id=Number(p.id)}if(str.charAt(++i)){try{p.data=json.parse(str.substr(i))}catch(e){return error()}}debug("decoded %s as %j",str,p);return p}Decoder.prototype.destroy=function(){if(this.reconstructor){this.reconstructor.finishedReconstruction()}};function BinaryReconstructor(packet){this.reconPack=packet;this.buffers=[]}BinaryReconstructor.prototype.takeBinaryData=function(binData){this.buffers.push(binData);if(this.buffers.length==this.reconPack.attachments){var packet=binary.reconstructPacket(this.reconPack,this.buffers);this.finishedReconstruction();return packet}return null};BinaryReconstructor.prototype.finishedReconstruction=function(){this.reconPack=null;this.buffers=[]};function error(data){return{type:exports.ERROR,data:"parser error"}}},{"./binary":43,"./is-buffer":45,"component-emitter":9,debug:10,isarray:46,json3:47}],45:[function(_dereq_,module,exports){(function(global){module.exports=isBuf;function isBuf(obj){return global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer}}).call(this,typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],46:[function(_dereq_,module,exports){module.exports=_dereq_(37)},{}],47:[function(_dereq_,module,exports){(function(window){var getClass={}.toString,isProperty,forEach,undef;var isLoader=typeof define==="function"&&define.amd;var nativeJSON=typeof JSON=="object"&&JSON;var JSON3=typeof exports=="object"&&exports&&!exports.nodeType&&exports;if(JSON3&&nativeJSON){JSON3.stringify=nativeJSON.stringify;JSON3.parse=nativeJSON.parse}else{JSON3=window.JSON=nativeJSON||{}}var isExtended=new Date(-0xc782b5b800cec);try{isExtended=isExtended.getUTCFullYear()==-109252&&isExtended.getUTCMonth()===0&&isExtended.getUTCDate()===1&&isExtended.getUTCHours()==10&&isExtended.getUTCMinutes()==37&&isExtended.getUTCSeconds()==6&&isExtended.getUTCMilliseconds()==708}catch(exception){}function has(name){if(has[name]!==undef){return has[name]}var isSupported;if(name=="bug-string-char-index"){isSupported="a"[0]!="a"}else if(name=="json"){isSupported=has("json-stringify")&&has("json-parse")}else{var value,serialized='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if(name=="json-stringify"){var stringify=JSON3.stringify,stringifySupported=typeof stringify=="function"&&isExtended;if(stringifySupported){(value=function(){return 1}).toJSON=value;try{stringifySupported=stringify(0)==="0"&&stringify(new Number)==="0"&&stringify(new String)=='""'&&stringify(getClass)===undef&&stringify(undef)===undef&&stringify()===undef&&stringify(value)==="1"&&stringify([value])=="[1]"&&stringify([undef])=="[null]"&&stringify(null)=="null"&&stringify([undef,getClass,null])=="[null,null,null]"&&stringify({a:[value,true,false,null,"\x00\b\n\f\r "]})==serialized&&stringify(null,value)==="1"&&stringify([1,2],null,1)=="[\n 1,\n 2\n]"&&stringify(new Date(-864e13))=='"-271821-04-20T00:00:00.000Z"'&&stringify(new Date(864e13))=='"+275760-09-13T00:00:00.000Z"'&&stringify(new Date(-621987552e5))=='"-000001-01-01T00:00:00.000Z"'&&stringify(new Date(-1))=='"1969-12-31T23:59:59.999Z"'}catch(exception){stringifySupported=false}}isSupported=stringifySupported}if(name=="json-parse"){var parse=JSON3.parse;if(typeof parse=="function"){try{if(parse("0")===0&&!parse(false)){value=parse(serialized);var parseSupported=value["a"].length==5&&value["a"][0]===1;if(parseSupported){try{parseSupported=!parse('" "')}catch(exception){}if(parseSupported){try{parseSupported=parse("01")!==1}catch(exception){}}if(parseSupported){try{parseSupported=parse("1.")!==1}catch(exception){}}}}}catch(exception){parseSupported=false}}isSupported=parseSupported}}return has[name]=!!isSupported}if(!has("json")){var functionClass="[object Function]";var dateClass="[object Date]";var numberClass="[object Number]";var stringClass="[object String]";var arrayClass="[object Array]";var booleanClass="[object Boolean]";var charIndexBuggy=has("bug-string-char-index");if(!isExtended){var floor=Math.floor;var Months=[0,31,59,90,120,151,181,212,243,273,304,334];var getDay=function(year,month){return Months[month]+365*(year-1970)+floor((year-1969+(month=+(month>1)))/4)-floor((year-1901+month)/100)+floor((year-1601+month)/400)}}if(!(isProperty={}.hasOwnProperty)){isProperty=function(property){var members={},constructor;if((members.__proto__=null,members.__proto__={toString:1},members).toString!=getClass){isProperty=function(property){var original=this.__proto__,result=property in(this.__proto__=null,this);this.__proto__=original;return result}}else{constructor=members.constructor;isProperty=function(property){var parent=(this.constructor||constructor).prototype;return property in this&&!(property in parent&&this[property]===parent[property])}}members=null;return isProperty.call(this,property)}}var PrimitiveTypes={"boolean":1,number:1,string:1,undefined:1};var isHostType=function(object,property){var type=typeof object[property];return type=="object"?!!object[property]:!PrimitiveTypes[type]};forEach=function(object,callback){var size=0,Properties,members,property;(Properties=function(){this.valueOf=0}).prototype.valueOf=0;members=new Properties;for(property in members){if(isProperty.call(members,property)){size++}}Properties=members=null;if(!size){members=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,length;var hasProperty=!isFunction&&typeof object.constructor!="function"&&isHostType(object,"hasOwnProperty")?object.hasOwnProperty:isProperty;for(property in object){if(!(isFunction&&property=="prototype")&&hasProperty.call(object,property)){callback(property)}}for(length=members.length;property=members[--length];hasProperty.call(object,property)&&callback(property));}}else if(size==2){forEach=function(object,callback){var members={},isFunction=getClass.call(object)==functionClass,property;for(property in object){if(!(isFunction&&property=="prototype")&&!isProperty.call(members,property)&&(members[property]=1)&&isProperty.call(object,property)){callback(property)}}}}else{forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,isConstructor;for(property in object){if(!(isFunction&&property=="prototype")&&isProperty.call(object,property)&&!(isConstructor=property==="constructor")){callback(property)}}if(isConstructor||isProperty.call(object,property="constructor")){callback(property)}}}return forEach(object,callback)};if(!has("json-stringify")){var Escapes={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"};var leadingZeroes="000000";var toPaddedString=function(width,value){return(leadingZeroes+(value||0)).slice(-width)};var unicodePrefix="\\u00";var quote=function(value){var result='"',index=0,length=value.length,isLarge=length>10&&charIndexBuggy,symbols;if(isLarge){symbols=value.split("")}for(;index<length;index++){var charCode=value.charCodeAt(index);switch(charCode){case 8:case 9:case 10:case 12:case 13:case 34:case 92:result+=Escapes[charCode];break;default:if(charCode<32){result+=unicodePrefix+toPaddedString(2,charCode.toString(16));break}result+=isLarge?symbols[index]:charIndexBuggy?value.charAt(index):value[index]}}return result+'"'};var serialize=function(property,object,callback,properties,whitespace,indentation,stack){var value,className,year,month,date,time,hours,minutes,seconds,milliseconds,results,element,index,length,prefix,result;try{value=object[property]}catch(exception){}if(typeof value=="object"&&value){className=getClass.call(value);if(className==dateClass&&!isProperty.call(value,"toJSON")){if(value>-1/0&&value<1/0){if(getDay){date=floor(value/864e5);for(year=floor(date/365.2425)+1970-1;getDay(year+1,0)<=date;year++);for(month=floor((date-getDay(year,0))/30.42);getDay(year,month+1)<=date;month++);date=1+date-getDay(year,month);time=(value%864e5+864e5)%864e5;hours=floor(time/36e5)%24;minutes=floor(time/6e4)%60;seconds=floor(time/1e3)%60;milliseconds=time%1e3}else{year=value.getUTCFullYear();month=value.getUTCMonth();date=value.getUTCDate();hours=value.getUTCHours();minutes=value.getUTCMinutes();seconds=value.getUTCSeconds();milliseconds=value.getUTCMilliseconds()}value=(year<=0||year>=1e4?(year<0?"-":"+")+toPaddedString(6,year<0?-year:year):toPaddedString(4,year))+"-"+toPaddedString(2,month+1)+"-"+toPaddedString(2,date)+"T"+toPaddedString(2,hours)+":"+toPaddedString(2,minutes)+":"+toPaddedString(2,seconds)+"."+toPaddedString(3,milliseconds)+"Z"}else{value=null}}else if(typeof value.toJSON=="function"&&(className!=numberClass&&className!=stringClass&&className!=arrayClass||isProperty.call(value,"toJSON"))){value=value.toJSON(property)}}if(callback){value=callback.call(object,property,value)}if(value===null){return"null"}className=getClass.call(value);if(className==booleanClass){return""+value}else if(className==numberClass){return value>-1/0&&value<1/0?""+value:"null"}else if(className==stringClass){return quote(""+value)}if(typeof value=="object"){for(length=stack.length;length--;){if(stack[length]===value){throw TypeError()}}stack.push(value);results=[];prefix=indentation;indentation+=whitespace;if(className==arrayClass){for(index=0,length=value.length;index<length;index++){element=serialize(index,value,callback,properties,whitespace,indentation,stack);results.push(element===undef?"null":element)}result=results.length?whitespace?"[\n"+indentation+results.join(",\n"+indentation)+"\n"+prefix+"]":"["+results.join(",")+"]":"[]"}else{forEach(properties||value,function(property){var element=serialize(property,value,callback,properties,whitespace,indentation,stack);if(element!==undef){results.push(quote(property)+":"+(whitespace?" ":"")+element)}});result=results.length?whitespace?"{\n"+indentation+results.join(",\n"+indentation)+"\n"+prefix+"}":"{"+results.join(",")+"}":"{}"}stack.pop();return result}};JSON3.stringify=function(source,filter,width){var whitespace,callback,properties,className;if(typeof filter=="function"||typeof filter=="object"&&filter){if((className=getClass.call(filter))==functionClass){callback=filter}else if(className==arrayClass){properties={};for(var index=0,length=filter.length,value;index<length;value=filter[index++],(className=getClass.call(value),className==stringClass||className==numberClass)&&(properties[value]=1));}}if(width){if((className=getClass.call(width))==numberClass){if((width-=width%1)>0){for(whitespace="",width>10&&(width=10);whitespace.length<width;whitespace+=" ");}}else if(className==stringClass){whitespace=width.length<=10?width:width.slice(0,10)}}return serialize("",(value={},value[""]=source,value),callback,properties,whitespace,"",[])}}if(!has("json-parse")){var fromCharCode=String.fromCharCode;var Unescapes={92:"\\",34:'"',47:"/",98:"\b",116:" ",110:"\n",102:"\f",114:"\r"};var Index,Source;var abort=function(){Index=Source=null;throw SyntaxError()};var lex=function(){var source=Source,length=source.length,value,begin,position,isSigned,charCode;while(Index<length){charCode=source.charCodeAt(Index);switch(charCode){case 9:case 10:case 13:case 32:Index++;break;case 123:case 125:case 91:case 93:case 58:case 44:value=charIndexBuggy?source.charAt(Index):source[Index];Index++;return value;case 34:for(value="@",Index++;Index<length;){charCode=source.charCodeAt(Index);if(charCode<32){abort()}else if(charCode==92){charCode=source.charCodeAt(++Index);switch(charCode){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:value+=Unescapes[charCode];Index++;break;case 117:begin=++Index;for(position=Index+4;Index<position;Index++){charCode=source.charCodeAt(Index);if(!(charCode>=48&&charCode<=57||charCode>=97&&charCode<=102||charCode>=65&&charCode<=70)){abort()}}value+=fromCharCode("0x"+source.slice(begin,Index));break;default:abort()}}else{if(charCode==34){break}charCode=source.charCodeAt(Index);begin=Index;while(charCode>=32&&charCode!=92&&charCode!=34){charCode=source.charCodeAt(++Index)}value+=source.slice(begin,Index)}}if(source.charCodeAt(Index)==34){Index++;return value}abort();default:begin=Index;if(charCode==45){isSigned=true;charCode=source.charCodeAt(++Index)}if(charCode>=48&&charCode<=57){if(charCode==48&&(charCode=source.charCodeAt(Index+1),charCode>=48&&charCode<=57)){abort()}isSigned=false;for(;Index<length&&(charCode=source.charCodeAt(Index),charCode>=48&&charCode<=57);Index++);if(source.charCodeAt(Index)==46){position=++Index;for(;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}charCode=source.charCodeAt(Index);if(charCode==101||charCode==69){charCode=source.charCodeAt(++Index);if(charCode==43||charCode==45){Index++}for(position=Index;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}return+source.slice(begin,Index)}if(isSigned){abort()}if(source.slice(Index,Index+4)=="true"){Index+=4;return true}else if(source.slice(Index,Index+5)=="false"){Index+=5;return false}else if(source.slice(Index,Index+4)=="null"){Index+=4;return null}abort()}}return"$"};var get=function(value){var results,hasMembers;if(value=="$"){abort()}if(typeof value=="string"){if((charIndexBuggy?value.charAt(0):value[0])=="@"){return value.slice(1)}if(value=="["){results=[];for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="]"){break}if(hasMembers){if(value==","){value=lex();if(value=="]"){abort()}}else{abort()}}if(value==","){abort()}results.push(get(value))}return results}else if(value=="{"){results={};for(;;hasMembers||(hasMembers=true)){value=lex();if(value=="}"){break}if(hasMembers){if(value==","){value=lex();if(value=="}"){abort()}}else{abort()}}if(value==","||typeof value!="string"||(charIndexBuggy?value.charAt(0):value[0])!="@"||lex()!=":"){abort()}results[value.slice(1)]=get(lex())}return results}abort()}return value};var update=function(source,property,callback){var element=walk(source,property,callback);if(element===undef){delete source[property]}else{source[property]=element}};var walk=function(source,property,callback){var value=source[property],length;if(typeof value=="object"&&value){if(getClass.call(value)==arrayClass){for(length=value.length;length--;){update(value,length,callback)}}else{forEach(value,function(property){update(value,property,callback)})}}return callback.call(source,property,value)};JSON3.parse=function(source,callback){var result,value;Index=0;Source=""+source;result=get(lex());if(lex()!="$"){abort()}Index=Source=null;return callback&&getClass.call(callback)==functionClass?walk((value={},value[""]=result,value),"",callback):result}}}if(isLoader){define(function(){return JSON3})}})(this)},{}],48:[function(_dereq_,module,exports){module.exports=toArray;function toArray(list,index){var array=[];index=index||0;for(var i=index||0;i<list.length;i++){array[i-index]=list[i]}return array}},{}]},{},[1])(1)}); \ No newline at end of file