diff --git a/README.md b/README.md index e144a051a..1467d43ed 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The source of truth for the [utopia-php](https://github.com/utopia-php) libraries. Each `packages/` is an independent Composer library; development happens here, and every push is mirrored to its read-only repository (e.g. `utopia-php/http`), so Composer/Packagist distribution is unchanged — mechanics in [docs/distribution.md](docs/distribution.md). -[`utopia-php/auth`](https://github.com/appwrite/appwrite/tree/main/packages/auth), [`utopia-php/cache`](https://github.com/appwrite/appwrite/tree/main/packages/cache), [`utopia-php/cdn`](https://github.com/appwrite/appwrite/tree/main/packages/cdn), [`utopia-php/circuit-breaker`](https://github.com/appwrite/appwrite/tree/main/packages/circuit-breaker), [`utopia-php/client`](https://github.com/appwrite/appwrite/tree/main/packages/client), [`utopia-php/compression`](https://github.com/appwrite/appwrite/tree/main/packages/compression), [`utopia-php/di`](https://github.com/appwrite/appwrite/tree/main/packages/di), [`utopia-php/image`](https://github.com/appwrite/appwrite/tree/main/packages/image), [`utopia-php/messaging`](https://github.com/appwrite/appwrite/tree/main/packages/messaging), [`utopia-php/openapi`](https://github.com/appwrite/appwrite/tree/main/packages/openapi), [`utopia-php/pools`](https://github.com/appwrite/appwrite/tree/main/packages/pools), [`utopia-php/schedule`](https://github.com/appwrite/appwrite/tree/main/packages/schedule), [`utopia-php/servers`](https://github.com/appwrite/appwrite/tree/main/packages/servers), [`utopia-php/smtp`](https://github.com/appwrite/appwrite/tree/main/packages/smtp), [`utopia-php/span`](https://github.com/appwrite/appwrite/tree/main/packages/span), [`utopia-php/system`](https://github.com/appwrite/appwrite/tree/main/packages/system), [`utopia-php/telemetry`](https://github.com/appwrite/appwrite/tree/main/packages/telemetry), [`utopia-php/user-agent`](https://github.com/appwrite/appwrite/tree/main/packages/user-agent), [`utopia-php/validators`](https://github.com/appwrite/appwrite/tree/main/packages/validators) and [`utopia-php/websocket`](https://github.com/appwrite/appwrite/tree/main/packages/websocket) are maintained in Appwrite. Their distribution mirrors and Packagist packages remain available. +[`utopia-php/auth`](https://github.com/appwrite/appwrite/tree/main/packages/auth), [`utopia-php/cache`](https://github.com/appwrite/appwrite/tree/main/packages/cache), [`utopia-php/cdn`](https://github.com/appwrite/appwrite/tree/main/packages/cdn), [`utopia-php/circuit-breaker`](https://github.com/appwrite/appwrite/tree/main/packages/circuit-breaker), [`utopia-php/client`](https://github.com/appwrite/appwrite/tree/main/packages/client), [`utopia-php/compression`](https://github.com/appwrite/appwrite/tree/main/packages/compression), [`utopia-php/di`](https://github.com/appwrite/appwrite/tree/main/packages/di), [`utopia-php/image`](https://github.com/appwrite/appwrite/tree/main/packages/image), [`utopia-php/messaging`](https://github.com/appwrite/appwrite/tree/main/packages/messaging), [`utopia-php/openapi`](https://github.com/appwrite/appwrite/tree/main/packages/openapi), [`utopia-php/pools`](https://github.com/appwrite/appwrite/tree/main/packages/pools), [`utopia-php/schedule`](https://github.com/appwrite/appwrite/tree/main/packages/schedule), [`utopia-php/servers`](https://github.com/appwrite/appwrite/tree/main/packages/servers), [`utopia-php/smtp`](https://github.com/appwrite/appwrite/tree/main/packages/smtp), [`utopia-php/span`](https://github.com/appwrite/appwrite/tree/main/packages/span), [`utopia-php/storage`](https://github.com/appwrite/appwrite/tree/main/packages/storage), [`utopia-php/system`](https://github.com/appwrite/appwrite/tree/main/packages/system), [`utopia-php/telemetry`](https://github.com/appwrite/appwrite/tree/main/packages/telemetry), [`utopia-php/user-agent`](https://github.com/appwrite/appwrite/tree/main/packages/user-agent), [`utopia-php/validators`](https://github.com/appwrite/appwrite/tree/main/packages/validators) and [`utopia-php/websocket`](https://github.com/appwrite/appwrite/tree/main/packages/websocket) are maintained in Appwrite. Their distribution mirrors and Packagist packages remain available. ## Quickstart @@ -62,7 +62,6 @@ graph TD nats replication reputation - storage vcs ``` diff --git a/packages/storage/.github/workflows/mirror.yml b/packages/storage/.github/workflows/mirror.yml deleted file mode 100644 index 2ca108037..000000000 --- a/packages/storage/.github/workflows/mirror.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Mirror - -on: - pull_request_target: - types: [opened] - issues: - types: [opened] - -permissions: - issues: write - pull-requests: write - -jobs: - redirect: - uses: utopia-php/monorepo/.github/workflows/mirror-redirect.yml@main - with: - package: storage diff --git a/packages/storage/.gitignore b/packages/storage/.gitignore deleted file mode 100644 index a039af172..000000000 --- a/packages/storage/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/vendor/ -/.vscode/ -.phpunit.result.cache -tests/chunk.php -.idea/ -.env -.DS_Store -composer.lock diff --git a/packages/storage/LICENSE b/packages/storage/LICENSE deleted file mode 100644 index ac621e7df..000000000 --- a/packages/storage/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 utopia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/storage/README.md b/packages/storage/README.md deleted file mode 100644 index 4af308a45..000000000 --- a/packages/storage/README.md +++ /dev/null @@ -1,411 +0,0 @@ -# Utopia Storage - -> [!IMPORTANT] -> This repository is a read-only mirror of the [utopia-php monorepo](https://github.com/utopia-php/monorepo). Development happens in [`packages/storage`](https://github.com/utopia-php/monorepo/tree/main/packages/storage) — please open issues and pull requests there. - -![Total Downloads](https://img.shields.io/packagist/dt/utopia-php/storage.svg) -[![Discord](https://img.shields.io/discord/564160730845151244?label=discord)](https://appwrite.io/discord) - -Utopia Storage is a simple and lightweight library for managing application storage across multiple adapters. This library is designed to be easy to learn and use, with a consistent API regardless of the storage provider. This library is maintained by the [Appwrite team](https://appwrite.io). - -This library is part of the [Utopia Framework](https://github.com/utopia-php/framework) project. - -## Getting started - -Install using Composer: -```bash -composer require utopia-php/storage -``` - -### Basic usage - -Devices are immutable value objects: construct one with its configuration and use it anywhere, including across coroutines. - -```php -upload(Stream::fromResource(fopen('/local/path/to/file.png', 'rb')), 'destination/path/file.png', 'image/png'); - -// Check if file exists -$exists = $device->exists('destination/path/file.png'); - -// Read file contents as a stream -$contents = (string) $device->read('destination/path/file.png'); - -// Delete a file -$device->delete('destination/path/file.png'); -``` - -## Available adapters - -### Local storage - -Use the local filesystem for storing files. - -```php -use Utopia\Storage\Device\Local; - -$device = new Local('/path/to/storage'); -``` - -### AWS S3 - -Store files in Amazon S3 or compatible services. - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\S3; - -$device = new S3( - 'root', // Root path in bucket - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME.s3.us-east-1.amazonaws.com', // Host - 'us-east-1', // Region - Acl::Private, // Access control (default: private) - bucket: 'YOUR_BUCKET_NAME', // Optional: enables server-side copy -); -``` - -When the bucket name is known, a same-device `copy()` — and therefore `move()` — runs entirely server side (`CopyObject`, or `UploadPartCopy` above 5 GB), so no bytes move through PHP. The provider-specific adapters below pass their bucket automatically. Without it, `copy()` falls back to a streamed download and re-upload. - -The provider-specific adapters below build the host for you from a bucket and region. Every S3-family adapter also accepts optional named constructor arguments: - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\AWS; - -$device = new AWS( - 'root', - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME', - AWS::US_EAST_1, - Acl::Private, - client: $psrClient, // any PSR-18 client (default: utopia-php/client with retries, see below) -); - -// Available ACL options -// Acl::Private, Acl::PublicRead, Acl::PublicReadWrite, Acl::AuthenticatedRead -// Pass null to write without an ACL, which buckets that have ACLs disabled require -``` - -### DigitalOcean Spaces - -Store files in DigitalOcean Spaces. - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\DOSpaces; - -$device = new DOSpaces( - 'root', // Root path in bucket - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME', - DOSpaces::NYC3, // Region (default: nyc3) - Acl::Private // Access control (default: private) -); - -// Available regions -// DOSpaces::NYC3, DOSpaces::SGP1, DOSpaces::FRA1, DOSpaces::SFO2, DOSpaces::SFO3, DOSpaces::AMS3 -``` - -### Backblaze B2 - -Store files in Backblaze B2 Cloud Storage. - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\Backblaze; - -$device = new Backblaze( - 'root', // Root path in bucket - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME', - Backblaze::US_WEST_004, // Region (default: us-west-004) - Acl::Private // Access control (default: private) -); - -// Available regions (clusters) -// Backblaze::US_WEST_000, Backblaze::US_WEST_001, Backblaze::US_WEST_002, -// Backblaze::US_WEST_004, Backblaze::EU_CENTRAL_003 -``` - -### Linode Object Storage - -Store files in Linode Object Storage. - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\Linode; - -$device = new Linode( - 'root', // Root path in bucket - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME', - Linode::EU_CENTRAL_1, // Region (default: eu-central-1) - Acl::Private // Access control (default: private) -); - -// Available regions -// Linode::EU_CENTRAL_1, Linode::US_SOUTHEAST_1, Linode::US_EAST_1, Linode::AP_SOUTH_1 -``` - -### Wasabi cloud storage - -Store files in Wasabi Cloud Storage. - -```php -use Utopia\Storage\Acl; -use Utopia\Storage\Device\Wasabi; - -$device = new Wasabi( - 'root', // Root path in bucket - 'YOUR_ACCESS_KEY', - 'YOUR_SECRET_KEY', - 'YOUR_BUCKET_NAME', - Wasabi::EU_CENTRAL_1, // Region (default: eu-central-1) - Acl::Private // Access control (default: private) -); - -// Available regions -// Wasabi::US_EAST_1, Wasabi::US_EAST_2, Wasabi::US_WEST_1, Wasabi::US_CENTRAL_1, -// Wasabi::EU_CENTRAL_1, Wasabi::EU_CENTRAL_2, Wasabi::EU_WEST_1, Wasabi::EU_WEST_2, -// Wasabi::AP_NORTHEAST_1, Wasabi::AP_NORTHEAST_2 -``` - -## Common operations - -All storage adapters provide a consistent API for working with files: - -```php -use Utopia\Psr7\Stream; - -// Upload a file from disk without loading it into memory -$device->upload(Stream::fromResource(fopen('/path/to/local/file.jpg', 'rb')), 'remote/path/file.jpg', 'image/jpeg'); - -// Contents already in memory wrap into a stream for free -$device->upload(new Stream($data), 'remote/path/file.jpg', 'image/jpeg'); - -// Check if file exists -$exists = $device->exists('remote/path/file.jpg'); - -// Get file size -$size = $device->getFileSize('remote/path/file.jpg'); - -// Get file MIME type -$mime = $device->getFileMimeType('remote/path/file.jpg'); - -// Get file MD5 hash -$hash = $device->getFileHash('remote/path/file.jpg'); - -// Size, last modification and ETag in one request -$info = $device->getFileInfo('remote/path/file.jpg'); - -// Read file contents as a PSR-7 stream; casting to string buffers it -$stream = $device->read('remote/path/file.jpg'); - -// Read partial file contents -$chunk = (string) $device->read('remote/path/file.jpg', 0, 1024); // Read first 1KB - -// Multipart/chunked uploads — part 1 of 3 -$metadata = []; -$device->upload(new Stream($firstChunk), 'remote/video.mp4', 'video/mp4', 1, 3, $metadata); - -// Resumable uploads: prepare, upload chunks in any order, finalize -$device->prepare('remote/video.mp4', 'video/mp4', 3, $metadata); -$device->upload(new Stream($secondChunk), 'remote/video.mp4', 'video/mp4', 2, 3, $metadata); -$device->finalize('remote/video.mp4', 3, $metadata); - -// Streaming uploads whose chunk count is unknown up front: pass 0 chunks, then finalize with the final count -$device->upload(new Stream($firstChunk), 'remote/video.mp4', 'video/mp4', 1, 0, $metadata); -$device->upload(new Stream($secondChunk), 'remote/video.mp4', 'video/mp4', 2, 0, $metadata); -$device->finalize('remote/video.mp4', 2, $metadata); // replaces whatever was at the path - -// List files under a prefix, one page at a time -$list = $device->listFiles('remote/directory', 100); -foreach ($list->files as $file) { - echo $file->path . ' (' . $file->size . " bytes)\n"; -} -if ($list->cursor !== null) { - $list = $device->listFiles('remote/directory', 100, $list->cursor); // Next page -} - -// Delete file -$device->delete('remote/path/file.jpg'); - -// Delete directory -$device->deletePath('remote/directory'); - -// Copy a file, on the same device or onto another one -$device->copy('source/path.jpg', 'target/path.jpg'); -$sourceDevice->copy('source/path.jpg', 'target/path.jpg', $targetDevice); - -// Copy with a custom chunk size (default: 20 MB) -$sourceDevice->copy('source/path.jpg', 'target/path.jpg', $targetDevice, 10000000); - -// Move is copy plus delete -$device->move('source/path.jpg', 'target/path.jpg'); -``` - -### Conditional operations - -Every file carries an ETag, reported by `getFileInfo()` and returned by every write, conditional or not. Naming it makes an operation apply to that version of the file and no other, which is what coordinating several processes through one file takes: a lock, a lease, or a dataset that must never be read half old and half new. - -```php -use Utopia\Storage\Exception\PreconditionFailedException; - -// Write only where nothing is yet; exactly one of several racing callers succeeds -try { - $etag = $device->create('locks/refresh', new Stream($token), 'text/plain'); -} catch (PreconditionFailedException) { - // Someone else holds it -} - -// Write over one version only; a stale ETag is refused -$etag = $device->replace('locks/refresh', new Stream($token), $etag, 'text/plain'); - -// Read only while the file still is the version you know -$chunk = $device->read('dataset.bin', $offset, $length, $etag); -``` - -On S3 the check and the operation are one request (`If-None-Match`, `If-Match`), so nothing can slip in between. On the local disk the ETag is the file's MD5 hash. `create()` opens the file exclusively and has no window at all; `replace()` checks the hash before writing, so a replacement landing between the two goes unnoticed and the last writer wins. Local writes land by renaming a finished temporary file over the path, so a reader never sees two versions mixed and a write that fails part way leaves the previous one in place. A conditional read on `Local` pins the file open and hashes it, one full pass before the first byte comes back. - -Multipart uploads left neither finalized nor aborted keep their parts, and S3 bills for them. `listUploads()` finds them, so a cleanup job can abort what a crashed process left behind. It is an `S3` method, forwarded by the `Telemetry` decorator; other devices have no multipart uploads and refuse the call. Amazon S3 takes any prefix; MinIO only honours a whole key. - -```php -$list = $device->listUploads('remote/directory'); -foreach ($list->uploads as $upload) { - $device->abort($upload->path, $upload->uploadId); -} -``` - -## Custom HTTP client - -The S3-family adapters send requests through any [PSR-18](https://www.php-fig.org/psr/psr-18/) client. By default they use [utopia-php/client](https://github.com/utopia-php/client) with the cURL adapter — no overall request timeout, a stall watchdog that aborts once no bytes move for 60 seconds, TCP keepalive — and the `Retry` decorator configured with `S3\RetryStrategy`. It retries transient S3 rate-limiting errors (`SlowDown`, `ServiceUnavailable`, `Throttling`, `RequestThrottled`, and plain 429/503 responses) three times with exponential backoff and full jitter from a 0.5 second base delay. - -Inject your own client to change the transport or the retry policy — for example the Swoole coroutine adapter with more aggressive retries: - -```php -use Utopia\Client\Client; -use Utopia\Client\Adapter\SwooleCoroutine\Client as SwooleAdapter; -use Utopia\Client\Decorator\Retry; -use Utopia\Storage\Device\S3; -use Utopia\Storage\Device\S3\RetryStrategy; - -$client = new Retry( - new Client(new SwooleAdapter())->withTimeout(60), - new RetryStrategy(retries: 5, delay: 1.0), -); - -$device = new S3('root', 'ACCESS_KEY', 'SECRET_KEY', 'HOST', 'us-east-1', client: $client); -``` - -Omit the `Retry` decorator to disable retries entirely, or pass any `Utopia\Client\Decorator\Retry\Strategy` of your own. - -## Error handling - -Every runtime failure throws a subclass of `Utopia\Storage\Exception\StorageException`, so one catch covers any storage problem. Match more precisely when you need to branch: - -```php -use Utopia\Storage\Exception\NotFoundException; -use Utopia\Storage\Exception\RemoteException; -use Utopia\Storage\Exception\StorageException; -use Utopia\Storage\Exception\TransportException; -use Utopia\Storage\Exception\UploadException; - -try { - $contents = $device->read('remote/path/file.jpg'); -} catch (NotFoundException) { - // The file does not exist -} catch (TransportException $e) { - // The request never reached the service; $e->getPrevious() is the PSR-18 exception -} catch (RemoteException $e) { - // The service answered with an error: $e->getCode() is the HTTP status, - // $e->errorCode the service's own error identifier (for example `SlowDown`) -} catch (UploadException) { - // A chunked upload is in an invalid state (missing chunk, never prepared) -} catch (StorageException $e) { - // Anything else, such as a local filesystem failure -} -``` - -Invalid arguments (a non-positive chunk size, a page size above the adapter limit) throw SPL `\InvalidArgumentException` — these are programmer errors, not storage failures. - -## Telemetry - -Wrap any device with the `Telemetry` decorator to record a `storage.operation` histogram for every call through a [utopia-php/telemetry](https://github.com/utopia-php/telemetry) adapter: - -```php -use Utopia\Storage\Device\Local; -use Utopia\Storage\Device\Telemetry; - -$device = new Telemetry($telemetryAdapter, new Local('/path/to/storage')); -``` - -## Upgrading from 4.1 - -- `write()` returns the ETag of the file written, a string, instead of `true`. A `false` never happened: every adapter threw instead. Callers testing the result for truth keep working; callers comparing it with `true` do not. -- `Device` has three new abstract methods, `getFileInfo()`, `create()` and `replace()`, and `read()` takes an optional ETag. Adapters outside this library must implement them. -- `finalize()` completes a multipart upload over an existing file instead of skipping it. Finalizing twice is still not an error, on either adapter and whatever the chunk count. A chunk that never arrived is reported, whatever file happens to sit at the path. - -## Upgrading from 3.x - -Version 4.0 makes streaming the only I/O path: file contents move as PSR-7 streams end to end, so memory stays bounded regardless of file size. - -- `read()` returns a `Psr\Http\Message\StreamInterface` instead of a string. Cast with `(string)` or call `getContents()` where you want the bytes in memory — the cost is visible at the call site. -- `write()` and the upload methods take a `StreamInterface` instead of a string. Wrap a string with `new Utopia\Psr7\Stream($data)`; wrap an open file handle with `Utopia\Psr7\Stream::fromResource($handle)`. S3 requires seekable streams: the payload is hashed for signing, rewound and sent — the same approach the AWS SDK takes. -- `uploadData()` and `uploadChunk()` merged into one `upload($data, $path, $contentType, $chunk, $chunks, $metadata)` — a whole file is the single-chunk default. `prepareUpload()`/`finalizeUpload()` are now `prepare()`/`finalize()`. -- `transfer()` is replaced by `copy($source, $target, $to, $chunkSize)` where `$to` defaults to the same device, and `move()` now works across every adapter as copy plus delete (`Local` still renames in place). The `TRANSFER_CHUNK_SIZE` constant is now `COPY_CHUNK_SIZE`. - -## Upgrading from 2.x - -Version 3.0 makes every device immutable and safe to share across coroutines, and removes all global state: - -- The `Storage` class is gone entirely: replace `Storage::setDevice('files', $device)` and `Storage::getDevice('files')` with your own wiring (a container, or passing the device instance directly), and inline `Storage::human()` if you used it. -- `setTelemetry()` is gone: wrap the device in the `Utopia\Storage\Device\Telemetry` decorator instead. `setHttpVersion()` is gone: transport options now belong to the injected PSR-18 client. The static `S3::setRetryAttempts()`/`S3::setRetryDelay()` moved into the `S3\RetryStrategy` used by the default client's `Retry` decorator — inject your own client to tune or disable retries. -- `setTransferChunkSize()`/`getTransferChunkSize()` became a per-call argument: `transfer($path, $destination, $device, $chunkSize)`. -- String constants became enums: the `Storage::DEVICE_*` constants are now the `Utopia\Storage\DeviceType` enum (`getType()` returns it), and the `S3::ACL_*` constants are now the `Utopia\Storage\Acl` enum. -- The S3 adapter no longer stores request headers on the instance, so one device can serve concurrent requests (for example Swoole coroutines) without data races. -- Requests go through a PSR-18 client instead of raw cURL calls. The default is [utopia-php/client](https://github.com/utopia-php/client) with the cURL adapter; pass the `client` constructor argument to swap the transport. -- Uploads are data-based: `upload($sourcePath, ...)` was removed — read the file yourself and call `uploadData($data, ...)` — and `uploadChunk()` now takes the chunk contents instead of a source file path. -- Filesystem-only methods (`createDirectory()`, `getDirectorySize()`, `getPartitionFreeSpace()`, `getPartitionTotalSpace()`) left the base `Device` contract and remain on `Local`; wrap devices in the `Telemetry` decorator and use its `getDevice()` accessor when you need them. `getFiles()` — which returned path strings on `Local` but a raw `ListObjectsV2` array on `S3` — is replaced by `listFiles(prefix, max, cursor)` returning typed `FileList`/`FileInfo` value objects consistently on every adapter. -- `getName()` and `getDescription()` were removed; use `getType()` to identify an adapter. -- Exceptions are typed: every runtime failure extends `Utopia\Storage\Exception\StorageException` (`NotFoundException`, `TransportException`, `RemoteException`, `UploadException`) instead of bare `\Exception`, and missing files throw `NotFoundException` consistently on every adapter and method — including S3 HEAD responses, which previously surfaced as a generic error with an empty message. Existing `catch (\Exception)` blocks keep working. - -## Adding new adapters - -For information on adding new storage adapters, see the [Adding New Storage Adapter](https://github.com/utopia-php/storage/blob/master/docs/adding-new-storage-adapter.md) guide. - -## System requirements - -Utopia Storage requires PHP 8.5 or later. We recommend using the latest PHP version whenever possible. - -## Contributing - -For security issues, please email [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue in GitHub. - -All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code. - -We welcome you to contribute to the Utopia Storage library. For details on how to do this, please refer to our [Contributing Guide](https://github.com/utopia-php/monorepo/blob/main/CONTRIBUTING.md). - -## License - -This library is available under the MIT License. - -## Copyright - -``` -Copyright (c) 2019-2025 Appwrite Team -``` diff --git a/packages/storage/composer.json b/packages/storage/composer.json deleted file mode 100644 index 1d595a665..000000000 --- a/packages/storage/composer.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "utopia-php/storage", - "description": "A simple Storage library to manage application storage", - "type": "library", - "keywords": [ - "php", - "framework", - "upf", - "utopia", - "storage" - ], - "license": "MIT", - "scripts": { - "test": "phpunit --testsuite unit", - "test:e2e": "phpunit --testsuite e2e" - }, - "authors": [], - "autoload": { - "psr-4": { - "Utopia\\Storage\\": "src/Storage" - } - }, - "autoload-dev": { - "psr-4": { - "Utopia\\Tests\\Storage\\": "tests/Storage", - "Utopia\\Tests\\Storage\\E2E\\": "tests/E2E" - } - }, - "require": { - "php": ">=8.5", - "ext-fileinfo": "*", - "ext-curl": "*", - "ext-simplexml": "*", - "utopia-php/telemetry": "^0.4.6", - "utopia-php/validators": "^1.0", - "psr/http-client": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "utopia-php/client": "^0.5", - "utopia-php/psr7": "0.2.*" - }, - "config": { - "allow-plugins": { - "php-http/discovery": false, - "tbachert/spi": false - } - } -} diff --git a/packages/storage/docker-compose.yml b/packages/storage/docker-compose.yml deleted file mode 100644 index 4b99e49e8..000000000 --- a/packages/storage/docker-compose.yml +++ /dev/null @@ -1,13 +0,0 @@ -services: - minio: - image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z - entrypoint: sh -c 'mkdir -p /data/utopia-storage-test && exec minio server /data' - environment: - MINIO_DOMAIN: localhost - ports: - - '9805:9000' - healthcheck: - test: ['CMD', 'mc', 'ready', 'local'] - interval: 2s - timeout: 5s - retries: 15 diff --git a/packages/storage/docs/adding-new-storage-adapter.md b/packages/storage/docs/adding-new-storage-adapter.md deleted file mode 100644 index 9b6d2935a..000000000 --- a/packages/storage/docs/adding-new-storage-adapter.md +++ /dev/null @@ -1,43 +0,0 @@ -# Adding New Storage Adapter - -This document is a part of Utopia PHP contributors' guide. Before you continue reading this document make sure you have read the [Code of Conduct](https://github.com/utopia-php/monorepo/blob/main/CODE_OF_CONDUCT.md) and the [Contributing Guide](https://github.com/utopia-php/monorepo/blob/main/CONTRIBUTING.md). - -## Getting started - -Storage adapters help us use various storage services to store our data. As of writing this guide, we already support Local storage, [AWS S3](https://aws.amazon.com/s3/) storage and [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/) storage. - -## 1. Prerequisites - -This library is developed in the [utopia-php monorepo](https://github.com/utopia-php/monorepo) — `utopia-php/storage` is a read-only mirror. Fork the monorepo, clone your fork, and create a `feat-XXX-YYY-storage-adapter` branch from `main`, where `XXX` is the issue ID and `YYY` the storage adapter name. The library lives in `packages/storage`. - -## 2. Implement new storage adapter - -### 2.1 Add new adapter and implement it - -In order to start implementing new storage adapter, add new file inside `packages/storage/src/Storage/Device/YYY.php` where `YYY` is the name of the storage provider in `PascalCase`. Inside the file you should create a class that extends the basic `Device` abstract class. Note that the class name should start with a capital letter, as PHP FIG standards suggest. - -Always use properly named environment variables if any credentials are required. - -### 2.2. Introduce new device type -Add a case for the new device to the `DeviceType` enum in `src/Storage/DeviceType.php` alongside the existing cases, and return it from your adapter's `getType()` method. - -## 3. Test your adapter - -After you finish adding your new adapter, you need to ensure that it is usable. Use your newly created adapter to make some sample requests to your storage service. - -Great! You're almost there. You can now move onto writing some tests for your Adapter! - -### 3.1. Introduce new device tests -Add tests for the newly added device adapter inside `tests/Storage/Device`. Use the existing adapter tests as a reference. The test file and class should be properly named `Test.php` and class should be `Test` - -### 3.2. Run and verify tests -Run tests using `bin/monorepo test storage` from the monorepo root and verify that everything is working correctly. - -If everything goes well, raise a pull request and be ready to respond to any feedback which can arise during our code review. - -## 4. Raise a pull request - -First of all, commit the changes with the message `Added YYY Storage adapter` and push the branch to your fork of the monorepo. If you visit your fork on GitHub, you will see a new alert saying you are ready to submit a pull request against `utopia-php/monorepo`. Follow the steps GitHub provides, and at the end, you will have your pull request submitted. - -## 🤕 Stuck ? -If you need any help with the contribution, feel free to head over to [our discord channel](https://appwrite.io/discord) and we'll be happy to help you out. diff --git a/packages/storage/phpstan.neon b/packages/storage/phpstan.neon deleted file mode 100644 index 5d9dff0bd..000000000 --- a/packages/storage/phpstan.neon +++ /dev/null @@ -1,5 +0,0 @@ -includes: - - ../../phpstan.neon - -parameters: - level: max diff --git a/packages/storage/phpunit.xml b/packages/storage/phpunit.xml deleted file mode 100644 index 48e0eb4d9..000000000 --- a/packages/storage/phpunit.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - tests/Storage - - - tests/E2E - - - - - src - - - diff --git a/packages/storage/rector.php b/packages/storage/rector.php deleted file mode 100644 index 35a483abe..000000000 --- a/packages/storage/rector.php +++ /dev/null @@ -1,11 +0,0 @@ -withPreparedSets( - typeDeclarationDocblocks: true, - privatization: true, - instanceOf: true, - rectorPreset: true, -); diff --git a/packages/storage/src/Storage/Acl.php b/packages/storage/src/Storage/Acl.php deleted file mode 100644 index 3c866b046..000000000 --- a/packages/storage/src/Storage/Acl.php +++ /dev/null @@ -1,19 +0,0 @@ -, chunks?: int, content_type?: string, uploadId?: string, whole?: bool} - */ -abstract class Device -{ - /** - * Default max chunk size while copying a file from one device to another - */ - public const COPY_CHUNK_SIZE = 20000000; // 20 MB - - /** - * Get Type. - * - * Get storage device type - */ - abstract public function getType(): DeviceType; - - /** - * Get Root. - * - * Get storage device root path - */ - abstract public function getRoot(): string; - - /** - * Get Path. - * - * Each device hold a complex directory structure that is being build in this method. - */ - abstract public function getPath(string $filename): string; - - /** - * Prepare. - * - * Initialize adapter-specific upload state without transferring a chunk body. - * Pass 0 chunks when their number is not known yet; `finalize()` then takes - * the final count. - * - * @param UploadMetadata $metadata - * - * @throws StorageException - */ - abstract public function prepare(string $path, string $contentType, int $chunks = 1, array &$metadata = []): void; - - /** - * Upload Chunk. - * - * Store exactly one chunk of file contents without finalizing the full upload. - * Returns the number of chunks received so far. - * - * @param UploadMetadata $metadata - * - * @throws StorageException - */ - abstract protected function uploadChunk(StreamInterface $data, string $path, int $chunk, int $chunks, array &$metadata): int; - - /** - * Finalize. - * - * Complete a prepared upload once all chunks are known to be present. The - * assembled file replaces whatever was at the path before. Finalizing an - * upload that was completed already is not an error. - * - * @param UploadMetadata $metadata - * - * @throws StorageException - */ - abstract public function finalize(string $path, int $chunks = 1, array &$metadata = []): bool; - - /** - * Upload. - * - * Upload one chunk of file contents to the desired destination, preparing the - * upload on first contact and finalizing it once every chunk has arrived. - * A whole file is the default single-chunk case. Pass 0 chunks when their - * number is not known yet: nothing is finalized until `finalize()` is called - * with the final count. - * Returns the number of chunks received so far. - * - * @param UploadMetadata $metadata - * - * @throws StorageException - */ - public function upload(StreamInterface $data, string $path, string $contentType, int $chunk = 1, int $chunks = 1, array &$metadata = []): int - { - $this->prepare($path, $contentType, $chunks, $metadata); - $chunksReceived = $this->uploadChunk($data, $path, $chunk, $chunks, $metadata); - - if ($chunks > 1 && $chunks === $chunksReceived && ! $this->finalize($path, $chunks, $metadata)) { - throw new UploadException('Failed to finalize upload ' . $path); - } - - return $chunksReceived; - } - - /** - * Abort Chunked Upload - */ - abstract public function abort(string $path, string $uploadId = ''): bool; - - /** - * Read file or part of file by given path, offset and length. - * - * The returned stream is positioned at the start of the requested window. - * A window that runs past the end of the file is cut short. With an ETag, - * the read only happens while the file still carries it, so bytes from a - * file replaced meanwhile are never mistaken for the one the caller knows. - * S3 checks the ETag as part of the read; `Local` pins the file open and - * hashes it, which costs a full pass over it before any byte is returned. - * - * @param int<0, max> $offset - * @param int<0, max>|null $length - * @param string|null $etag Only read while the file has this ETag, as reported by `getFileInfo()` - * - * @throws NotFoundException When there is no file at the path - * @throws PreconditionFailedException When the file's ETag is not the given one - */ - abstract public function read(string $path, int $offset = 0, ?int $length = null, ?string $etag = null): StreamInterface; - - /** - * Write file by given path, replacing whatever was there. - * - * The stream is consumed in full: seekable streams are rewound and sent - * from the beginning on every adapter. Returns the ETag of the file - * written, as `getFileInfo()` will report it. - * - * @throws StorageException - */ - abstract public function write(string $path, StreamInterface $data, string $contentType): string; - - /** - * Write a file where there is none yet. - * - * Exactly one of several callers racing to create the same path succeeds; - * the others get a PreconditionFailedException. Returns the ETag of the - * file written. - * - * @throws PreconditionFailedException When a file is already there - */ - abstract public function create(string $path, StreamInterface $data, string $contentType = ''): string; - - /** - * Write over the file that carries the given ETag, and no other. - * - * Exactly one of several callers racing to replace the same version - * succeeds; the others get a PreconditionFailedException. Returns the ETag - * of the file written. - * - * @param string $etag The ETag the file must have, as reported by `getFileInfo()` or a previous write - * - * @throws PreconditionFailedException When the file is gone or has another ETag - */ - abstract public function replace(string $path, StreamInterface $data, string $etag, string $contentType = ''): string; - - /** - * Copy a file to another path, on this device or onto another one. - * - * Large files are piped chunk by chunk, so memory stays bounded regardless - * of file size. A started multipart upload is aborted on failure. - * - * @throws StorageException - */ - public function copy(string $source, string $target, ?Device $to = null, int $chunkSize = self::COPY_CHUNK_SIZE): bool - { - if ($chunkSize <= 0) { - throw new \InvalidArgumentException('Chunk size must be greater than zero'); - } - - $to ??= $this; - $size = $this->getFileSize($source); - $contentType = $this->getFileMimeType($source); - - if ($size <= $chunkSize) { - $to->write($target, $this->read($source), $contentType); - - return true; - } - - $totalChunks = (int) ceil($size / $chunkSize); - $metadata = ['content_type' => $contentType]; - try { - for ($counter = 0; $counter < $totalChunks; ++$counter) { - $data = $this->read($source, $counter * $chunkSize, $chunkSize); - $to->upload($data, $target, $contentType, $counter + 1, $totalChunks, $metadata); - } - } catch (\Throwable $e) { - // Best effort, and only once a multipart upload was actually started — - // its unclaimed parts are billed until aborted. Aborting without one - // could delete a pre-existing destination the copy never touched. - $uploadId = $metadata['uploadId'] ?? null; - if (\is_string($uploadId) && $uploadId !== '') { - try { - $to->abort($target, $uploadId); - } catch (\Throwable) { - } - } - throw $e; - } - - return true; - } - - /** - * Move file from given source to given path, return true on success and false on failure. - */ - public function move(string $source, string $target): bool - { - if ($source === $target) { - return false; - } - - if ($this->copy($source, $target)) { - return $this->delete($source); - } - - return false; - } - - /** - * Delete file in given path return true on success and false on failure. - */ - abstract public function delete(string $path, bool $recursive = false): bool; - - /** - * Delete files in given path, path must be a directory. return true on success and false on failure. - */ - abstract public function deletePath(string $path): bool; - - /** - * Check if file exists - */ - abstract public function exists(string $path): bool; - - /** - * List files under the given prefix, one page at a time. - * - * @param int<1, max> $max - */ - abstract public function listFiles(string $prefix = '', int $max = 1000, ?string $cursor = null): FileList; - - /** - * Size, last modification and ETag of a file, in one request. - * - * @throws NotFoundException When there is no file at the path - * @throws StorageException When the file cannot be looked at - */ - abstract public function getFileInfo(string $path): FileInfo; - - /** - * Returns given file path its size. - */ - abstract public function getFileSize(string $path): int; - - /** - * Returns given file path its mime type. - */ - abstract public function getFileMimeType(string $path): string; - - /** - * Returns given file path its MD5 hash value. - */ - abstract public function getFileHash(string $path): string; - - /** - * Get the absolute path by resolving strings like ../, .., //, /\ and so on. - * - * Works like the realpath function but works on files that does not exist - * - * Reference https://www.php.net/manual/en/function.realpath.php#84012 - */ - public function getAbsolutePath(string $path): string - { - $path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path); - $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), fn(string $part): bool => $part !== ''); - - $absolutes = []; - foreach ($parts as $part) { - if ($part == '.') { - continue; - } - if ($part == '..') { - array_pop($absolutes); - } else { - $absolutes[] = $part; - } - } - - return DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $absolutes); - } -} diff --git a/packages/storage/src/Storage/Device/AWS.php b/packages/storage/src/Storage/Device/AWS.php deleted file mode 100644 index 80ac701d7..000000000 --- a/packages/storage/src/Storage/Device/AWS.php +++ /dev/null @@ -1,94 +0,0 @@ - $bucket . '.s3.' . $region . '.amazonaws.cn', - default => $bucket . '.s3.' . $region . '.amazonaws.com' - }; - parent::__construct($root, $accessKey, $secretKey, $host, $region, $acl, $client, $bucket); - } - - #[\Override] - public function getType(): DeviceType - { - return DeviceType::AwsS3; - } -} diff --git a/packages/storage/src/Storage/Device/Backblaze.php b/packages/storage/src/Storage/Device/Backblaze.php deleted file mode 100644 index 2dfc3df91..000000000 --- a/packages/storage/src/Storage/Device/Backblaze.php +++ /dev/null @@ -1,52 +0,0 @@ -root; - } - - public function getPath(string $filename): string - { - return $this->getAbsolutePath($this->getRoot() . DIRECTORY_SEPARATOR . $filename); - } - - /** - * @param UploadMetadata $metadata - */ - public function prepare(string $path, string $contentType, int $chunks = 1, array &$metadata = []): void - { - $this->createDirectory(\dirname($path)); - $metadata['parts'] ??= []; - $metadata['chunks'] ??= 0; - } - - /** - * @param UploadMetadata $metadata - */ - protected function uploadChunk(StreamInterface $data, string $path, int $chunk, int $chunks, array &$metadata): int - { - $this->createDirectory(\dirname($path)); - $metadata['parts'] ??= []; - $metadata['chunks'] ??= 0; - - if ($chunks === 1) { - $this->writeAtomic($path, $data); - - $metadata['parts'][$chunk] = true; - $metadata['chunks'] = 1; - $metadata['whole'] = true; - - return 1; - } - - $tmp = \dirname($path) . DIRECTORY_SEPARATOR . 'tmp_' . basename($path); - $this->createDirectory($tmp); - - $chunkFilePath = $tmp . DIRECTORY_SEPARATOR . pathinfo($path, PATHINFO_FILENAME) . '.part.' . $chunk; - - // skip writing chunk if the chunk was re-uploaded - if (! file_exists($chunkFilePath)) { - $this->writeFile($chunkFilePath, $data); - } - - $chunksReceived = $this->countChunks($tmp, $path); - $metadata['parts'][$chunk] = true; - $metadata['chunks'] = $chunksReceived; - $metadata['whole'] = false; - - return $chunksReceived; - } - - public function finalize(string $path, int $chunks = 1, array &$metadata = []): bool - { - $tmp = \dirname($path) . DIRECTORY_SEPARATOR . 'tmp_' . basename($path); - - // A single chunk was written as the whole file, unless the upload was - // prepared without knowing the count: then it is one part to join. The - // upload itself says which it was; without its metadata, a part left - // behind by an abandoned upload is indistinguishable from this one's. - $whole = $metadata['whole'] ?? ! file_exists($tmp . DIRECTORY_SEPARATOR . pathinfo($path, PATHINFO_FILENAME) . '.part.1'); - - if ($chunks === 1 && $whole) { - return file_exists($path); - } - - for ($i = 1; $i <= $chunks; ++$i) { - $part = $tmp . DIRECTORY_SEPARATOR . pathinfo($path, PATHINFO_FILENAME) . '.part.' . $i; - if (file_exists($part)) { - continue; - } - - // The chunk directory goes once the parts are joined, so its absence - // next to a file in place is a finalized upload. While it is still - // there, the chunk is missing, whatever sits at the path. - if (! is_dir($tmp) && file_exists($path)) { - return true; - } - - throw new UploadException('Missing chunk ' . $i); - } - - $this->joinChunks($path, $chunks); - - return true; - } - - private function countChunks(string $tmp, string $path): int - { - $escaped = (fn(string $literal): string => str_replace(['\\', '*', '?', '[', ']', '{', '}'], ['\\\\', '\\*', '\\?', '\\[', '\\]', '\\{', '\\}'], $literal)); - $pattern = $escaped($tmp) . DIRECTORY_SEPARATOR . $escaped(pathinfo($path, PATHINFO_FILENAME)) . '.part.*'; - $files = glob($pattern); - if ($files === false) { - return 0; - } - - $count = 0; - foreach ($files as $file) { - if (preg_match('/\.part\.\d+$/', $file)) { - ++$count; - } - } - - return $count; - } - - private function joinChunks(string $path, int $chunks): void - { - $tmp = \dirname($path) . DIRECTORY_SEPARATOR . 'tmp_' . basename($path); - $tmpAssemble = tempnam(\dirname($path), 'tmp_assemble_' . basename($path) . '_'); - - $dest = fopen($tmpAssemble, 'wb'); - if ($dest === false) { - throw new StorageException('Failed to open temporary assembly file ' . $tmpAssemble); - } - - $partsToUnlink = []; - for ($i = 1; $i <= $chunks; ++$i) { - $part = $tmp . DIRECTORY_SEPARATOR . pathinfo($path, PATHINFO_FILENAME) . '.part.' . $i; - $src = @fopen($part, 'rb'); - if ($src === false) { - fclose($dest); - unlink($tmpAssemble); - - // The chunks go once joined: a file in place means another - // request assembled it meanwhile, and there is nothing left to do. - if (file_exists($path)) { - return; - } - - throw new StorageException('Failed to open chunk ' . $part); - } - - if (stream_copy_to_stream($src, $dest) === false) { - fclose($src); - fclose($dest); - unlink($tmpAssemble); - throw new StorageException('Failed to copy chunk ' . $part); - } - fclose($src); - $partsToUnlink[] = $part; - } - - fclose($dest); - - // tempnam() creates the file private to its owner; the assembled file - // takes the permissions a plain write would have given it. - @chmod($tmpAssemble, 0644 & ~umask()); - - // rename() replaces a file in place, so the assembled file takes over from whatever was there. - if (! rename($tmpAssemble, $path)) { - unlink($tmpAssemble); - throw new StorageException('Failed to finalize assembled file ' . $path); - } - - foreach ($partsToUnlink as $part) { - if (! unlink($part)) { - trigger_error('Failed to remove chunk part ' . $part, E_USER_WARNING); - } - } - - if (! rmdir($tmp)) { - trigger_error('Failed to remove temporary chunk directory ' . $tmp, E_USER_WARNING); - } - } - - /** - * Abort Chunked Upload - */ - public function abort(string $path, string $uploadId = ''): bool - { - if (file_exists($path)) { - unlink($path); - } - - $tmp = \dirname($path) . DIRECTORY_SEPARATOR . 'tmp_' . basename($path) . DIRECTORY_SEPARATOR; - - if (! file_exists(\dirname($tmp))) { // Checks if directory path to file exists - throw new NotFoundException('File doesn\'t exist: ' . \dirname($path)); - } - $files = $this->scanDirectory($tmp); - - foreach ($files as $file) { - $this->delete($file, true); - } - - return rmdir($tmp); - } - - /** - * Read file or part of file by given path, offset and length. - * - * A full read returns a stream over the file itself; a bounded window is - * copied into a temporary stream so consumers can read to its end. The - * ETag of a local file is its MD5 hash, so a conditional read hashes the - * whole file first. - * - * @throws StorageException - */ - public function read(string $path, int $offset = 0, ?int $length = null, ?string $etag = null): StreamInterface - { - if (! $this->exists($path)) { - throw new NotFoundException('File not found'); - } - - $handle = fopen($path, 'rb'); - if ($handle === false) { - throw new StorageException('Failed to read file ' . $path); - } - - if ($etag !== null && $this->hashHandle($handle, $path) !== $etag) { - fclose($handle); - throw new PreconditionFailedException('File ' . $path . ' no longer has ETag ' . $etag); - } - - if ($offset > 0 && fseek($handle, $offset) !== 0) { - fclose($handle); - throw new StorageException('Failed to seek file ' . $path); - } - - if ($length === null) { - return Stream::fromResource($handle); - } - - $window = fopen('php://temp', 'r+b'); - if ($window === false || stream_copy_to_stream($handle, $window, $length) === false) { - fclose($handle); - throw new StorageException('Failed to read file ' . $path); - } - fclose($handle); - rewind($window); - - return Stream::fromResource($window); - } - - /** - * Write file by given path. The ETag of a local file is its MD5 hash, - * taken from the bytes as they are written. - */ - public function write(string $path, StreamInterface $data, string $contentType = ''): string - { - // Checks if directory path to file exists - if (! file_exists(\dirname($path)) && ! @mkdir(\dirname($path), 0755, true)) { - throw new StorageException('Can\'t create directory ' . \dirname($path)); - } - - return $this->writeAtomic($path, $data); - } - - /** - * Write a file where there is none yet. Opening the file exclusively makes - * the check and the creation one step. - */ - public function create(string $path, StreamInterface $data, string $contentType = ''): string - { - if (! file_exists(\dirname($path)) && ! @mkdir(\dirname($path), 0755, true)) { - throw new StorageException('Can\'t create directory ' . \dirname($path)); - } - - $handle = @fopen($path, 'xb'); - if ($handle === false) { - if (file_exists($path)) { - throw new PreconditionFailedException('File ' . $path . ' already exists'); - } - - throw new StorageException('Can\'t write file ' . $path); - } - - // The path is claimed the moment the handle opens: a body that fails - // must give it back, or the path can never be created again. - try { - return $this->pipe($handle, $path, $data); - } catch (\Throwable $e) { - @unlink($path); - - throw $e; - } - } - - /** - * Write over the file with the given ETag. The check and the write are two - * steps, so a replacement landing between them goes unnoticed and the last - * writer wins; a local disk offers nothing better without a lock file. The - * write itself is atomic, so no reader ever sees the two mixed. - */ - public function replace(string $path, StreamInterface $data, string $etag, string $contentType = ''): string - { - if (! $this->exists($path)) { - throw new PreconditionFailedException('File ' . $path . ' is gone'); - } - - if ($this->getFileHash($path) !== $etag) { - throw new PreconditionFailedException('File ' . $path . ' no longer has ETag ' . $etag); - } - - return $this->writeAtomic($path, $data); - } - - /** - * Pipe a stream into a sibling temporary file and rename it over the path. - * - * rename() is atomic, so a reader sees either the whole old file or the - * whole new one, and a write that fails part way leaves the old one alone. - * - * @return string MD5 hash of the bytes written - * - * @throws StorageException - */ - private function writeAtomic(string $path, StreamInterface $data): string - { - $tmp = tempnam(\dirname($path), 'tmp_write_' . basename($path) . '_'); - if ($tmp === false) { - throw new StorageException('Can\'t write file ' . $path); - } - - try { - $hash = $this->writeFile($tmp, $data); - @chmod($tmp, 0644 & ~umask()); - - if (! rename($tmp, $path)) { - throw new StorageException('Can\'t write file ' . $path); - } - } catch (\Throwable $e) { - @unlink($tmp); - - throw $e; - } - - return $hash; - } - - /** - * MD5 the open file and leave it positioned at the start again. - * - * @param resource $handle - * - * @throws StorageException - */ - private function hashHandle($handle, string $path): string - { - $context = hash_init('md5'); - hash_update_stream($context, $handle); - - if (! rewind($handle)) { - throw new StorageException('Failed to read file ' . $path); - } - - return hash_final($context); - } - - /** - * Pipe a stream into a file, chunk by chunk. - * - * @return string MD5 hash of the bytes written - * - * @throws StorageException - */ - private function writeFile(string $path, StreamInterface $data): string - { - $handle = fopen($path, 'wb'); - if ($handle === false) { - throw new StorageException('Can\'t write file ' . $path); - } - - return $this->pipe($handle, $path, $data); - } - - /** - * Pipe a stream into an open file, chunk by chunk, and close it. - * - * @param resource $handle - * @return string MD5 hash of the bytes written, the file's ETag - * - * @throws StorageException - */ - private function pipe($handle, string $path, StreamInterface $data): string - { - if ($data->isSeekable()) { - $data->rewind(); - } - - $hash = hash_init('md5'); - - try { - while (! $data->eof()) { - $chunk = $data->read(self::PIPE_CHUNK_SIZE); - $written = 0; - $length = \strlen($chunk); - if ($length === 0) { - break; - } - hash_update($hash, $chunk); - while ($written < $length) { - $bytes = fwrite($handle, substr($chunk, $written)); - if ($bytes === false || $bytes === 0) { - throw new StorageException('Can\'t write file ' . $path); - } - $written += $bytes; - } - } - } finally { - fclose($handle); - } - - return hash_final($hash); - } - - /** - * Move file from given source to given path, Return true on success and false on failure. - * - * @throws StorageException - */ - #[\Override] - public function move(string $source, string $target): bool - { - if ($source === $target) { - return false; - } - - // Checks if directory path to file exists - if (! file_exists(\dirname($target)) && ! @mkdir(\dirname($target), 0755, true)) { - throw new StorageException('Can\'t create directory ' . \dirname($target)); - } - - return rename($source, $target); - } - - /** - * Delete file in given path, Return true on success and false on failure. - */ - public function delete(string $path, bool $recursive = false): bool - { - if (is_dir($path) && $recursive) { - $entries = scandir($path); - - if ($entries === false) { - return false; - } - - foreach ($entries as $entry) { - if ($entry === '.') { - continue; - } - if ($entry === '..') { - continue; - } - if (! $this->delete($path . DIRECTORY_SEPARATOR . $entry, true)) { - return false; - } - } - - return rmdir($path); - } - - if (is_file($path) || is_link($path)) { - return unlink($path); - } - - return false; - } - - /** - * Delete files in given path, path must be a directory. Return true on success and false on failure. - */ - public function deletePath(string $path): bool - { - $path = realpath($this->getRoot() . DIRECTORY_SEPARATOR . $path); - - if ($path === false || ! is_dir($path)) { - return false; - } - - $files = $this->scanDirectory($path); - - foreach ($files as $file) { - if (is_dir($file)) { - $this->deletePath(substr_replace($file, '', 0, \strlen($this->getRoot() . DIRECTORY_SEPARATOR))); - } else { - $this->delete($file, true); - } - } - - return rmdir($path); - } - - /** - * Check if file exists - */ - public function exists(string $path): bool - { - return file_exists($path); - } - - /** - * Size, last modification and MD5 hash of a file. The hash reads the whole file. - */ - public function getFileInfo(string $path): FileInfo - { - if (! $this->exists($path)) { - throw new NotFoundException('File not found: ' . $path); - } - - $modified = filemtime($path); - - return new FileInfo( - path: $path, - size: $this->getFileSize($path), - modifiedAt: $modified === false ? null : new \DateTimeImmutable('@' . $modified), - etag: $this->getFileHash($path), - ); - } - - /** - * Returns given file path its size. - * - * @see http://php.net/manual/en/function.filesize.php - */ - public function getFileSize(string $path): int - { - $size = $this->exists($path) ? filesize($path) : false; - if ($size === false) { - throw $this->exists($path) ? new StorageException('Failed to get size of file ' . $path) : new NotFoundException('File not found: ' . $path); - } - - return $size; - } - - /** - * Returns given file path its mime type. - * - * @see http://php.net/manual/en/function.mime-content-type.php - */ - public function getFileMimeType(string $path): string - { - $mimeType = $this->exists($path) ? mime_content_type($path) : false; - if ($mimeType === false) { - throw $this->exists($path) ? new StorageException('Failed to get mime type of file ' . $path) : new NotFoundException('File not found: ' . $path); - } - - return $mimeType; - } - - /** - * Returns given file path its MD5 hash value. - * - * @see http://php.net/manual/en/function.md5-file.php - */ - public function getFileHash(string $path): string - { - $hash = $this->exists($path) ? md5_file($path) : false; - if ($hash === false) { - throw $this->exists($path) ? new StorageException('Failed to hash file ' . $path) : new NotFoundException('File not found: ' . $path); - } - - return $hash; - } - - /** - * Create a directory at the specified path. - * - * Returns true on success or if the directory already exists and false on error - */ - public function createDirectory(string $path): bool - { - if (file_exists($path)) { - return true; - } - - return @mkdir($path, 0755, true); - } - - /** - * Get directory size in bytes. - * - * Return -1 on error - * - * Based on http://www.jonasjohn.de/snippets/php/dir-size.htm - */ - public function getDirectorySize(string $path): int - { - if ($path === '') { - return -1; - } - - $size = 0; - $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; - - $directory = opendir($path); - - if (! $directory) { - return -1; - } - - while (($file = readdir($directory)) !== false) { - // Skip file pointers - if ($file[0] === '.') { - continue; - } - - // Go recursive down, or add the file size - if (is_dir($path . $file)) { - $size += $this->getDirectorySize($path . $file . DIRECTORY_SEPARATOR); - } else { - $size += filesize($path . $file); - } - } - - closedir($directory); - - return $size; - } - - /** - * Get Partition Free Space. - * - * disk_free_space — Returns available space on filesystem or disk partition - */ - public function getPartitionFreeSpace(): float - { - return disk_free_space($this->getRoot()) ?: 0.0; - } - - /** - * Get Partition Total Space. - * - * disk_total_space — Returns the total size of a filesystem or disk partition - */ - public function getPartitionTotalSpace(): float - { - return disk_total_space($this->getRoot()) ?: 0.0; - } - - /** - * List all files under the given directory, recursively, sorted by path. - * - * The cursor is a numeric offset into the sorted listing. - */ - public function listFiles(string $prefix = '', int $max = 1000, ?string $cursor = null): FileList - { - $paths = []; - $pending = [rtrim($prefix, DIRECTORY_SEPARATOR)]; - while ($pending !== []) { - $directory = array_pop($pending); - foreach ($this->scanDirectory($directory) as $entry) { - if (is_dir($entry)) { - $pending[] = $entry; - } else { - $paths[] = $entry; - } - } - } - sort($paths); - - $offset = is_numeric($cursor) ? (int) $cursor : 0; - $page = \array_slice($paths, $offset, $max); - - $files = []; - foreach ($page as $path) { - $modified = filemtime($path); - $files[] = new FileInfo( - path: $path, - size: filesize($path) ?: 0, - modifiedAt: $modified === false ? null : new \DateTimeImmutable('@' . $modified), - ); - } - - return new FileList( - files: $files, - cursor: $offset + \count($page) < \count($paths) ? (string) ($offset + \count($page)) : null, - ); - } - - /** - * Get all files and directories directly inside a directory, hidden entries included. - * - * @return string[] - */ - private function scanDirectory(string $dir): array - { - $dir = rtrim($dir, DIRECTORY_SEPARATOR); - $files = glob($dir . DIRECTORY_SEPARATOR . '*') ?: []; - - /** - * Hidden files - */ - foreach (glob($dir . DIRECTORY_SEPARATOR . '.[!.]*') ?: [] as $file) { - $files[] = $file; - } - - return $files; - } -} diff --git a/packages/storage/src/Storage/Device/S3.php b/packages/storage/src/Storage/Device/S3.php deleted file mode 100644 index 643bff0a2..000000000 --- a/packages/storage/src/Storage/Device/S3.php +++ /dev/null @@ -1,1121 +0,0 @@ -getHost(); - $port = $endpoint->getPort(); - if ($port !== null) { - $authority .= ':' . $port; - } - $this->fqdn = $endpoint->getScheme() . '://' . $authority; - $this->host = $authority; - $this->path = rtrim($endpoint->getPath(), '/'); - - $this->client = $client ?? new Retry( - new HttpClient(new CurlAdapter(options: [ - \CURLOPT_TIMEOUT_MS => 0, - \CURLOPT_LOW_SPEED_LIMIT => 1, - \CURLOPT_LOW_SPEED_TIME => 60, - \CURLOPT_TCP_KEEPALIVE => 1, - ])), - new S3\RetryStrategy(), - ); - } - - public function getType(): DeviceType - { - return DeviceType::S3; - } - - public function getRoot(): string - { - return $this->root; - } - - public function getPath(string $filename): string - { - return $this->getRoot() . DIRECTORY_SEPARATOR . $filename; - } - - /** - * @param UploadMetadata $metadata - */ - public function prepare(string $path, string $contentType, int $chunks = 1, array &$metadata = []): void - { - $metadata['parts'] ??= []; - $metadata['chunks'] ??= 0; - $metadata['content_type'] ??= $contentType; - - if ($chunks === 1 || isset($metadata['uploadId']) && ! \in_array($metadata['uploadId'], ['', '0', [], 0], true)) { - return; - } - - $metadata['uploadId'] = $this->createMultipartUpload($path, $contentType); - } - - public function finalize(string $path, int $chunks = 1, array &$metadata = []): bool - { - // No multipart upload to complete: either a single chunk went up as a - // whole object, or an earlier call completed the upload and the ID is - // gone with it. The object in place is the answer to both; without one - // there was never an upload here, and the caller is told so. - if (empty($metadata['uploadId'])) { - return $this->exists($path); - } - - $metadata['parts'] ??= []; - for ($i = 1; $i <= $chunks; ++$i) { - if (! \array_key_exists($i, $metadata['parts'])) { - throw new UploadException('Missing chunk ' . $i); - } - } - - try { - $this->completeMultipartUpload($path, $metadata['uploadId'], $metadata['parts']); - } catch (NotFoundException $e) { - // The upload is gone: completed by an earlier call, in which case - // the object is there, or aborted, in which case it is not. - if ($this->exists($path)) { - return true; - } - - throw $e; - } - - return true; - } - - /** - * @param UploadMetadata $metadata - */ - protected function uploadChunk(StreamInterface $data, string $path, int $chunk, int $chunks, array &$metadata): int - { - $contentType = $metadata['content_type'] ?? ''; - - if ($chunk === 1 && $chunks === 1) { - $this->write($path, $data, $contentType); - $metadata['parts'][$chunk] = true; - $metadata['chunks'] = 1; - - return 1; - } - - if (empty($metadata['uploadId'])) { - throw new UploadException('Missing multipart upload ID'); - } - - $metadata['parts'] ??= []; - $metadata['chunks'] ??= 0; - - $etag = $this->uploadPart($data, $path, $contentType, $chunk, $metadata['uploadId']); - // skip incrementing if the chunk was re-uploaded - if (! \array_key_exists($chunk, $metadata['parts'])) { - ++$metadata['chunks']; - } - $metadata['parts'][$chunk] = $etag; - - return $metadata['chunks']; - } - - /** - * Start Multipart Upload - * - * Initiate a multipart upload and return an upload ID. - * - * - * @throws StorageException - */ - protected function createMultipartUpload(string $path, string $contentType): string - { - $uri = $path !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($path)) : '/'; - - $response = $this->call( - Method::POST, - $uri, - '', - ['uploads' => ''], - headers: ['content-type' => $contentType], - amzHeaders: $this->aclHeaders(), - ); - - $uploadId = \is_array($response->body) ? ($response->body['UploadId'] ?? null) : null; - if (! \is_string($uploadId)) { - throw new RemoteException('Missing upload ID in S3 response'); - } - - return $uploadId; - } - - /** - * Upload Part - * - * - * @throws StorageException - */ - protected function uploadPart(StreamInterface $data, string $path, string $contentType, int $chunk, string $uploadId): string - { - $uri = $path !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($path)) : '/'; - - // ACL header is not allowed in parts, only createMultipartUpload accepts this header. - $response = $this->call( - Method::PUT, - $uri, - $data, - [ - 'partNumber' => $chunk, - 'uploadId' => $uploadId, - ], - headers: ['content-type' => $contentType], - ); - - return $response->headers['etag'] ?? throw new RemoteException('Missing ETag in S3 response'); - } - - /** - * Complete Multipart Upload - * - * @param array $parts - * - * @throws StorageException - */ - protected function completeMultipartUpload(string $path, string $uploadId, array $parts): bool - { - $uri = $path !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($path)) : '/'; - - ksort($parts, SORT_NUMERIC); - - $body = ''; - foreach ($parts as $key => $etag) { - if (! \is_string($etag)) { - throw new UploadException('Missing ETag for part ' . $key); - } - $body .= "{$etag}{$key}"; - } - $body .= ''; - - $this->call( - Method::POST, - $uri, - $body, - ['uploadId' => $uploadId], - headers: ['content-type' => 'application/xml'], - ); - - return true; - } - - /** - * Abort Chunked Upload - * - * - * @throws StorageException - */ - public function abort(string $path, string $uploadId = ''): bool - { - $uri = $path !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($path)) : '/'; - $this->call(Method::DELETE, $uri, '', ['uploadId' => $uploadId]); - - return true; - } - - /** - * Read file or part of file by given path, offset and length. - * - * The body streams into a temporary stream as it arrives, so memory stays - * bounded regardless of object size. With an ETag the request carries - * `If-Match`, which S3 checks against the object it serves in the same - * step, so a read can never mix the caller's idea of the object with the - * bytes of a replacement. - * - * @throws StorageException - */ - public function read(string $path, int $offset = 0, ?int $length = null, ?string $etag = null): StreamInterface - { - $uri = ($path !== '') ? '/' . str_replace('%2F', '/', rawurlencode($path)) : '/'; - - if ($length === 0) { - return new Stream(''); - } - - $headers = []; - if ($length !== null) { - $end = $offset + $length - 1; - $headers['range'] = "bytes=$offset-$end"; - } elseif ($offset > 0) { - $headers['range'] = "bytes=$offset-"; - } - - if ($etag !== null) { - $headers['if-match'] = $this->quote($etag); - } - - $handle = fopen('php://temp', 'r+b'); - if ($handle === false) { - throw new StorageException('Failed to allocate read buffer'); - } - - $this->call(Method::GET, $uri, headers: $headers, decode: false, sink: static function (string $chunk) use ($handle): void { - $written = 0; - $total = \strlen($chunk); - while ($written < $total) { - $bytes = fwrite($handle, substr($chunk, $written)); - if ($bytes === false || $bytes === 0) { - throw new StorageException('Failed to buffer S3 read response'); - } - $written += $bytes; - } - }); - rewind($handle); - - return Stream::fromResource($handle); - } - - /** - * Write file by given path. - * - * - * @throws StorageException - */ - public function write(string $path, StreamInterface $data, string $contentType = ''): string - { - return $this->put($path, $data, $contentType); - } - - /** - * Write an object where there is none yet, with `If-None-Match: *`, which - * S3 checks and honours in one step. - */ - public function create(string $path, StreamInterface $data, string $contentType = ''): string - { - return $this->put($path, $data, $contentType, ['if-none-match' => '*']); - } - - /** - * Write over the object with the given ETag, with `If-Match`, which S3 - * checks and honours in one step. - */ - public function replace(string $path, StreamInterface $data, string $etag, string $contentType = ''): string - { - return $this->put($path, $data, $contentType, ['if-match' => $this->quote($etag)]); - } - - /** - * Send a PutObject request and return the ETag of the object written. - * - * @param array $headers Conditions on the write - * - * @throws StorageException - */ - private function put(string $path, StreamInterface $data, string $contentType, array $headers = []): string - { - $uri = $path !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($path)) : '/'; - - $response = $this->call( - Method::PUT, - $uri, - $data, - headers: ['content-type' => $contentType] + $headers, - amzHeaders: $this->aclHeaders(), - ); - - return $this->unquote($response->headers['etag'] ?? throw new RemoteException('Missing ETag in S3 response')); - } - - /** - * Delete file in given path, Return true on success and false on failure. - * - * @see http://php.net/manual/en/function.filesize.php - * - * @throws StorageException - */ - public function delete(string $path, bool $recursive = false): bool - { - $uri = ($path !== '') ? '/' . str_replace('%2F', '/', rawurlencode($path)) : '/'; - - $this->call(Method::DELETE, $uri); - - return true; - } - - /** - * Get list of objects in the given path. - * - * @return array - * - * @throws StorageException - */ - protected function listObjects(string $prefix = '', int $maxKeys = self::MAX_PAGE_SIZE, string $continuationToken = ''): array - { - if ($maxKeys > self::MAX_PAGE_SIZE) { - throw new \InvalidArgumentException('Cannot list more than ' . self::MAX_PAGE_SIZE . ' objects'); - } - - $uri = '/'; - $prefix = ltrim($prefix, '/'); /** S3 specific requirement that prefix should never contain a leading slash */ - $parameters = [ - 'list-type' => 2, - 'prefix' => $prefix, - 'max-keys' => $maxKeys, - ]; - - if ($continuationToken !== '' && $continuationToken !== '0') { - $parameters['continuation-token'] = $continuationToken; - } - - $response = $this->call(Method::GET, $uri, '', $parameters, headers: ['content-type' => 'text/plain']); - - if (! \is_array($response->body)) { - throw new RemoteException('Unexpected S3 list response'); - } - - return $response->body; - } - - /** - * Copy a file to another path, on this device or onto another one. - * - * A same-device copy with a known bucket runs entirely server side — - * `CopyObject` up to 5 GB, `UploadPartCopy` beyond — so no bytes move - * through PHP. Everything else falls back to the streamed base copy. - * - * @throws StorageException - */ - #[\Override] - public function copy(string $source, string $target, ?Device $to = null, int $chunkSize = self::COPY_CHUNK_SIZE): bool - { - if ((!$to instanceof \Utopia\Storage\Device || $to === $this) && $this->bucket !== null) { - return $this->copyObject($source, $target); - } - - return parent::copy($source, $target, $to, $chunkSize); - } - - /** - * Copy an object server side within this bucket. - * - * @throws StorageException - */ - private function copyObject(string $source, string $target): bool - { - $info = $this->getInfo($source); - $size = (int) ($info['content-length'] ?? 0); - - $copySource = '/' . $this->bucket . '/' . ltrim(str_replace('%2F', '/', rawurlencode($source)), '/'); - $uri = $target !== '' ? '/' . str_replace(['%2F', '%3F'], ['/', '?'], rawurlencode($target)) : '/'; - - if ($size <= self::MAX_COPY_OBJECT_SIZE) { - $response = $this->call(Method::PUT, $uri, amzHeaders: [ - 'x-amz-copy-source' => $copySource, - 'x-amz-metadata-directive' => 'COPY', - ] + $this->aclHeaders()); - - // S3 reports CopyObject failures in a 200 body, so success is the ETag. - if (! \is_array($response->body) || ! isset($response->body['ETag'])) { - throw new RemoteException('Unexpected S3 copy response'); - } - - return true; - } - - $uploadId = $this->createMultipartUpload($target, $info['content-type'] ?? ''); - try { - $parts = []; - $totalParts = (int) ceil($size / self::MAX_COPY_OBJECT_SIZE); - for ($part = 1; $part <= $totalParts; ++$part) { - $start = ($part - 1) * self::MAX_COPY_OBJECT_SIZE; - $end = min($size, $start + self::MAX_COPY_OBJECT_SIZE) - 1; - $response = $this->call( - Method::PUT, - $uri, - parameters: ['partNumber' => $part, 'uploadId' => $uploadId], - amzHeaders: [ - 'x-amz-copy-source' => $copySource, - 'x-amz-copy-source-range' => "bytes=$start-$end", - ], - ); - - $etag = \is_array($response->body) ? ($response->body['ETag'] ?? null) : null; - if (! \is_string($etag)) { - throw new RemoteException('Missing ETag in S3 response'); - } - $parts[$part] = $etag; - } - $this->completeMultipartUpload($target, $uploadId, $parts); - } catch (\Throwable $e) { - // Best effort — unclaimed multipart parts are billed until aborted. - try { - $this->abort($target, $uploadId); - } catch (\Throwable) { - } - throw $e; - } - - return true; - } - - /** - * Delete files in given path, path must be a directory. Return true on success and false on failure. - * - * - * @throws StorageException - */ - public function deletePath(string $path): bool - { - $path = $this->getRoot() . '/' . $path; - - $uri = '/'; - $continuationToken = ''; - do { - $objects = $this->listObjects($path, continuationToken: $continuationToken); - $token = $objects['NextContinuationToken'] ?? ''; - $continuationToken = \is_string($token) ? $token : ''; - - // A single object is returned as one associative entry, multiple objects as a list of them. - $contents = $objects['Contents'] ?? []; - $entries = \is_array($contents) ? (isset($contents['Key']) ? [$contents] : $contents) : []; - - $keys = []; - foreach ($entries as $object) { - $key = \is_array($object) ? ($object['Key'] ?? null) : null; - if (\is_string($key)) { - $keys[] = $key; - } - } - - if ($keys === []) { - break; - } - - $body = ''; - foreach ($keys as $key) { - $body .= "{$key}"; - } - $body .= 'true'; - $body .= ''; - $this->call(Method::POST, $uri, $body, ['delete' => ''], headers: ['content-type' => 'application/xml']); - } while ($continuationToken !== ''); - - return true; - } - - /** - * Check if file exists - */ - public function exists(string $path): bool - { - try { - $this->getInfo($path); - } catch (NotFoundException) { - return false; - } - - return true; - } - - /** - * Size, last modification and ETag of an object, from one HEAD request. - */ - public function getFileInfo(string $path): FileInfo - { - $headers = $this->getInfo($path); - $modified = isset($headers['last-modified']) ? strtotime($headers['last-modified']) : false; - - return new FileInfo( - path: $path, - size: (int) ($headers['content-length'] ?? 0), - modifiedAt: $modified === false ? null : new \DateTimeImmutable('@' . $modified), - etag: isset($headers['etag']) ? $this->unquote($headers['etag']) : null, - ); - } - - /** - * Returns given file path its size. - * - * @see http://php.net/manual/en/function.filesize.php - */ - public function getFileSize(string $path): int - { - $response = $this->getInfo($path); - - return (int) ($response['content-length'] ?? 0); - } - - /** - * Returns given file path its mime type. - * - * @see http://php.net/manual/en/function.mime-content-type.php - */ - public function getFileMimeType(string $path): string - { - $response = $this->getInfo($path); - - return $response['content-type'] ?? ''; - } - - /** - * Returns given file path its MD5 hash value. - * - * @see http://php.net/manual/en/function.md5-file.php - */ - public function getFileHash(string $path): string - { - return $this->unquote($this->getInfo($path)['etag'] ?? ''); - } - - /** - * List objects under the given prefix, one page at a time. - * - * The cursor is the S3 continuation token. - * - * @throws StorageException - */ - public function listFiles(string $prefix = '', int $max = self::MAX_PAGE_SIZE, ?string $cursor = null): FileList - { - $data = $this->listObjects($prefix, $max, $cursor ?? ''); - - // A single object is returned as one associative entry, multiple objects as a list of them. - $contents = $data['Contents'] ?? []; - $entries = \is_array($contents) ? (isset($contents['Key']) ? [$contents] : $contents) : []; - - $files = []; - foreach ($entries as $object) { - if (! \is_array($object)) { - continue; - } - if (! \is_string($object['Key'] ?? null)) { - continue; - } - $size = $object['Size'] ?? null; - $modified = $object['LastModified'] ?? null; - $etag = $object['ETag'] ?? null; - $files[] = new FileInfo( - path: $object['Key'], - size: is_numeric($size) ? (int) $size : 0, - modifiedAt: \is_string($modified) ? new \DateTimeImmutable($modified) : null, - etag: \is_string($etag) ? trim($etag, '"') : null, - ); - } - - $token = $data['NextContinuationToken'] ?? null; - - return new FileList( - files: $files, - cursor: ($data['IsTruncated'] ?? null) === 'true' && \is_string($token) ? $token : null, - ); - } - - /** - * List the multipart uploads in progress under the given prefix, one page - * at a time: those prepared but neither finalized nor aborted, whose parts - * are billed until one or the other happens. - * - * The cursor is the pair of markers S3 pages by. Amazon S3 takes any - * prefix; some compatible services, MinIO among them, only honour one that - * is a whole key, and answer any other with an empty page. - * - * @param int<1, max> $max - * - * @throws StorageException - */ - public function listUploads(string $prefix = '', int $max = self::MAX_PAGE_SIZE, ?string $cursor = null): UploadList - { - if ($max > self::MAX_PAGE_SIZE) { - throw new \InvalidArgumentException('Cannot list more than ' . self::MAX_PAGE_SIZE . ' uploads'); - } - - $parameters = [ - 'uploads' => '', - 'prefix' => ltrim($prefix, '/'), - 'max-uploads' => $max, - ]; - - if ($cursor !== null && $cursor !== '') { - $markers = json_decode($cursor, true); - if (! \is_array($markers) || ! \is_string($markers['key'] ?? null) || ! \is_string($markers['upload'] ?? null)) { - throw new \InvalidArgumentException('Invalid cursor'); - } - $parameters['key-marker'] = $markers['key']; - $parameters['upload-id-marker'] = $markers['upload']; - } - - $response = $this->call(Method::GET, '/', '', $parameters, headers: ['content-type' => 'text/plain']); - - if (! \is_array($response->body)) { - throw new RemoteException('Unexpected S3 upload listing response'); - } - - // A single upload is returned as one associative entry, multiple uploads as a list of them. - $contents = $response->body['Upload'] ?? []; - $entries = \is_array($contents) ? (isset($contents['Key']) ? [$contents] : $contents) : []; - - $uploads = []; - foreach ($entries as $entry) { - if (! \is_array($entry)) { - continue; - } - if (! \is_string($entry['Key'] ?? null)) { - continue; - } - if (! \is_string($entry['UploadId'] ?? null)) { - continue; - } - $initiated = $entry['Initiated'] ?? null; - $uploads[] = new UploadInfo( - path: $entry['Key'], - uploadId: $entry['UploadId'], - initiatedAt: \is_string($initiated) ? new \DateTimeImmutable($initiated) : null, - ); - } - - $keyMarker = $response->body['NextKeyMarker'] ?? null; - $uploadMarker = $response->body['NextUploadIdMarker'] ?? null; - $truncated = ($response->body['IsTruncated'] ?? null) === 'true' && \is_string($keyMarker) && \is_string($uploadMarker); - - return new UploadList( - uploads: $uploads, - cursor: $truncated ? (string) json_encode(['key' => $keyMarker, 'upload' => $uploadMarker]) : null, - ); - } - - /** - * Get file info - * - * @return array - * - * @throws StorageException - */ - private function getInfo(string $path): array - { - $uri = $path !== '' ? '/' . str_replace('%2F', '/', rawurlencode($path)) : '/'; - $response = $this->call(Method::HEAD, $uri); - - return $response->headers; - } - - /** - * The ACL header for a write, or none when the device was told not to send one. - * - * @return array - */ - private function aclHeaders(): array - { - return $this->acl instanceof Acl ? ['x-amz-acl' => $this->acl->value] : []; - } - - /** - * An ETag as S3 reports it, in double quotes, from the bare form the library hands out. - */ - private function quote(string $etag): string - { - return str_starts_with($etag, '"') ? $etag : '"' . $etag . '"'; - } - - /** - * The bare form of an ETag, without the double quotes S3 puts around it. - */ - private function unquote(string $etag): string - { - return trim($etag, '"'); - } - - /** - * Generate the headers for AWS Signature V4 - * - * @param non-empty-string $method - * @param array $parameters - * @param array $headers - * @param array $amzHeaders - */ - private function getSignatureV4(string $method, string $uri, array $parameters, array $headers, array $amzHeaders): string - { - $service = 's3'; - $region = $this->region; - - $algorithm = 'AWS4-HMAC-SHA256'; - $combinedHeaders = []; - - $amzDateStamp = substr($amzHeaders['x-amz-date'] ?? '', 0, 8); - - // CanonicalHeaders - foreach ($headers as $k => $v) { - $combinedHeaders[strtolower($k)] = trim($v); - } - - foreach ($amzHeaders as $k => $v) { - $combinedHeaders[strtolower($k)] = trim($v); - } - - uksort($combinedHeaders, $this->sortMetaHeadersCmp(...)); - - // Convert null query string parameters to strings and sort - uksort($parameters, $this->sortMetaHeadersCmp(...)); - $queryString = http_build_query($parameters, '', '&', PHP_QUERY_RFC3986); - - // Payload - $amzPayload = [$method]; - - $qsPos = strpos($uri, '?'); - $amzPayload[] = ($qsPos === false ? $uri : substr($uri, 0, $qsPos)); - - $amzPayload[] = $queryString; - - foreach ($combinedHeaders as $k => $v) { // add header as string to requests - $amzPayload[] = $k . ':' . $v; - } - - $amzPayload[] = ''; // add a blank entry so we end up with an extra line break - $amzPayload[] = implode(';', array_keys($combinedHeaders)); // SignedHeaders - $amzPayload[] = $amzHeaders['x-amz-content-sha256'] ?? ''; // payload hash - - $amzPayloadStr = implode("\n", $amzPayload); // request as string - - // CredentialScope - $credentialScope = [$amzDateStamp, $region, $service, 'aws4_request']; - - // stringToSign - $stringToSignStr = implode("\n", [ - $algorithm, - $amzHeaders['x-amz-date'] ?? '', - implode('/', $credentialScope), - hash('sha256', $amzPayloadStr), - ]); - - // Make Signature - $kSecret = 'AWS4' . $this->secretKey; - $kDate = hash_hmac('sha256', $amzDateStamp, $kSecret, true); - $kRegion = hash_hmac('sha256', $region, $kDate, true); - $kService = hash_hmac('sha256', $service, $kRegion, true); - $kSigning = hash_hmac('sha256', 'aws4_request', $kService, true); - - $signature = hash_hmac('sha256', mb_convert_encoding($stringToSignStr, 'utf-8'), $kSigning); - - return $algorithm . ' ' . implode(',', [ - 'Credential=' . $this->accessKey . '/' . implode('/', $credentialScope), - 'SignedHeaders=' . implode(';', array_keys($combinedHeaders)), - 'Signature=' . $signature, - ]); - } - - /** - * Execute a signed S3 request and return its response. - * - * Headers are built per call — the instance holds no request state, so a - * single device is safe to share across concurrent coroutines. - * - * When a $sink is given, the response body is delivered to it chunk by - * chunk instead of being buffered; only its head is kept so an error - * response can still be parsed. - * - * @param non-empty-string $method - * @param array $parameters - * @param array $headers - * @param array $amzHeaders - * @param (callable(string): void)|null $sink - * - * @throws StorageException - */ - protected function call(string $method, string $uri, StreamInterface|string $data = '', array $parameters = [], array $headers = [], array $amzHeaders = [], bool $decode = true, ?callable $sink = null): S3\Response - { - $uri = $this->path . $this->getAbsolutePath($uri); - $url = $this->fqdn . $uri . '?' . http_build_query($parameters, '', '&', PHP_QUERY_RFC3986); - - if ($data instanceof StreamInterface) { - [$md5, $sha256, $length] = $this->hashBody($data); - $body = $data; - } else { - $md5 = base64_encode(md5($data, true)); - $sha256 = hash('sha256', $data); - $length = \strlen($data); - $body = new Stream($data); - } - - $headers = array_filter($headers, fn(string $value): bool => $value !== ''); - $headers['host'] = $this->host; - $headers['date'] = gmdate('D, d M Y H:i:s T'); - $headers['content-md5'] = $md5; - // Send an explicit Content-Length (signed, alongside content-md5). Without - // it the cURL transport streams the body with Transfer-Encoding: chunked — - // or omits the header on an empty POST — which S3-compatible services such - // as GCS reject with HTTP 411. The value is the full body size, so it also - // matches what the transport sends for a size-known stream. - $headers['content-length'] = (string) $length; - - $amzHeaders = array_filter($amzHeaders, fn(string $value): bool => $value !== ''); - $amzHeaders['x-amz-date'] = gmdate('Ymd\THis\Z'); - $amzHeaders['x-amz-content-sha256'] = $sha256; - - $request = new Request($method, Uri::parse($url), $body); - foreach ([...$amzHeaders, ...$headers] as $header => $value) { - $request = $request->withHeader($header, $value); - } - $request = $request - ->withHeader('authorization', $this->getSignatureV4($method, $uri, $parameters, $headers, $amzHeaders)) - ->withHeader('user-agent', 'utopia-php/storage'); - - try { - if ($sink === null) { - $response = $this->client->sendRequest($request); - $responseBody = (string) $response->getBody(); - } else { - $head = ''; - $tee = static function (string $chunk) use ($sink, &$head): void { - if (\strlen($head) < self::ERROR_BODY_BUFFER_SIZE) { - $head .= substr($chunk, 0, self::ERROR_BODY_BUFFER_SIZE - \strlen($head)); - } - $sink($chunk); - }; - $response = $this->client->stream($request, $tee); - $responseBody = $head; - } - } catch (ClientExceptionInterface $e) { - throw new TransportException($e->getMessage(), $e->getCode(), $e); - } - - $code = $response->getStatusCode(); - - $responseHeaders = []; - foreach ($response->getHeaders() as $name => $values) { - $responseHeaders[strtolower((string) $name)] = implode(', ', $values); - } - - if ($code >= 400) { - $this->parseAndThrowS3Error($responseBody, $code, $responseHeaders); - } - - $contentType = $responseHeaders['content-type'] ?? ''; - $isXml = $contentType === 'application/xml' || (str_starts_with($responseBody, 'decodeXml($responseBody) : $responseBody, - ); - } - - /** - * Hash a request body for signing without materializing it as a string. - * - * SigV4 needs the payload digests before the first byte is sent, so the - * stream is read once for hashing and rewound for the actual send — the - * same approach the AWS SDK takes. This is why S3 requires seekable - * streams. Hashing starts from the beginning, matching the transport: - * the cURL adapter rewinds seekable bodies before sending, so the - * signature must cover the full stream. - * - * @return array{string, string, int} Base64 MD5, hex SHA-256, and byte length of the full stream - */ - private function hashBody(StreamInterface $body): array - { - if (! $body->isSeekable()) { - throw new \InvalidArgumentException('S3 requires a seekable stream so the payload can be signed'); - } - - $body->rewind(); - $md5 = hash_init('md5'); - $sha256 = hash_init('sha256'); - $length = 0; - while (! $body->eof()) { - $chunk = $body->read(self::PIPE_CHUNK_SIZE); - if ($chunk === '') { - break; - } - $length += \strlen($chunk); - hash_update($md5, $chunk); - hash_update($sha256, $chunk); - } - $body->rewind(); - - return [base64_encode(hash_final($md5, true)), hash_final($sha256), $length]; - } - - /** - * Decode an XML response body into an associative array. - * - * @return array - * - * @throws StorageException - */ - private function decodeXml(string $body): array - { - $xml = @simplexml_load_string($body, \SimpleXMLElement::class, LIBXML_NONET | LIBXML_NOCDATA); - $decoded = $xml === false ? null : $this->xmlToArray($xml); - if (! \is_array($decoded)) { - throw new RemoteException('Failed to decode S3 XML response'); - } - - return $decoded; - } - - /** - * Convert an XML element into nested arrays: repeated child names become - * lists, text-only elements become strings and empty elements become - * empty arrays. - * - * @return array|string - */ - private function xmlToArray(\SimpleXMLElement $element): array|string - { - $children = $element->children(); - if (\count($children) === 0) { - $text = (string) $element; - - return $text === '' ? [] : $text; - } - - $grouped = []; - foreach ($children as $name => $child) { - $grouped[$name][] = $this->xmlToArray($child); - } - - $result = []; - foreach ($grouped as $name => $values) { - $result[$name] = \count($values) === 1 ? $values[0] : $values; - } - - return $result; - } - - /** - * Parse an S3 error response and throw the matching exception. - * - * @param string $errorBody The error response body - * @param int $statusCode The HTTP status code - * @param array $headers The response headers, for the S3 request IDs provider support asks for - * - * @throws NotFoundException When the object does not exist (404, or a NoSuchKey error code) - * @throws PreconditionFailedException When a condition on the request did not hold (412) - * @throws RemoteException For every other error response - */ - private function parseAndThrowS3Error(string $errorBody, int $statusCode, array $headers = []): never - { - $errorCode = null; - $errorMessage = null; - if (str_starts_with(ltrim($errorBody), 'Code ?? '') ?: null; - $errorMessage = (string) ($xml->Message ?? '') ?: null; - } - } - - $requestIds = array_filter([ - 'request-id' => $headers['x-amz-request-id'] ?? '', - 'id-2' => $headers['x-amz-id-2'] ?? '', - ]); - $suffix = $requestIds === [] ? '' : ' [' . implode(', ', array_map( - fn(string $key, string $value): string => "$key: $value", - array_keys($requestIds), - $requestIds, - )) . ']'; - - // HEAD error responses carry no body, so the status code is the only signal. - if ($statusCode === 404 || $errorCode === 'NoSuchKey') { - throw new NotFoundException(($errorMessage ?? 'File not found') . $suffix, $statusCode); - } - - if ($statusCode === 412 || $errorCode === 'PreconditionFailed') { - throw new PreconditionFailedException(($errorMessage ?? 'Precondition failed') . $suffix, $statusCode); - } - - throw new RemoteException(($errorMessage ?? ($errorBody !== '' ? $errorBody : 'S3 request failed')) . $suffix, $statusCode, $errorCode); - } - - /** - * Sort compare for meta headers - * - * @internal Used to sort x-amz meta headers - * - * @param string $a String A - * @param string $b String B - */ - protected function sortMetaHeadersCmp(string $a, string $b): int - { - $lenA = \strlen($a); - $lenB = \strlen($b); - $minLen = min($lenA, $lenB); - $ncmp = strncmp($a, $b, $minLen); - if ($lenA === $lenB) { - return $ncmp; - } - - if ($ncmp === 0) { - return $lenA < $lenB ? -1 : 1; - } - - return $ncmp; - } -} diff --git a/packages/storage/src/Storage/Device/S3/Response.php b/packages/storage/src/Storage/Device/S3/Response.php deleted file mode 100644 index 07383d1b8..000000000 --- a/packages/storage/src/Storage/Device/S3/Response.php +++ /dev/null @@ -1,18 +0,0 @@ - $headers - * @param string|array $body Raw body, or the decoded XML document - */ - public function __construct( - public int $code, - public array $headers, - public string|array $body, - ) {} -} diff --git a/packages/storage/src/Storage/Device/S3/RetryStrategy.php b/packages/storage/src/Storage/Device/S3/RetryStrategy.php deleted file mode 100644 index fcd9309c7..000000000 --- a/packages/storage/src/Storage/Device/S3/RetryStrategy.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ - private const array TRANSIENT_ERROR_CODES = ['SlowDown', 'ServiceUnavailable', 'Throttling', 'RequestThrottled']; - - /** - * @var array - */ - private const array TRANSIENT_STATUS_CODES = [429, 503]; - - private Closure $randomizer; - - /** - * @param int $retries Retries after the initial attempt - * @param float $delay Base delay in seconds; the wait before retry N is drawn uniformly from [0, min(maxDelay, delay * 2^(N-1))) - * @param float $maxDelay Ceiling for the backoff window in seconds - * @param (Closure(): float)|null $randomizer Returns a value in [0, 1) for jitter - */ - public function __construct( - private int $retries = 3, - private float $delay = 0.5, - private float $maxDelay = 20.0, - ?Closure $randomizer = null, - ) { - $this->randomizer = $randomizer ?? static fn(): float => mt_rand() / mt_getrandmax(); - } - - public function delay(RequestInterface $request, int $attempt, ?ResponseInterface $response, ?ClientExceptionInterface $error): ?float - { - if ($attempt > $this->retries || ! $response instanceof ResponseInterface) { - return null; - } - - if (! $this->isTransient($response)) { - return null; - } - - return ($this->randomizer)() * min($this->maxDelay, $this->delay * 2 ** ($attempt - 1)); - } - - private function isTransient(ResponseInterface $response): bool - { - $body = (string) $response->getBody(); - - $trimmed = ltrim($body); - if (str_starts_with($trimmed, 'Code ?? ''); - if (\in_array($code, self::TRANSIENT_ERROR_CODES, true)) { - return true; - } - // Successfully parsed XML with a non-transient error code — do not retry. - if ($code !== '') { - return false; - } - } - } - - // Fall back to HTTP status code for responses that cannot be parsed as XML. - return \in_array($response->getStatusCode(), self::TRANSIENT_STATUS_CODES, true); - } -} diff --git a/packages/storage/src/Storage/Device/Telemetry.php b/packages/storage/src/Storage/Device/Telemetry.php deleted file mode 100644 index 4d5224094..000000000 --- a/packages/storage/src/Storage/Device/Telemetry.php +++ /dev/null @@ -1,214 +0,0 @@ -telemetry = $telemetry->createHistogram( - name: 'storage.operation', - unit: 's', - advisory: ['ExplicitBucketBoundaries' => [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10]], - ); - } - - /** - * The decorated device, for access to adapter-specific methods that are - * not part of the base contract (for example `Local` partition metrics or - * the `S3` object listing). - */ - public function getDevice(): Device - { - return $this->device; - } - - /** - * @template T - * - * @param callable(): T $operation - * @return T - */ - private function measure(string $method, callable $operation): mixed - { - $start = microtime(true); - try { - return $operation(); - } finally { - $this->telemetry->record( - microtime(true) - $start, - [ - 'storage' => $this->device->getType()->value, - 'operation' => "device:$method", - ], - ); - } - } - - public function getType(): DeviceType - { - return $this->device->getType(); - } - - public function getRoot(): string - { - return $this->device->getRoot(); - } - - public function getPath(string $filename): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->getPath($filename)); - } - - /** - * @param UploadMetadata $metadata - */ - public function prepare(string $path, string $contentType, int $chunks = 1, array &$metadata = []): void - { - $this->measure(__FUNCTION__, function () use ($path, $contentType, $chunks, &$metadata): void { - $this->device->prepare($path, $contentType, $chunks, $metadata); - }); - } - - /** - * @param UploadMetadata $metadata - */ - /** - * @param UploadMetadata $metadata - */ - protected function uploadChunk(StreamInterface $data, string $path, int $chunk, int $chunks, array &$metadata): int - { - return $this->measure(__FUNCTION__, function () use ($data, $path, $chunk, $chunks, &$metadata): int { - return $this->device->uploadChunk($data, $path, $chunk, $chunks, $metadata); - }); - } - - /** - * @param UploadMetadata $metadata - */ - public function finalize(string $path, int $chunks = 1, array &$metadata = []): bool - { - return $this->measure(__FUNCTION__, function () use ($path, $chunks, &$metadata): bool { - return $this->device->finalize($path, $chunks, $metadata); - }); - } - - public function abort(string $path, string $uploadId = ''): bool - { - return $this->measure(__FUNCTION__, fn(): bool => $this->device->abort($path, $uploadId)); - } - - /** - * @param int<0, max> $offset - * @param int<0, max>|null $length - */ - public function read(string $path, int $offset = 0, ?int $length = null, ?string $etag = null): StreamInterface - { - return $this->measure(__FUNCTION__, fn(): StreamInterface => $this->device->read($path, $offset, $length, $etag)); - } - - #[\Override] - public function copy(string $source, string $target, ?Device $to = null, int $chunkSize = self::COPY_CHUNK_SIZE): bool - { - return $this->measure(__FUNCTION__, fn(): bool => $this->device->copy($source, $target, $to, $chunkSize)); - } - - public function write(string $path, StreamInterface $data, string $contentType): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->write($path, $data, $contentType)); - } - - public function create(string $path, StreamInterface $data, string $contentType = ''): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->create($path, $data, $contentType)); - } - - public function replace(string $path, StreamInterface $data, string $etag, string $contentType = ''): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->replace($path, $data, $etag, $contentType)); - } - - public function delete(string $path, bool $recursive = false): bool - { - return $this->measure(__FUNCTION__, fn(): bool => $this->device->delete($path, $recursive)); - } - - public function deletePath(string $path): bool - { - return $this->measure(__FUNCTION__, fn(): bool => $this->device->deletePath($path)); - } - - public function exists(string $path): bool - { - return $this->measure(__FUNCTION__, fn(): bool => $this->device->exists($path)); - } - - /** - * @param int<1, max> $max - */ - public function listFiles(string $prefix = '', int $max = 1000, ?string $cursor = null): FileList - { - return $this->measure(__FUNCTION__, fn(): FileList => $this->device->listFiles($prefix, $max, $cursor)); - } - - /** - * List the multipart uploads in progress on the decorated device. - * - * Only `S3` has uploads to list; wrapping anything else and asking for - * them is a programming error rather than an empty page, which would read - * as "nothing is being billed". - * - * @param int<1, max> $max - * - * @throws \BadMethodCallException When the decorated device has no multipart uploads - */ - public function listUploads(string $prefix = '', int $max = 1000, ?string $cursor = null): UploadList - { - $device = $this->device; - if (! $device instanceof S3) { - throw new \BadMethodCallException($device::class . ' does not list multipart uploads'); - } - - return $this->measure(__FUNCTION__, fn(): UploadList => $device->listUploads($prefix, $max, $cursor)); - } - - public function getFileInfo(string $path): FileInfo - { - return $this->measure(__FUNCTION__, fn(): FileInfo => $this->device->getFileInfo($path)); - } - - public function getFileSize(string $path): int - { - return $this->measure(__FUNCTION__, fn(): int => $this->device->getFileSize($path)); - } - - public function getFileMimeType(string $path): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->getFileMimeType($path)); - } - - public function getFileHash(string $path): string - { - return $this->measure(__FUNCTION__, fn(): string => $this->device->getFileHash($path)); - } -} diff --git a/packages/storage/src/Storage/Device/Wasabi.php b/packages/storage/src/Storage/Device/Wasabi.php deleted file mode 100644 index 9a9c96287..000000000 --- a/packages/storage/src/Storage/Device/Wasabi.php +++ /dev/null @@ -1,59 +0,0 @@ - $files - */ - public function __construct( - public array $files, - public ?string $cursor = null, - ) {} -} diff --git a/packages/storage/src/Storage/UploadInfo.php b/packages/storage/src/Storage/UploadInfo.php deleted file mode 100644 index b5a4784be..000000000 --- a/packages/storage/src/Storage/UploadInfo.php +++ /dev/null @@ -1,17 +0,0 @@ - $uploads - */ - public function __construct( - public array $uploads, - public ?string $cursor = null, - ) {} -} diff --git a/packages/storage/src/Storage/Validator/FileExt.php b/packages/storage/src/Storage/Validator/FileExt.php deleted file mode 100644 index 9bfafd0b3..000000000 --- a/packages/storage/src/Storage/Validator/FileExt.php +++ /dev/null @@ -1,73 +0,0 @@ - $allowed - */ - public function __construct(protected array $allowed) {} - - /** - * Get Description - */ - public function getDescription(): string - { - return 'File extension is not valid'; - } - - /** - * Check if file extenstion is allowed - * - * @param mixed $filename - */ - public function isValid($filename): bool - { - if (! \is_string($filename)) { - return false; - } - $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); - - return \in_array($ext, $this->allowed); - } - - /** - * Is array - * - * Function will return true if object is array. - */ - public function isArray(): bool - { - return false; - } - - /** - * Get Type - * - * Returns validator type. - */ - public function getType(): string - { - return self::TYPE_STRING; - } -} diff --git a/packages/storage/src/Storage/Validator/FileName.php b/packages/storage/src/Storage/Validator/FileName.php deleted file mode 100644 index 2e2e7caf8..000000000 --- a/packages/storage/src/Storage/Validator/FileName.php +++ /dev/null @@ -1,58 +0,0 @@ -max; - } - - /** - * Finds whether a file size is smaller than required limit. - * - * @param mixed $fileSize - */ - public function isValid($fileSize): bool - { - if (! \is_int($fileSize)) { - return false; - } - return $fileSize <= $this->max; - } - - /** - * Is array - * - * Function will return true if object is array. - */ - public function isArray(): bool - { - return false; - } - - /** - * Get Type - * - * Returns validator type. - */ - public function getType(): string - { - return self::TYPE_INTEGER; - } -} diff --git a/packages/storage/src/Storage/Validator/FileType.php b/packages/storage/src/Storage/Validator/FileType.php deleted file mode 100644 index 5d472f228..000000000 --- a/packages/storage/src/Storage/Validator/FileType.php +++ /dev/null @@ -1,127 +0,0 @@ - - */ - protected $types = [ - self::FILE_TYPE_JPEG => "\xFF\xD8\xFF", - self::FILE_TYPE_GIF => 'GIF', - self::FILE_TYPE_PNG => "\x89\x50\x4e\x47\x0d\x0a", - self::FILE_TYPE_GZIP => 'application/x-gzip', - ]; - - /** - * @var array - */ - protected array $allowed; - - /** - * @param array $allowed - * - * @throws Exception - */ - public function __construct(array $allowed) - { - foreach ($allowed as $key) { - if (! isset($this->types[$key])) { - throw new \InvalidArgumentException('Unknown file mime type'); - } - } - - $this->allowed = $allowed; - } - - /** - * Get Description - */ - public function getDescription(): string - { - return 'File mime-type is not allowed '; - } - - /** - * Is Valid. - * - * Binary check to finds whether a file is of valid type - * - * @see http://stackoverflow.com/a/3313196 - * - * @param mixed $path - */ - public function isValid($path): bool - { - if (! \is_string($path) || ! is_readable($path)) { - return false; - } - - $handle = fopen($path, 'r'); - - if (! $handle) { - return false; - } - - $bytes = fgets($handle, 8); - if ($bytes === false) { - fclose($handle); - - return false; - } - - foreach ($this->allowed as $key) { - if (str_starts_with($bytes, $this->types[$key])) { - fclose($handle); - - return true; - } - } - - fclose($handle); - - return false; - } - - /** - * Is array - * - * Function will return true if object is array. - */ - public function isArray(): bool - { - return false; - } - - /** - * Get Type - * - * Returns validator type. - */ - public function getType(): string - { - return self::TYPE_STRING; - } -} diff --git a/packages/storage/src/Storage/Validator/Upload.php b/packages/storage/src/Storage/Validator/Upload.php deleted file mode 100644 index 0d8f3541b..000000000 --- a/packages/storage/src/Storage/Validator/Upload.php +++ /dev/null @@ -1,54 +0,0 @@ - $length - */ - private function readBytes($handle, int $length): string - { - $contents = fread($handle, $length); - if ($contents === false) { - throw new \RuntimeException('Failed to read stream'); - } - - return $contents; - } - - abstract protected function init(): void; - - abstract protected function getAdapterType(): DeviceType; - - /** - * @var S3 - */ - protected $object; - - /** - * @var string - */ - protected $root = '/root'; - - protected function setUp(): void - { - $this->init(); - $this->uploadTestFiles(); - } - - private function uploadFile(string $source, string $path): void - { - $handle = $this->openStream($source); - $this->object->upload(Stream::fromResource($handle), $path, mime_content_type($source) ?: ''); - } - - private function uploadTestFiles(): void - { - $this->uploadFile(__DIR__ . '/../resources/disk-a/kitten-1.jpg', $this->object->getPath('testing/kitten-1.jpg')); - $this->uploadFile(__DIR__ . '/../resources/disk-a/kitten-2.jpg', $this->object->getPath('testing/kitten-2.jpg')); - $this->uploadFile(__DIR__ . '/../resources/disk-b/kitten-1.png', $this->object->getPath('testing/kitten-1.png')); - $this->uploadFile(__DIR__ . '/../resources/disk-b/kitten-2.png', $this->object->getPath('testing/kitten-2.png')); - } - - private function removeTestFiles(): void - { - $this->object->delete($this->object->getPath('testing/kitten-1.jpg')); - $this->object->delete($this->object->getPath('testing/kitten-2.jpg')); - $this->object->delete($this->object->getPath('testing/kitten-1.png')); - $this->object->delete($this->object->getPath('testing/kitten-2.png')); - } - - protected function tearDown(): void - { - $this->removeTestFiles(); - } - - public function testListFiles(): void - { - $path = $this->object->getPath('testing/'); - $list = $this->object->listFiles($path); - - $this->assertCount(4, $list->files); - $this->assertNull($list->cursor); - - $file = $list->files[0]; - $this->assertStringContainsString('testing/kitten', $file->path); - $this->assertGreaterThan(0, $file->size); - $this->assertInstanceOf(\DateTimeImmutable::class, $file->modifiedAt); - $this->assertNotNull($file->etag); - } - - public function testListFilesPagination(): void - { - $path = $this->object->getPath('testing/'); - - $list = $this->object->listFiles($path, 3); - $this->assertCount(3, $list->files); - $this->assertNotNull($list->cursor); - - $list = $this->object->listFiles($path, 1000, $list->cursor); - $this->assertCount(1, $list->files); - $this->assertNull($list->cursor); - } - - public function testListFilesSingleObject(): void - { - $path = $this->object->getPath('single/'); - $this->object->write($path . 'only.txt', new Stream('one'), 'text/plain'); - - $list = $this->object->listFiles($path); - $this->assertCount(1, $list->files); - $this->assertSame(ltrim($path . 'only.txt', '/'), $list->files[0]->path); - $this->assertNull($list->cursor); - - $this->object->delete($path . 'only.txt'); - } - - public function testType(): void - { - $this->assertEquals($this->getAdapterType(), $this->object->getType()); - } - - public function testRoot(): void - { - $this->assertEquals($this->root, $this->object->getRoot()); - } - - public function testPath(): void - { - $this->assertEquals($this->root . '/image.png', $this->object->getPath('image.png')); - } - - public function testWrite(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text.txt'), new Stream('Hello World'), 'text/plain')); - - $this->object->delete($this->object->getPath('text.txt')); - } - - public function testRead(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-read.txt'), new Stream('Hello World'), 'text/plain')); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-read.txt'))); - - $this->object->delete($this->object->getPath('text-for-read.txt')); - } - - public function testReadNonExistentFile(): void - { - $this->expectException(NotFoundException::class); - $this->object->read($this->object->getPath('non-existent-file.txt')); - } - - public function testFileExists(): void - { - $this->assertEquals(true, $this->object->exists($this->object->getPath('testing/kitten-1.jpg'))); - $this->assertEquals(false, $this->object->exists($this->object->getPath('testing/kitten-5.jpg'))); - } - - public function testMove(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-move.txt'), new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($this->object->getPath('text-for-move.txt'))); - $this->assertEquals(true, $this->object->move($this->object->getPath('text-for-move.txt'), $this->object->getPath('text-for-move-new.txt'))); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-move-new.txt'))); - $this->assertEquals(false, $this->object->exists($this->object->getPath('text-for-move.txt'))); - - $this->object->delete($this->object->getPath('text-for-move-new.txt')); - } - - public function testCopySameDevice(): void - { - $source = $this->object->getPath('testing/kitten-1.jpg'); - $target = $this->object->getPath('testing/kitten-copy.jpg'); - - $this->assertTrue($this->object->copy($source, $target)); - $this->assertSame($this->object->getFileHash($source), $this->object->getFileHash($target)); - $this->assertSame($this->object->getFileSize($source), $this->object->getFileSize($target)); - - $this->object->delete($target); - } - - public function testMoveIdenticalName(): void - { - $file = '/kitten-1.jpg'; - $this->assertFalse($this->object->move($file, $file)); - } - - public function testDelete(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-delete.txt'), new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($this->object->getPath('text-for-delete.txt'))); - $this->assertEquals(true, $this->object->delete($this->object->getPath('text-for-delete.txt'))); - } - - public function testSvgUpload(): void - { - $this->uploadFile(__DIR__ . '/../resources/disk-b/appwrite.svg', $this->object->getPath('testing/appwrite.svg')); - $this->assertEquals(file_get_contents(__DIR__ . '/../resources/disk-b/appwrite.svg'), (string) $this->object->read($this->object->getPath('testing/appwrite.svg'))); - $this->assertEquals(true, $this->object->exists($this->object->getPath('testing/appwrite.svg'))); - $this->assertEquals(true, $this->object->delete($this->object->getPath('testing/appwrite.svg'))); - } - - public function testXmlUpload(): void - { - $this->uploadFile(__DIR__ . '/../resources/disk-a/config.xml', $this->object->getPath('testing/config.xml')); - $this->assertEquals(file_get_contents(__DIR__ . '/../resources/disk-a/config.xml'), (string) $this->object->read($this->object->getPath('testing/config.xml'))); - $this->assertEquals(true, $this->object->exists($this->object->getPath('testing/config.xml'))); - $this->assertEquals(true, $this->object->delete($this->object->getPath('testing/config.xml'))); - } - - public function testDeletePath(): void - { - // Test Single Object - $path = $this->object->getPath('text-for-delete-path.txt'); - $path = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path); - $this->assertSame(md5('Hello World'), $this->object->write($path, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path)); - $this->assertEquals(true, $this->object->deletePath('bucket')); - $this->assertEquals(false, $this->object->exists($path)); - - // Test Multiple Objects - $path = $this->object->getPath('text-for-delete-path1.txt'); - $path = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path); - $this->assertSame(md5('Hello World'), $this->object->write($path, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path)); - - $path2 = $this->object->getPath('text-for-delete-path2.txt'); - $path2 = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path2); - $this->assertSame(md5('Hello World'), $this->object->write($path2, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path2)); - - $this->assertEquals(true, $this->object->deletePath('bucket')); - $this->assertEquals(false, $this->object->exists($path)); - $this->assertEquals(false, $this->object->exists($path2)); - } - - public function testFileSize(): void - { - $this->assertEquals(599639, $this->object->getFileSize($this->object->getPath('testing/kitten-1.jpg'))); - $this->assertEquals(131958, $this->object->getFileSize($this->object->getPath('testing/kitten-2.jpg'))); - } - - public function testFileMimeType(): void - { - $this->assertEquals('image/jpeg', $this->object->getFileMimeType($this->object->getPath('testing/kitten-1.jpg'))); - $this->assertEquals('image/jpeg', $this->object->getFileMimeType($this->object->getPath('testing/kitten-2.jpg'))); - $this->assertEquals('image/png', $this->object->getFileMimeType($this->object->getPath('testing/kitten-1.png'))); - $this->assertEquals('image/png', $this->object->getFileMimeType($this->object->getPath('testing/kitten-2.png'))); - } - - public function testFileHash(): void - { - $this->assertEquals('7551f343143d2e24ab4aaf4624996b6a', $this->object->getFileHash($this->object->getPath('testing/kitten-1.jpg'))); - $this->assertEquals('81702fdeef2e55b1a22617bce4951cb5', $this->object->getFileHash($this->object->getPath('testing/kitten-2.jpg'))); - $this->assertEquals('03010f4f02980521a8fd6213b52ec313', $this->object->getFileHash($this->object->getPath('testing/kitten-1.png'))); - $this->assertEquals('8a9ed992b77e4b62b10e3a5c8ed72062', $this->object->getFileHash($this->object->getPath('testing/kitten-2.png'))); - } - - public function testPartUpload(): string - { - $source = __DIR__ . '/../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('uploaded.mp4'); - $totalSize = filesize($source); - // AWS S3 requires each part to be at least 5MB except for last part - $chunkSize = 5 * 1024 * 1024; - - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - - $metadata = [ - 'parts' => [], - 'chunks' => 0, - 'content_type' => mime_content_type($source) ?: '', - ]; - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, $metadata['content_type'] ?? '', $chunk, $chunks, $metadata); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - - $this->assertEquals(filesize($source), $this->object->getFileSize($dest)); - - // S3 doesnt provide a method to get a proper MD5-hash of a file created using multipart upload - // https://stackoverflow.com/questions/8618218/amazon-s3-checksum - // More info on how AWS calculates ETag for multipart upload here - // https://savjee.be/2015/10/Verifying-Amazon-S3-multi-part-uploads-with-ETag-hash/ - // TODO - // $this->assertEquals(\md5_file($source), $this->object->getFileHash($dest)); - // $this->object->delete($dest); - return $dest; - } - - public function testPartUploadRetry(): string - { - $source = __DIR__ . '/../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('uploaded.mp4'); - $totalSize = filesize($source); - // AWS S3 requires each part to be at least 5MB except for last part - $chunkSize = 5 * 1024 * 1024; - - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - - $metadata = [ - 'parts' => [], - 'chunks' => 0, - 'content_type' => mime_content_type($source) ?: '', - ]; - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, $metadata['content_type'] ?? '', $chunk, $chunks, $metadata); - $start += \strlen($contents); - ++$chunk; - break; - } - fclose($handle); - - $chunk = 1; - $start = 0; - // retry from first to make sure duplicate chunk re-upload works without issue - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, $metadata['content_type'] ?? '', $chunk, $chunks, $metadata); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - - $this->assertEquals(filesize($source), $this->object->getFileSize($dest)); - - // S3 doesnt provide a method to get a proper MD5-hash of a file created using multipart upload - // https://stackoverflow.com/questions/8618218/amazon-s3-checksum - // More info on how AWS calculates ETag for multipart upload here - // https://savjee.be/2015/10/Verifying-Amazon-S3-multi-part-uploads-with-ETag-hash/ - // TODO - // $this->assertEquals(\md5_file($source), $this->object->getFileHash($dest)); - // $this->object->delete($dest); - return $dest; - } - - public function testOutOfOrderPartUpload(): string - { - $source = __DIR__ . '/../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('uploaded-out-of-order.mp4'); - $totalSize = filesize($source); - // AWS S3 requires each part to be at least 5MB except for last part - $chunkSize = 5 * 1024 * 1024; - - $chunks = (int) ceil($totalSize / $chunkSize); - - // Read all chunk contents into memory so we can upload out of order - $parts = []; - $handle = $this->openStream($source); - $chunkNum = 1; - while ($chunkNum <= $chunks) { - $parts[$chunkNum] = $this->readBytes($handle, $chunkSize); - ++$chunkNum; - } - fclose($handle); - - $metadata = [ - 'parts' => [], - 'chunks' => 0, - 'content_type' => mime_content_type($source) ?: '', - ]; - - // Upload chunks in reverse order - for ($i = $chunks; $i >= 1; --$i) { - $this->object->upload(new Stream($parts[$i]), $dest, $metadata['content_type'] ?? '', $i, $chunks, $metadata); - } - - $this->assertEquals(filesize($source), $this->object->getFileSize($dest)); - - // S3 doesnt provide a method to get a proper MD5-hash of a file created using multipart upload - // TODO - // $this->assertEquals(\md5_file($source), $this->object->getFileHash($dest)); - // $this->object->delete($dest); - return $dest; - } - - #[Depends('testPartUpload')] - public function testPartRead(string $path): void - { - $source = __DIR__ . '/../resources/disk-a/large_file.mp4'; - $chunk = file_get_contents($source, false, null, 0, 500); - $readChunk = (string) $this->object->read($path, 0, 500); - $this->assertEquals($chunk, $readChunk); - } - - #[Depends('testPartUpload')] - public function testCopyLarge(string $path): void - { - // chunked file - $device = new Local(__DIR__ . '/../resources/disk-a'); - $destination = $device->getPath('largefile.mp4'); - - $this->assertTrue($this->object->copy($path, $destination, $device, 10000000)); // 10 mb chunks - $this->assertTrue($device->exists($destination)); - $this->assertSame('video/mp4', $device->getFileMimeType($destination)); - - $device->delete($destination); - $this->object->delete($path); - } - - public function testCopySmall(): void - { - $device = new Local(__DIR__ . '/../resources/disk-a'); - - $path = $this->object->getPath('text-for-read.txt'); - $this->object->write($path, new Stream('Hello World'), 'text/plain'); - - $destination = $device->getPath('hello.txt'); - $this->assertTrue($this->object->copy($path, $destination, $device, 10000000)); // 10 mb chunks - $this->assertTrue($device->exists($destination)); - $this->assertSame('Hello World', (string) $device->read($destination)); - - $this->object->delete($path); - $device->delete($destination); - } - - public function testCopyNonExistentFile(): void - { - $device = new Local(__DIR__ . '/../resources/disk-a'); - - $path = $this->object->getPath('non-existent-file.txt'); - $destination = $device->getPath('hello.txt'); - - $this->expectException(NotFoundException::class); - $this->object->copy($path, $destination, $device); - } -} diff --git a/packages/storage/tests/E2E/S3Test.php b/packages/storage/tests/E2E/S3Test.php deleted file mode 100644 index 8cf17e5b1..000000000 --- a/packages/storage/tests/E2E/S3Test.php +++ /dev/null @@ -1,222 +0,0 @@ -root = '/root'; - $this->bucket = $this->env('S3_BUCKET', 'utopia-storage-test'); - $this->accessKey = $this->env('S3_ACCESS_KEY', 'minioadmin'); - $this->secretKey = $this->env('S3_SECRET', 'minioadmin'); - $this->region = $this->env('S3_REGION', 'us-east-1'); - $this->pathHost = $this->configured('S3_PATH_HOST'); - $this->pathBucket = $this->env('S3_PATH_BUCKET', $this->bucket); - $host = $this->env('S3_HOST', "http://{$this->bucket}.localhost:9805"); - - $this->object = new S3($this->root, $this->accessKey, $this->secretKey, $host, $this->region, Acl::Private, bucket: $this->bucket); - } - - protected function getAdapterType(): DeviceType - { - return $this->object->getType(); - } - - public function testPathStyleEndpointSharesVirtualHostedBucket(): void - { - $pathHost = $this->pathHost; - $virtualHost = $this->configured('S3_HOST'); - if (($pathHost === null) !== ($virtualHost === null)) { - self::markTestSkipped('S3_HOST and S3_PATH_HOST must both be configured when overriding the local MinIO endpoints'); - } - - if ($pathHost === null) { - $pathHost = 'http://localhost:9805'; - } - - $this->assertSame($this->bucket, $this->pathBucket, 'S3_PATH_BUCKET and S3_BUCKET must identify the same bucket for cross-visibility'); - - $path = new S3( - root: '/', - accessKey: $this->accessKey, - secretKey: $this->secretKey, - host: rtrim($pathHost, '/') . '/' . rawurlencode($this->pathBucket) . '/', - region: $this->region, - bucket: $this->pathBucket, - ); - $prefix = 'endpoint-path/' . bin2hex(random_bytes(8)); - $pathObject = $prefix . '/path.txt'; - $virtualObject = $prefix . '/virtual.txt'; - $failure = null; - - try { - $this->assertSame(md5('path-style'), $path->write($pathObject, new Stream('path-style'), 'text/plain')); - $this->assertSame('path-style', (string) $this->object->read($pathObject)); - - $this->assertSame(md5('virtual-hosted'), $this->object->write($virtualObject, new Stream('virtual-hosted'), 'text/plain')); - $this->assertSame('virtual-hosted', (string) $path->read($virtualObject)); - $this->assertSame( - [$pathObject, $virtualObject], - array_map(static fn(FileInfo $file): string => $file->path, $path->listFiles($prefix)->files), - ); - } catch (Throwable $error) { - $failure = $error; - - throw $error; - } finally { - $cleanup = []; - foreach ([[$path, $pathObject], [$this->object, $virtualObject]] as [$device, $object]) { - try { - if (! $device->delete($object)) { - $cleanup[] = "Failed to delete {$object}"; - } - } catch (Throwable $error) { - $cleanup[] = "Failed to delete {$object}: {$error->getMessage()}"; - } - } - - if (!$failure instanceof Throwable && $cleanup !== []) { - self::fail(implode('; ', $cleanup)); - } - } - } - - public function testConditionalWritesHaveOneWinner(): void - { - $path = $this->object->getPath('conditional/' . bin2hex(random_bytes(8)) . '/lock'); - - try { - $first = $this->object->create($path, new Stream('first'), 'text/plain'); - $this->assertSame(md5('first'), $first); - - try { - $this->object->create($path, new Stream('second'), 'text/plain'); - self::fail('A second create must be refused'); - } catch (PreconditionFailedException) { - $this->assertSame('first', (string) $this->object->read($path)); - } - - $second = $this->object->replace($path, new Stream('second'), $first, 'text/plain'); - $this->assertSame(md5('second'), $second); - - try { - $this->object->replace($path, new Stream('third'), $first, 'text/plain'); - self::fail('A replace naming a stale ETag must be refused'); - } catch (PreconditionFailedException) { - $this->assertSame('second', (string) $this->object->read($path)); - } - - $info = $this->object->getFileInfo($path); - $this->assertSame($second, $info->etag); - $this->assertSame(6, $info->size); - $this->assertInstanceOf(\DateTimeImmutable::class, $info->modifiedAt); - - $this->assertSame('sec', (string) $this->object->read($path, 0, 3, $second)); - - $this->expectException(PreconditionFailedException::class); - $this->object->read($path, 0, 3, $first); - } finally { - $this->object->delete($path); - } - } - - public function testMultipartUploadReplacesAnExistingObject(): void - { - $path = $this->object->getPath('replaced/' . bin2hex(random_bytes(8)) . '.bin'); - $part = str_repeat('a', 5 * 1024 * 1024); // the smallest part S3 accepts, except for the last one - - try { - $this->assertSame(md5('old'), $this->object->write($path, new Stream('old'), 'text/plain')); - - // The number of parts is not known up front: nothing finalizes until asked. - $metadata = []; - $this->object->upload(new Stream('tail'), $path, 'application/octet-stream', 2, 0, $metadata); - $this->object->upload(new Stream($part), $path, 'application/octet-stream', 1, 0, $metadata); - $this->assertSame('old', (string) $this->object->read($path), 'nothing changes before finalize'); - - // MinIO only honours a prefix that is a whole key; Amazon S3 takes any prefix. - $uploads = $this->object->listUploads($path); - $this->assertCount(1, $uploads->uploads); - $this->assertSame(ltrim($path, '/'), $uploads->uploads[0]->path); - $this->assertSame($metadata['uploadId'] ?? null, $uploads->uploads[0]->uploadId); - $this->assertNull($uploads->cursor); - - $this->assertTrue($this->object->finalize($path, 2, $metadata)); - $this->assertSame(\strlen($part) + 4, $this->object->getFileSize($path)); - $this->assertSame('tail', (string) $this->object->read($path, \strlen($part))); - $this->assertTrue($this->object->finalize($path, 2, $metadata), 'finalizing again is not an error'); - $this->assertSame([], $this->object->listUploads($path)->uploads); - } finally { - $this->object->delete($path); - } - } - - public function testAbandonedUploadsAreListedAndAborted(): void - { - $path = $this->object->getPath('abandoned/' . bin2hex(random_bytes(8)) . '/a.bin'); - $metadata = []; - - $this->object->prepare($path, 'application/octet-stream', 2, $metadata); - $uploadId = $metadata['uploadId'] ?? ''; - $this->assertNotSame('', $uploadId); - - $list = $this->object->listUploads($path); - $this->assertCount(1, $list->uploads); - $this->assertSame(ltrim($path, '/'), $list->uploads[0]->path); - $this->assertSame($uploadId, $list->uploads[0]->uploadId); - $this->assertInstanceOf(\DateTimeImmutable::class, $list->uploads[0]->initiatedAt); - - $this->assertTrue($this->object->abort($path, $uploadId)); - $this->assertSame([], $this->object->listUploads($path)->uploads); - } - - public function testWritesWithoutAnAcl(): void - { - $device = new S3($this->root, $this->accessKey, $this->secretKey, $this->env('S3_HOST', "http://{$this->bucket}.localhost:9805"), $this->region, null, bucket: $this->bucket); - $path = $device->getPath('no-acl/' . bin2hex(random_bytes(8)) . '.txt'); - - try { - $this->assertSame(md5('no acl'), $device->write($path, new Stream('no acl'), 'text/plain')); - $this->assertSame('no acl', (string) $device->read($path)); - } finally { - $device->delete($path); - } - } -} diff --git a/packages/storage/tests/Storage/Device/LocalTest.php b/packages/storage/tests/Storage/Device/LocalTest.php deleted file mode 100644 index ca5f6be0d..000000000 --- a/packages/storage/tests/Storage/Device/LocalTest.php +++ /dev/null @@ -1,1025 +0,0 @@ - $length - */ - private function readBytes($handle, int $length): string - { - $contents = fread($handle, $length); - if ($contents === false) { - throw new \RuntimeException('Failed to read stream'); - } - - return $contents; - } - - /** - * A stream that hands over one chunk and then fails, standing in for a - * full disk or a connection dropped mid-body. - */ - private function failingStream(): StreamInterface - { - return new class implements StreamInterface { - private bool $sent = false; - - public function read(int $length): string - { - if ($this->sent) { - throw new \DomainException('Stream failed'); - } - - $this->sent = true; - - return 'partial'; - } - - public function eof(): bool - { - return false; - } - - public function isReadable(): bool - { - return true; - } - - public function isSeekable(): bool - { - return false; - } - - public function isWritable(): bool - { - return false; - } - - public function __toString(): string - { - return ''; - } - - public function close(): void {} - - public function detach() - { - return null; - } - - public function getSize(): ?int - { - return null; - } - - public function tell(): int - { - return 0; - } - - public function seek(int $offset, int $whence = SEEK_SET): void {} - - public function rewind(): void {} - - public function write(string $string): int - { - return 0; - } - - public function getContents(): string - { - return ''; - } - - public function getMetadata(?string $key = null): mixed - { - return null; - } - }; - } - - private Local $object; - - protected function setUp(): void - { - $this->object = new Local(realpath(__DIR__ . '/../../resources/disk-a') ?: ''); - } - - protected function tearDown(): void {} - - public function testPaths(): void - { - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('////storage/functions')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('storage/functions')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('/storage/functions')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('//storage///functions//')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('\\\\\storage\functions')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('..\\\\\//storage\\//functions')); - $this->assertSame('/storage/functions', $this->object->getAbsolutePath('./..\\\\\//storage\\//functions')); - } - - public function testType(): void - { - $this->assertSame(DeviceType::Local, $this->object->getType()); - } - - public function testRoot(): void - { - $this->assertSame($this->object->getRoot(), $this->object->getAbsolutePath(__DIR__ . '/../../resources/disk-a')); - } - - public function testPath(): void - { - $this->assertSame($this->object->getPath('image.png'), $this->object->getAbsolutePath(__DIR__ . '/../../resources/disk-a') . '/image.png'); - } - - public function testWrite(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text.txt'), new Stream('Hello World'))); - $this->assertFileExists($this->object->getPath('text.txt')); - $this->assertIsReadable($this->object->getPath('text.txt')); - - $this->object->delete($this->object->getPath('text.txt')); - } - - public function testRead(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-read.txt'), new Stream('Hello World'))); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-read.txt'))); - - $this->object->delete($this->object->getPath('text-for-read.txt')); - } - - public function testWriteRewindsPartiallyConsumedStream(): void - { - $stream = new Stream('Hello World'); - $stream->read(6); // consume a prefix — seekable streams are sent from the beginning - - $path = $this->object->getPath('text-for-rewind.txt'); - $this->assertSame(md5('Hello World'), $this->object->write($path, $stream)); - $this->assertSame('Hello World', (string) $this->object->read($path)); - - $this->object->delete($path); - } - - public function testReadNonExistentFile(): void - { - $this->expectException(NotFoundException::class); - $this->object->read($this->object->getPath('non-existent-file.txt')); - } - - public function testFileExists(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-test-exists.txt'), new Stream('Hello World'))); - $this->assertEquals(true, $this->object->exists($this->object->getPath('text-for-test-exists.txt'))); - $this->assertEquals(false, $this->object->exists($this->object->getPath('text-for-test-doesnt-exist.txt'))); - - $this->object->delete($this->object->getPath('text-for-test-exists.txt')); - } - - public function testMove(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-move.txt'), new Stream('Hello World'))); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-move.txt'))); - $this->assertEquals(true, $this->object->move($this->object->getPath('text-for-move.txt'), $this->object->getPath('text-for-move-new.txt'))); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-move-new.txt'))); - $this->assertFileDoesNotExist($this->object->getPath('text-for-move.txt')); - $this->assertIsNotReadable($this->object->getPath('text-for-move.txt')); - $this->assertFileExists($this->object->getPath('text-for-move-new.txt')); - $this->assertIsReadable($this->object->getPath('text-for-move-new.txt')); - - $this->object->delete($this->object->getPath('text-for-move-new.txt')); - } - - public function testCopyRejectsInvalidChunkSize(): void - { - $device = new Local(realpath(__DIR__ . '/../../resources/disk-b') ?: ''); - - $this->expectExceptionMessage('Chunk size must be greater than zero'); - $this->object->copy($this->object->getPath('kitten-1.jpg'), $device->getPath('kitten-1.jpg'), $device, 0); - } - - public function testListFiles(): void - { - $directory = $this->object->getPath('list-files'); - $this->object->write($directory . '/a.txt', new Stream('aa')); - $this->object->write($directory . '/nested/b.txt', new Stream('bb')); - $this->object->write($directory . '/.hidden', new Stream('hh')); - - $list = $this->object->listFiles($directory, 2); - $this->assertCount(2, $list->files); - $this->assertNotNull($list->cursor); - - $rest = $this->object->listFiles($directory, 10, $list->cursor); - $this->assertCount(1, $rest->files); - $this->assertNull($rest->cursor); - - $paths = array_map(fn(FileInfo $file): string => $file->path, array_merge($list->files, $rest->files)); - $this->assertContains($directory . '/a.txt', $paths); - $this->assertContains($directory . '/nested/b.txt', $paths); - $this->assertContains($directory . '/.hidden', $paths); - $this->assertSame(2, $list->files[1]->size); - - $this->object->delete($directory, true); - } - - public function testStatOnMissingFileThrowsNotFound(): void - { - $this->expectException(NotFoundException::class); - $this->object->getFileSize($this->object->getPath('does-not-exist.txt')); - } - - public function testMoveIdenticalName(): void - { - $file = '/kitten-1.jpg'; - $this->assertFalse($this->object->move($file, $file)); - } - - public function testDelete(): void - { - $this->assertSame(md5('Hello World'), $this->object->write($this->object->getPath('text-for-delete.txt'), new Stream('Hello World'))); - $this->assertSame('Hello World', (string) $this->object->read($this->object->getPath('text-for-delete.txt'))); - $this->assertEquals(true, $this->object->delete($this->object->getPath('text-for-delete.txt'))); - $this->assertFileDoesNotExist($this->object->getPath('text-for-delete.txt')); - $this->assertIsNotReadable($this->object->getPath('text-for-delete.txt')); - } - - public function testRecursiveDeleteRemovesHiddenFiles(): void - { - $directory = $this->object->getPath('delete-hidden'); - - $this->assertTrue($this->object->createDirectory($directory)); - $this->assertSame(md5('secret'), $this->object->write($directory . DIRECTORY_SEPARATOR . '.hidden', new Stream('secret'))); - $this->assertSame(md5('visible'), $this->object->write($directory . DIRECTORY_SEPARATOR . 'visible', new Stream('visible'))); - - $this->assertTrue($this->object->delete($directory, true)); - $this->assertFalse($this->object->exists($directory)); - } - - public function testFileSize(): void - { - $this->assertSame(599639, $this->object->getFileSize(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $this->assertSame(131958, $this->object->getFileSize(__DIR__ . '/../../resources/disk-a/kitten-2.jpg')); - } - - public function testFileMimeType(): void - { - $this->assertSame('image/jpeg', $this->object->getFileMimeType(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $this->assertSame('image/jpeg', $this->object->getFileMimeType(__DIR__ . '/../../resources/disk-a/kitten-2.jpg')); - $this->assertSame('image/png', $this->object->getFileMimeType(__DIR__ . '/../../resources/disk-b/kitten-1.png')); - $this->assertSame('image/png', $this->object->getFileMimeType(__DIR__ . '/../../resources/disk-b/kitten-2.png')); - } - - public function testFileHash(): void - { - $this->assertSame('7551f343143d2e24ab4aaf4624996b6a', $this->object->getFileHash(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $this->assertSame('81702fdeef2e55b1a22617bce4951cb5', $this->object->getFileHash(__DIR__ . '/../../resources/disk-a/kitten-2.jpg')); - $this->assertSame('03010f4f02980521a8fd6213b52ec313', $this->object->getFileHash(__DIR__ . '/../../resources/disk-b/kitten-1.png')); - $this->assertSame('8a9ed992b77e4b62b10e3a5c8ed72062', $this->object->getFileHash(__DIR__ . '/../../resources/disk-b/kitten-2.png')); - } - - public function testDirectoryCreate(): void - { - $directory = uniqid(); - $this->assertTrue($this->object->createDirectory(__DIR__ . "/$directory")); - $this->assertTrue($this->object->exists(__DIR__ . "/$directory")); - } - - public function testDirectorySize(): void - { - $this->assertGreaterThan(0, $this->object->getDirectorySize(__DIR__ . '/../../resources/disk-a/')); - $this->assertGreaterThan(0, $this->object->getDirectorySize(__DIR__ . '/../../resources/disk-b/')); - - // Paths without a trailing separator must measure the same tree. - $this->assertSame( - $this->object->getDirectorySize(__DIR__ . '/../../resources/disk-a/'), - $this->object->getDirectorySize(__DIR__ . '/../../resources/disk-a'), - ); - - // An empty path is an error, not the filesystem root. - $this->assertSame(-1, $this->object->getDirectorySize('')); - } - - /** Without a started multipart upload there is nothing to reclaim — aborting could delete a pre-existing destination. */ - public function testFailedCopyDoesNotAbortOrDeleteExistingDestination(): void - { - $source = $this->object->getPath(uniqid() . '.txt'); - $this->object->write($source, new Stream(str_repeat('a', 30)), 'text/plain'); - - $device = new class (sys_get_temp_dir()) extends Local { - public int $aborts = 0; - - #[\Override] - public function upload(StreamInterface $data, string $path, string $contentType, int $chunk = 1, int $chunks = 1, array &$metadata = []): int - { - if ($chunk === 2) { - throw new UploadException('Injected chunk failure'); - } - - return parent::upload($data, $path, $contentType, $chunk, $chunks, $metadata); - } - - #[\Override] - public function abort(string $path, string $uploadId = ''): bool - { - ++$this->aborts; - - return parent::abort($path, $uploadId); - } - }; - - $destination = $device->getPath(uniqid() . '-dest.txt'); - $device->write($destination, new Stream('pre-existing'), 'text/plain'); - - try { - $this->object->copy($source, $destination, $device, 10); - self::fail('Expected the injected chunk failure to surface'); - } catch (UploadException $e) { - $this->assertSame('Injected chunk failure', $e->getMessage()); - } finally { - $this->object->delete($source); - } - - $this->assertSame(0, $device->aborts); - $this->assertSame('pre-existing', (string) $device->read($destination)); - $device->delete($destination); - } - - public function testPartUpload(): string - { - $source = __DIR__ . '/../../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('uploaded.mp4'); - $totalSize = $this->object->getFileSize($source); - $chunkSize = 2097152; - - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, '', $chunk, $chunks); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - $this->assertEquals(filesize($source), $this->object->getFileSize($dest)); - $this->assertEquals(md5_file($source), $this->object->getFileHash($dest)); - - return $dest; - } - - public function testUploadDoesNotFinalizeUntilLastChunk(): void - { - $dest = $this->object->getPath('chunked-phase-upload.txt'); - $metadata = []; - - $this->object->upload(new Stream('bbb'), $dest, '', 2, 3, $metadata); - $this->assertFalse($this->object->exists($dest)); - $this->object->upload(new Stream('aaa'), $dest, '', 1, 3, $metadata); - $this->assertFalse($this->object->exists($dest)); - - $this->assertSame(3, $this->object->upload(new Stream('ccc'), $dest, '', 3, 3, $metadata)); - $this->assertSame('aaabbbccc', (string) $this->object->read($dest)); - // Finalizing an already assembled upload is idempotent. - $this->assertTrue($this->object->finalize($dest, 3, $metadata)); - - $this->object->delete($dest); - } - - public function testFinalizeRequiresAllLocalChunks(): void - { - $dest = $this->object->getPath('chunked-phase-missing.txt'); - $metadata = []; - - $this->object->upload(new Stream('aaa'), $dest, '', 1, 2, $metadata); - - try { - $this->object->finalize($dest, 2, $metadata); - $this->fail('Expected missing chunk exception'); - } catch (UploadException $e) { - $this->assertSame('Missing chunk 2', $e->getMessage()); - } finally { - $this->object->abort($dest); - } - } - - public function testPartUploadRetry(): string - { - $source = __DIR__ . '/../../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('uploaded2.mp4'); - $totalSize = filesize($source); - // AWS S3 requires each part to be at least 5MB except for last part - $chunkSize = 5 * 1024 * 1024; - - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, '', $chunk, $chunks); - $start += \strlen($contents); - ++$chunk; - break; - } - fclose($handle); - - $chunk = 1; - $start = 0; - // retry from first to make sure duplicate chunk re-upload works without issue - $handle = $this->openStream($source); - while ($start < $totalSize) { - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, '', $chunk, $chunks); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - - $this->assertEquals(filesize($source), $this->object->getFileSize($dest)); - $this->assertEquals(md5_file($source), $this->object->getFileHash($dest)); - - return $dest; - } - - public function testAbort(): void - { - $source = __DIR__ . '/../../resources/disk-a/large_file.mp4'; - $dest = $this->object->getPath('abcduploaded.mp4'); - $totalSize = $this->object->getFileSize($source); - $chunkSize = 2097152; - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - - $handle = $this->openStream($source); - while ($chunk < 3) { // only upload two chunks - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest, '', $chunk, $chunks); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - - // using file name with same first four chars - $source = __DIR__ . '/../../resources/disk-a/large_file.mp4'; - $dest1 = $this->object->getPath('abcduploaded2.mp4'); - $totalSize = $this->object->getFileSize($source); - $chunkSize = 2097152; - $chunks = (int) ceil($totalSize / $chunkSize); - - $chunk = 1; - $start = 0; - - $handle = $this->openStream($source); - while ($chunk < 3) { // only upload two chunks - $contents = $this->readBytes($handle, $chunkSize); - $this->object->upload(new Stream($contents), $dest1, '', $chunk, $chunks); - $start += \strlen($contents); - ++$chunk; - fseek($handle, $start); - } - fclose($handle); - - $this->assertTrue($this->object->abort($dest)); - $this->assertTrue($this->object->abort($dest1)); - } - - #[Depends('testPartUpload')] - public function testPartRead(string $path): void - { - $source = __DIR__ . '/../../resources/disk-a/large_file.mp4'; - $chunk = file_get_contents($source, false, null, 0, 500); - $readChunk = (string) $this->object->read($path, 0, 500); - $this->assertEquals($chunk, $readChunk); - } - - public function testPartitionFreeSpace(): void - { - $this->assertGreaterThan(0, $this->object->getPartitionFreeSpace()); - } - - public function testPartitionTotalSpace(): void - { - $this->assertGreaterThan(0, $this->object->getPartitionTotalSpace()); - } - - #[Depends('testPartUpload')] - public function testCopyLarge(string $path): void - { - // chunked file - $device = new Local(realpath(__DIR__ . '/../../resources/disk-b') ?: ''); - $destination = $device->getPath('largefile.mp4'); - - $this->assertTrue($this->object->copy($path, $destination, $device, 10000000)); // 10 mb chunks - $this->assertTrue($device->exists($destination)); - $this->assertSame('video/mp4', $device->getFileMimeType($destination)); - - $device->delete($destination); - $this->object->delete($path); - } - - public function testCopySmall(): void - { - $device = new Local(realpath(__DIR__ . '/../../resources/disk-b') ?: ''); - - $path = $this->object->getPath('text-for-read.txt'); - $this->object->write($path, new Stream('Hello World')); - - $destination = $device->getPath('hello.txt'); - $this->assertTrue($this->object->copy($path, $destination, $device, 10000000)); // 10 mb chunks - $this->assertTrue($device->exists($destination)); - $this->assertSame('Hello World', (string) $device->read($destination)); - - $this->object->delete($path); - $device->delete($destination); - } - - public function testDeletePath(): void - { - // Test Single Object - $path = $this->object->getPath('text-for-delete-path.txt'); - $path = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path); - $this->assertSame(md5('Hello World'), $this->object->write($path, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path)); - $this->assertEquals(true, $this->object->deletePath('bucket')); - $this->assertEquals(false, $this->object->exists($path)); - - // Test Multiple Objects - $path = $this->object->getPath('text-for-delete-path1.txt'); - $path = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path); - $this->assertSame(md5('Hello World'), $this->object->write($path, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path)); - - $path2 = $this->object->getPath('text-for-delete-path2.txt'); - $path2 = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path2); - $this->assertSame(md5('Hello World'), $this->object->write($path2, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path2)); - - $path3 = $this->object->getPath('.hidden.txt'); - $path3 = str_ireplace($this->object->getRoot(), $this->object->getRoot() . DIRECTORY_SEPARATOR . 'bucket', $path3); - $this->assertSame(md5('Hello World'), $this->object->write($path3, new Stream('Hello World'), 'text/plain')); - $this->assertEquals(true, $this->object->exists($path3)); - - $this->assertEquals(true, $this->object->deletePath('bucket/')); - $this->assertEquals(false, $this->object->exists($path)); - $this->assertEquals(false, $this->object->exists($path2)); - $this->assertEquals(false, $this->object->exists($path3)); - } - - public function testListFilesEmptyAndGrowingDirectory(): void - { - $dir = $this->object->getPath('get-files-test'); - - $this->assertTrue($this->object->createDirectory($dir)); - - $this->assertCount(0, $this->object->listFiles($dir)->files); - - $this->object->write($dir . DIRECTORY_SEPARATOR . 'new-file.txt', new Stream('Hello World')); - $this->object->write($dir . DIRECTORY_SEPARATOR . 'new-file-two.txt', new Stream('Hello World')); - - $this->assertCount(2, $this->object->listFiles($dir)->files); - - $this->assertTrue($this->object->deletePath('get-files-test')); - } - - public function testNestedDeletePath(): void - { - $dir = $this->object->getPath('nested-delete-path-test'); - $dir2 = $dir . DIRECTORY_SEPARATOR . 'dir2'; - $dir3 = $dir2 . DIRECTORY_SEPARATOR . 'dir3'; - - $this->assertTrue($this->object->createDirectory($dir)); - $this->object->write($dir . DIRECTORY_SEPARATOR . 'new-file.txt', new Stream('Hello World')); - $this->assertTrue($this->object->createDirectory($dir2)); - $this->object->write($dir2 . DIRECTORY_SEPARATOR . 'new-file-2.txt', new Stream('Hello World')); - $this->assertTrue($this->object->createDirectory($dir3)); - $this->object->write($dir3 . DIRECTORY_SEPARATOR . 'new-file-3.txt', new Stream('Hello World')); - - $this->assertTrue($this->object->deletePath('nested-delete-path-test')); - $this->assertFalse($this->object->exists($dir)); - } - - // ------------------------------------------------------------------------- - // joinChunks tests - // ------------------------------------------------------------------------- - - /** - * Create a self-contained Local storage instance in a fresh temp directory. - * The caller is responsible for deleting the root after the test. - */ - private function makeJoinTestStorage(): Local - { - $dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'utopia-join-test-' . uniqid(); - mkdir($dir, 0755, true); - - return new Local($dir); - } - - public function testJoinChunksAssemblesContentCorrectly(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'test.dat'; - - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - - $this->assertFileExists($dest); - $this->assertSame('AAAABBBBCCCC', file_get_contents($dest)); - - $storage->delete($storage->getRoot(), true); - } - - public function testJoinChunksCleansUpTempFilesOnSuccess(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'test.dat'; - $tmpDir = $storage->getRoot() . DIRECTORY_SEPARATOR . 'tmp_test.dat'; - $tmpAssemble = $storage->getRoot() . DIRECTORY_SEPARATOR . 'tmp_assemble_test.dat'; - - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - - $this->assertDirectoryDoesNotExist($tmpDir, 'Temp chunk directory should be removed after assembly'); - $this->assertFileDoesNotExist($tmpAssemble, 'Temp assembly file should be removed after rename'); - for ($i = 1; $i <= 3; ++$i) { - $this->assertFileDoesNotExist( - $tmpDir . DIRECTORY_SEPARATOR . 'test.part.' . $i, - "Part file $i should be removed after assembly", - ); - } - - $storage->delete($storage->getRoot(), true); - } - - public function testJoinChunksMissingPartDoesNotFinalize(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'test.dat'; - $tmpDir = $storage->getRoot() . DIRECTORY_SEPARATOR . 'tmp_test.dat'; - $tmpAssemble = $storage->getRoot() . DIRECTORY_SEPARATOR . 'tmp_assemble_test.dat'; - - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - - // Simulate a missing/corrupted chunk by deleting part 1 before the - // final upload triggers assembly. - unlink($tmpDir . DIRECTORY_SEPARATOR . 'test.part.1'); - - // Uploading the final chunk should NOT throw or finalize, - // because part 1 is missing and the part-file count is only 2. - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - - $this->assertFileDoesNotExist($dest, 'Final file must not be created when a chunk is missing'); - $this->assertFileDoesNotExist($tmpAssemble, 'Temp assembly file must not be created'); - // Surviving parts must remain so the upload can be retried. - $this->assertFileExists( - $tmpDir . DIRECTORY_SEPARATOR . 'test.part.2', - 'Part 2 must be preserved for retry', - ); - $this->assertFileExists( - $tmpDir . DIRECTORY_SEPARATOR . 'test.part.3', - 'Part 3 must be preserved for retry', - ); - - // Re-upload the missing chunk — assembly should now succeed. - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $this->assertFileExists($dest, 'Final file should be created after missing chunk is re-uploaded'); - $this->assertSame('AAAABBBBCCCC', file_get_contents($dest), 'Re-uploaded chunk must allow correct assembly'); - - $storage->delete($storage->getRoot(), true); - } - - public function testJoinChunksStaleAssemblyFileIsOverwritten(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'test.dat'; - - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - - // Simulate a stale assembly file left by a previously crashed attempt. - // With unique temp paths (tempnam), stale files at old hardcoded paths - // are naturally bypassed rather than overwritten. - $staleFile = $storage->getRoot() . DIRECTORY_SEPARATOR . 'tmp_assemble_test.dat'; - file_put_contents($staleFile, 'STALE_GARBAGE_DATA'); - - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - - $this->assertFileExists($dest); - $this->assertSame('AAAABBBBCCCC', file_get_contents($dest), 'Stale assembly file must not corrupt output'); - - $storage->delete($storage->getRoot(), true); - } - - public function testOutOfOrderUpload(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'out-of-order.dat'; - - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - $this->assertFileDoesNotExist($dest, 'File should not be assembled after chunk 3'); - - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - $this->assertFileDoesNotExist($dest, 'File should not be assembled after chunk 1'); - - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - $this->assertFileExists($dest, 'File should be assembled after final chunk'); - $this->assertSame('AAAABBBBCCCC', file_get_contents($dest), 'Chunks must be assembled in correct order'); - - $storage->delete($storage->getRoot(), true); - } - - public function testOutOfOrderUploadWithRetry(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'out-of-order-retry.dat'; - - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 3); - - // Re-upload chunk 2 (duplicate) — should be silently ignored - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 3); - $this->assertFileDoesNotExist($dest, 'File should not be assembled after duplicate retry'); - - $storage->upload(new Stream('CCCC'), $dest, 'application/octet-stream', 3, 3); - $this->assertFileExists($dest, 'File should be assembled after final chunk'); - $this->assertSame('AAAABBBBCCCC', file_get_contents($dest), 'Duplicate retry must not corrupt final file'); - - $storage->delete($storage->getRoot(), true); - } - - public function testParallelChunkUpload(): void - { - $storage = $this->makeJoinTestStorage(); - $dest = $storage->getRoot() . DIRECTORY_SEPARATOR . 'parallel.dat'; - - // Upload chunk 1 (creates temp directory) - $storage->upload(new Stream('AAAA'), $dest, 'application/octet-stream', 1, 2); - - // Upload chunk 2 (assembles the file) - $storage->upload(new Stream('BBBB'), $dest, 'application/octet-stream', 2, 2); - - // Verify file exists and is correct - $this->assertFileExists($dest); - $this->assertSame('AAAABBBB', file_get_contents($dest)); - - // Simulate the race where another request already assembled the file - // by calling joinChunks directly when the file already exists - $reflection = new \ReflectionClass($storage); - $method = $reflection->getMethod('joinChunks'); - - try { - $method->invoke($storage, $dest, 2); - } catch (\Exception $e) { - $this->fail('Duplicate assembly should not throw: ' . $e->getMessage()); - } - - $this->assertFileExists($dest, 'File should still exist after duplicate assembly attempt'); - $this->assertSame('AAAABBBB', file_get_contents($dest), 'File content must not be corrupted'); - - $storage->delete($storage->getRoot(), true); - } - - public function testFileInfoReportsSizeModificationAndHash(): void - { - $path = $this->object->getPath('info.txt'); - $this->object->write($path, new Stream('Hello World'), 'text/plain'); - - $info = $this->object->getFileInfo($path); - - $this->assertSame($path, $info->path); - $this->assertSame(11, $info->size); - $this->assertSame(md5('Hello World'), $info->etag); - $this->assertEqualsWithDelta(time(), $info->modifiedAt?->getTimestamp() ?? 0, 5); - - $this->object->delete($path); - } - - public function testFileInfoOfAMissingFileThrowsNotFound(): void - { - $this->expectException(NotFoundException::class); - $this->object->getFileInfo($this->object->getPath('missing.txt')); - } - - public function testCreateWritesOnlyWhereNothingIs(): void - { - $path = $this->object->getPath('created.txt'); - - $this->assertSame(md5('first'), $this->object->create($path, new Stream('first'), 'text/plain')); - $this->assertSame('first', file_get_contents($path)); - - try { - $this->object->create($path, new Stream('second'), 'text/plain'); - self::fail('Expected precondition failure'); - } catch (PreconditionFailedException) { - $this->assertSame('first', file_get_contents($path), 'the file is left alone'); - } - - $this->object->delete($path); - } - - public function testReplaceWritesOverTheNamedVersionOnly(): void - { - $path = $this->object->getPath('replaced.txt'); - $etag = $this->object->create($path, new Stream('first'), 'text/plain'); - - $this->assertSame(md5('second'), $this->object->replace($path, new Stream('second'), $etag, 'text/plain')); - $this->assertSame('second', file_get_contents($path)); - - try { - $this->object->replace($path, new Stream('third'), $etag, 'text/plain'); - self::fail('Expected precondition failure'); - } catch (PreconditionFailedException) { - $this->assertSame('second', file_get_contents($path), 'a stale ETag changes nothing'); - } - - $this->object->delete($path); - - $this->expectException(PreconditionFailedException::class); - $this->object->replace($path, new Stream('third'), md5('second'), 'text/plain'); - } - - public function testReadWithEtagRefusesAReplacedFile(): void - { - $path = $this->object->getPath('conditional.txt'); - $etag = $this->object->create($path, new Stream('Hello World'), 'text/plain'); - - $this->assertSame('World', (string) $this->object->read($path, 6, 5, $etag)); - - $this->object->write($path, new Stream('Goodbye World'), 'text/plain'); - - try { - $this->expectException(PreconditionFailedException::class); - $this->object->read($path, 6, 5, $etag); - } finally { - $this->object->delete($path); - } - } - - public function testASingleChunkOfAnUploadWithUnknownCountIsJoined(): void - { - $path = $this->object->getPath('single-chunk.txt'); - $this->object->write($path, new Stream('old contents'), 'text/plain'); - - $metadata = []; - $this->object->upload(new Stream('new contents'), $path, 'text/plain', 1, 0, $metadata); - $this->assertSame('old contents', file_get_contents($path), 'a chunk of an upload with unknown count is not the file yet'); - - $this->assertTrue($this->object->finalize($path, 1, $metadata)); - $this->assertSame('new contents', file_get_contents($path)); - $this->assertTrue($this->object->finalize($path, 1, $metadata), 'finalizing again is not an error'); - - $this->object->delete($path); - } - - public function testFinalizeReplacesAnExistingFile(): void - { - $path = $this->object->getPath('replaced-by-upload.txt'); - $this->object->write($path, new Stream('old contents'), 'text/plain'); - - $metadata = []; - $this->object->upload(new Stream('new '), $path, 'text/plain', 1, 0, $metadata); - $this->object->upload(new Stream('contents'), $path, 'text/plain', 2, 0, $metadata); - $this->assertSame('old contents', file_get_contents($path), 'nothing changes before finalize'); - - $this->assertTrue($this->object->finalize($path, 2, $metadata)); - $this->assertSame('new contents', file_get_contents($path)); - $this->assertTrue($this->object->finalize($path, 2, $metadata), 'finalizing again is not an error'); - - $this->object->delete($path); - } - - public function testFinalizeWithAMissingChunkDoesNotClaimAnExistingFile(): void - { - $path = $this->object->getPath('incomplete.txt'); - $this->object->write($path, new Stream('old contents'), 'text/plain'); - - $metadata = []; - $this->object->upload(new Stream('new '), $path, 'text/plain', 1, 3, $metadata); - $this->object->upload(new Stream('!'), $path, 'text/plain', 3, 3, $metadata); - - try { - $this->object->finalize($path, 3, $metadata); - self::fail('Expected the missing chunk to be reported'); - } catch (UploadException) { - $this->assertSame('old contents', file_get_contents($path), 'a file in the way is not this upload'); - } - - $this->object->abort($path); - } - - public function testAStalePartDoesNotHijackAWholeFileUpload(): void - { - $path = $this->object->getPath('hijacked.txt'); - - $abandoned = []; - $this->object->upload(new Stream('abandoned chunk'), $path, 'text/plain', 1, 0, $abandoned); - - $metadata = []; - $this->object->upload(new Stream('whole file'), $path, 'text/plain', 1, 1, $metadata); - - $this->assertTrue($this->object->finalize($path, 1, $metadata)); - $this->assertSame('whole file', file_get_contents($path), 'another upload\'s leftovers are not this file'); - - $this->object->abort($path); - } - - public function testAFailedCreateGivesThePathBack(): void - { - $path = $this->object->getPath('failed-create.txt'); - - try { - $this->object->create($path, $this->failingStream(), 'text/plain'); - self::fail('Expected the write to fail'); - } catch (\DomainException) { - $this->assertFileDoesNotExist($path, 'a path claimed but never written stays free'); - } - - $this->assertSame(md5('taken'), $this->object->create($path, new Stream('taken'), 'text/plain')); - - $this->object->delete($path); - } - - public function testAFailedReplaceLeavesThePreviousVersionInPlace(): void - { - $path = $this->object->getPath('failed-replace.txt'); - $etag = $this->object->create($path, new Stream('first'), 'text/plain'); - - try { - $this->object->replace($path, $this->failingStream(), $etag, 'text/plain'); - self::fail('Expected the write to fail'); - } catch (\DomainException) { - $this->assertSame('first', file_get_contents($path)); - $this->assertSame($etag, $this->object->getFileInfo($path)->etag); - } - - $this->assertSame([], glob(\dirname($path) . DIRECTORY_SEPARATOR . 'tmp_write_*') ?: [], 'the half-written file is cleaned up'); - - $this->object->delete($path); - } - - public function testAReplacementDoesNotDisturbAReaderAlreadyStreaming(): void - { - $path = $this->object->getPath('atomic.txt'); - $etag = $this->object->create($path, new Stream('first version'), 'text/plain'); - - $stream = $this->object->read($path, 0, null, $etag); - $this->object->replace($path, new Stream('second'), $etag, 'text/plain'); - - $this->assertSame('first version', (string) $stream, 'the reader keeps the file whose ETag it checked'); - $this->assertSame('second', file_get_contents($path)); - - $this->object->delete($path); - } - - public function testAReplacedFileKeepsReadablePermissions(): void - { - $path = $this->object->getPath('permissions.txt'); - $etag = $this->object->create($path, new Stream('first'), 'text/plain'); - $this->object->replace($path, new Stream('second'), $etag, 'text/plain'); - - $this->assertSame(0644 & ~umask(), fileperms($path) & 0777); - - $this->object->delete($path); - } -} diff --git a/packages/storage/tests/Storage/Device/S3/ContentLengthTest.php b/packages/storage/tests/Storage/Device/S3/ContentLengthTest.php deleted file mode 100644 index 5fe630d8b..000000000 --- a/packages/storage/tests/Storage/Device/S3/ContentLengthTest.php +++ /dev/null @@ -1,97 +0,0 @@ -lastRequest = $request; - - return $this->response; - } - - #[\Override] - public function stream(RequestInterface $request, callable $sink): ResponseInterface - { - $this->lastRequest = $request; - - return $this->response; - } -} - -/** - * Regression coverage for the HTTP 411 fix: every S3 request must carry an - * explicit Content-Length so the transport never falls back to chunked - * transfer encoding (which GCS and other S3-compatible services reject). - */ -final class ContentLengthTest extends TestCase -{ - /** - * @return array{S3, CapturingClient} - */ - private function device(ResponseInterface $response): array - { - $client = new CapturingClient($response); - $device = new S3( - root: 'bucket-root', - accessKey: 'access-key', - secretKey: 'secret-key', - host: 'https://s3.example.com', - region: 'us-east-1', - client: $client, - ); - - return [$device, $client]; - } - - /** A streamed body must send its exact byte length, never chunked. */ - public function testStreamedWriteSendsExactContentLength(): void - { - [$device, $client] = $this->device(new Response(200)->withHeader('etag', '"abc"')); - - $payload = 'hello world'; // 11 bytes - $device->write('file.txt', new Stream($payload), 'text/plain'); - - $this->assertInstanceOf(RequestInterface::class, $client->lastRequest); - $this->assertSame( - (string) \strlen($payload), - $client->lastRequest->getHeaderLine('content-length'), - ); - } - - /** An empty-body POST (multipart initiation) must send Content-Length: 0. */ - public function testEmptyBodyMultipartPostSendsZeroContentLength(): void - { - $xml = 'test-upload-id'; - [$device, $client] = $this->device(new Response(200, body: new Stream($xml))); - - // A multi-chunk prepare() initiates a multipart upload, whose POST - // carries no body — this is the empty-body request GCS rejected with 411. - $metadata = []; - $device->prepare('file.txt', 'text/plain', 2, $metadata); - - $this->assertSame('test-upload-id', $metadata['uploadId'] ?? null); - $this->assertInstanceOf(RequestInterface::class, $client->lastRequest); - $this->assertSame('0', $client->lastRequest->getHeaderLine('content-length')); - } -} diff --git a/packages/storage/tests/Storage/Device/S3/RetryStrategyTest.php b/packages/storage/tests/Storage/Device/S3/RetryStrategyTest.php deleted file mode 100644 index 3bd0ef2a7..000000000 --- a/packages/storage/tests/Storage/Device/S3/RetryStrategyTest.php +++ /dev/null @@ -1,97 +0,0 @@ -SlowDownPlease reduce your request rate.'; - $strategy = new RetryStrategy(delay: 0.5, randomizer: static fn(): float => 1.0); - - $this->assertEqualsWithDelta(0.5, $strategy->delay($this->request(), 1, $this->response(503, $body), null), PHP_FLOAT_EPSILON); - } - - /** The backoff window doubles per attempt (full jitter draws uniformly inside it) and is capped by maxDelay. */ - public function testBackoffWindowGrowsExponentiallyWithJitter(): void - { - $strategy = new RetryStrategy(retries: 4, delay: 0.5, maxDelay: 1.5, randomizer: static fn(): float => 1.0); - $response = $this->response(503); - - $this->assertEqualsWithDelta(0.5, $strategy->delay($this->request(), 1, $response, null), PHP_FLOAT_EPSILON); - $this->assertEqualsWithDelta(1.0, $strategy->delay($this->request(), 2, $response, null), PHP_FLOAT_EPSILON); - $this->assertEqualsWithDelta(1.5, $strategy->delay($this->request(), 3, $response, null), PHP_FLOAT_EPSILON); - - $jittered = new RetryStrategy(delay: 0.5, randomizer: static fn(): float => 0.5); - $this->assertEqualsWithDelta(0.25, $jittered->delay($this->request(), 1, $response, null), PHP_FLOAT_EPSILON); - } - - public function testNonTransientXmlErrorIsNotRetried(): void - { - $body = 'NoSuchKeyThe specified key does not exist.'; - - $this->assertNull(new RetryStrategy()->delay($this->request(), 1, $this->response(404, $body), null)); - } - - public function testStatusFallbackIsTransient(): void - { - $strategy = new RetryStrategy(); - - $this->assertNotNull($strategy->delay($this->request(), 1, $this->response(429), null)); - $this->assertNotNull($strategy->delay($this->request(), 1, $this->response(503), null)); - } - - /** XML error code takes precedence over HTTP status — 503 with non-transient XML must not be retried. */ - public function test503WithNonTransientXmlIsNotRetried(): void - { - $body = 'InternalErrorInternal server error.'; - - $this->assertNull(new RetryStrategy()->delay($this->request(), 1, $this->response(503, $body), null)); - } - - public function testRetriesAreCapped(): void - { - $strategy = new RetryStrategy(retries: 2); - $response = $this->response(503); - - $this->assertNotNull($strategy->delay($this->request(), 1, $response, null)); - $this->assertNotNull($strategy->delay($this->request(), 2, $response, null)); - $this->assertNull($strategy->delay($this->request(), 3, $response, null)); - } - - public function testTransportErrorsAreNotRetried(): void - { - $error = new NetworkException($this->request(), 'Connection reset'); - - $this->assertNull(new RetryStrategy()->delay($this->request(), 1, null, $error)); - } - - public function testReadingTheBodyLeavesItReadable(): void - { - $body = 'SlowDown'; - $response = $this->response(503, $body); - - $this->assertNotNull(new RetryStrategy()->delay($this->request(), 1, $response, null)); - $this->assertSame($body, (string) $response->getBody()); - } -} diff --git a/packages/storage/tests/Storage/Device/S3Test.php b/packages/storage/tests/Storage/Device/S3Test.php deleted file mode 100644 index e98c8e7c4..000000000 --- a/packages/storage/tests/Storage/Device/S3Test.php +++ /dev/null @@ -1,860 +0,0 @@ - - */ - public array $calls = []; - - public string $completedBody = ''; - - /** - * @var array> - */ - public array $headersByOperation = []; - - public ?int $failPart = null; - - public bool $objectExists = false; - - public string $infoContentLength = '1'; - - /** - * @var array>> - */ - public array $amzHeadersByOperation = []; - - #[\Override] - protected function call(string $method, string $uri, StreamInterface|string $data = '', array $parameters = [], array $headers = [], array $amzHeaders = [], bool $decode = true, ?callable $sink = null): S3Response - { - $operation = match (true) { - $method === 'HEAD' => 's3:info', - $method === 'POST' && \array_key_exists('uploads', $parameters) => 's3:createMultipartUpload', - $method === 'PUT' && isset($parameters['partNumber'], $amzHeaders['x-amz-copy-source']) => 's3:uploadPartCopy', - $method === 'PUT' && isset($amzHeaders['x-amz-copy-source']) => 's3:copyObject', - $method === 'PUT' && isset($parameters['partNumber']) => 's3:uploadPart', - $method === 'POST' && isset($parameters['uploadId']) => 's3:completeMultipartUpload', - $method === 'DELETE' && isset($parameters['uploadId']) => 's3:abort', - $method === 'GET' && \array_key_exists('uploads', $parameters) => 's3:listUploads', - $method === 'PUT' => 's3:write', - default => 's3:' . strtolower($method), - }; - $this->calls[] = $operation; - $this->headersByOperation[$operation] = $headers; - $this->amzHeadersByOperation[$operation][] = $amzHeaders; - - if ($operation === 's3:info') { - if (! $this->objectExists) { - throw new NotFoundException('Not found'); - } - - return new S3Response(code: 200, headers: ['content-length' => $this->infoContentLength], body: ''); - } - - if ($operation === 's3:copyObject') { - return new S3Response(code: 200, headers: [], body: ['ETag' => '"etag-copy"']); - } - - if ($operation === 's3:uploadPartCopy') { - return new S3Response(code: 200, headers: [], body: ['ETag' => '"etag-' . $parameters['partNumber'] . '"']); - } - - if ($operation === 's3:createMultipartUpload') { - return new S3Response(code: 200, headers: [], body: ['UploadId' => 'upload-123']); - } - - if ($operation === 's3:uploadPart') { - if ($this->failPart === $parameters['partNumber']) { - throw new RemoteException('Injected part failure'); - } - - return new S3Response(code: 200, headers: ['etag' => 'etag-' . $parameters['partNumber']], body: ''); - } - - if ($operation === 's3:completeMultipartUpload') { - if ($this->completedBody !== '') { - throw new NotFoundException('The specified multipart upload does not exist.', 404); - } - - $this->completedBody = (string) $data; - $this->objectExists = true; - - return new S3Response(code: 200, headers: [], body: ''); - } - - if ($operation === 's3:write') { - $this->objectExists = true; - - return new S3Response(code: 200, headers: ['etag' => '"etag-write"'], body: ''); - } - - return new S3Response(code: 200, headers: [], body: ''); - } -} - -/** - * Client stub that replays scripted responses and records every request. - * Implements the full utopia-php/client Adapter so the Retry decorator can wrap it. - */ -final class ScriptedClient implements Adapter -{ - /** - * @var array - */ - public array $requests = []; - - /** - * @param array $responses - */ - public function __construct(private array $responses) {} - - public function sendRequest(RequestInterface $request): ResponseInterface - { - $this->requests[] = $request; - $response = array_shift($this->responses); - if ($response instanceof ClientExceptionInterface) { - throw $response; - } - if (! $response instanceof ResponseInterface) { - throw new \RuntimeException('No scripted response left for ' . $request->getMethod() . ' ' . $request->getUri()); - } - - return $response; - } - - public function stream(RequestInterface $request, callable $sink): ResponseInterface - { - $response = $this->sendRequest($request); - $sink((string) $response->getBody()); - - return $response; - } - - public function withTimeout(float $seconds): static - { - return $this; - } - - public function withConnectTimeout(float $seconds): static - { - return $this; - } - - public function withSslVerification(bool $enabled = true): static - { - return $this; - } - - public function withCustomCA(string $path): static - { - return $this; - } - - public function withCertificate(string $certPath, string $keyPath, ?string $passphrase = null): static - { - return $this; - } - - public function withMinTlsVersion(Tls $version): static - { - return $this; - } - - public function withConnectionReuse(bool $enabled = true): static - { - return $this; - } - - public function withFollowRedirects(bool $enabled = true): static - { - return $this; - } -} - -final class S3Test extends TestCase -{ - private TestableS3 $s3; - - protected function setUp(): void - { - $this->s3 = new TestableS3( - root: '/root', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'https://s3.example.com', - region: 'us-east-1', - ); - } - - public function testPrepareCreatesMultipartMetadata(): void - { - $metadata = []; - - $this->s3->prepare('/root/file.txt', 'text/plain', 2, $metadata); - - $this->assertSame('upload-123', $metadata['uploadId'] ?? null); - $this->assertSame([], $metadata['parts'] ?? null); - $this->assertSame(0, $metadata['chunks'] ?? null); - $this->assertSame(['s3:createMultipartUpload'], $this->s3->calls); - } - - public function testUploadRecordsPartWithoutCompleting(): void - { - $metadata = []; - - $chunks = $this->s3->upload(new Stream('aaa'), '/root/file.txt', 'text/plain', 1, 2, $metadata); - - $this->assertSame(1, $chunks); - $this->assertSame('etag-1', ($metadata['parts'] ?? [])[1] ?? null); - $this->assertNotContains('s3:completeMultipartUpload', $this->s3->calls); - } - - public function testSingleChunkUploadDoesNotFinalizeOrCheckExists(): void - { - $metadata = []; - - $this->assertSame(1, $this->s3->upload(new Stream('aaa'), '/root/file.txt', 'text/plain', 1, 1, $metadata)); - $this->assertSame(['s3:write'], $this->s3->calls); - $this->assertSame([1 => true], $metadata['parts'] ?? null); - $this->assertSame(1, $metadata['chunks'] ?? null); - } - - public function testFinalizeRequiresAllS3Parts(): void - { - $metadata = [ - 'uploadId' => 'upload-123', - 'parts' => [1 => 'etag-1'], - 'chunks' => 1, - ]; - - $this->expectException(UploadException::class); - $this->expectExceptionMessage('Missing chunk 2'); - $this->s3->finalize('/root/file.txt', 2, $metadata); - } - - public function testFinalizeCompletesS3PartsInNumericOrder(): void - { - $metadata = [ - 'uploadId' => 'upload-123', - 'parts' => [ - 10 => 'etag-10', - 9 => 'etag-9', - 8 => 'etag-8', - 7 => 'etag-7', - 6 => 'etag-6', - 5 => 'etag-5', - 4 => 'etag-4', - 3 => 'etag-3', - 2 => 'etag-2', - 1 => 'etag-1', - ], - 'chunks' => 10, - ]; - - $this->assertTrue($this->s3->finalize('/root/file.txt', 10, $metadata)); - - $part1 = strpos($this->s3->completedBody, '1'); - $part2 = strpos($this->s3->completedBody, '2'); - $part10 = strpos($this->s3->completedBody, '10'); - - $this->assertNotFalse($part1); - $this->assertNotFalse($part2); - $this->assertNotFalse($part10); - $this->assertLessThan($part2, $part1); - $this->assertLessThan($part10, $part2); - } - - public function testFinalizeSendsCompleteBodyAsXml(): void - { - $metadata = [ - 'uploadId' => 'upload-123', - 'parts' => [1 => 'etag-1', 2 => 'etag-2'], - 'chunks' => 2, - ]; - - $this->assertTrue($this->s3->finalize('/root/file.txt', 2, $metadata)); - $this->assertSame('application/xml', $this->s3->headersByOperation['s3:completeMultipartUpload']['content-type']); - } - - private function device(ScriptedClient $client): S3 - { - return new S3( - root: '/root', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'https://s3.example.com', - region: 'us-east-1', - client: new Retry($client, new RetryStrategy(delay: 0.0)), - ); - } - - private function slowDown(): Response - { - $body = 'SlowDownPlease reduce your request rate.'; - - return new Response(503, body: new Stream($body))->withHeader('content-type', 'application/xml'); - } - - public function testWriteSendsSignedRequest(): void - { - $client = new ScriptedClient([new Response(200)->withHeader('etag', '"b10a8db164e0754105b7a99be72e3fe5"')]); - - $this->assertSame('b10a8db164e0754105b7a99be72e3fe5', $this->device($client)->write('/root/file.txt', new Stream('Hello World'), 'text/plain'), 'the ETag comes back without its quotes'); - $this->assertCount(1, $client->requests); - - $request = $client->requests[0]; - $this->assertSame('PUT', $request->getMethod()); - $this->assertSame('s3.example.com', $request->getUri()->getHost()); - $this->assertSame('/root/file.txt', $request->getUri()->getPath()); - $this->assertSame('Hello World', (string) $request->getBody()); - $this->assertSame('text/plain', $request->getHeaderLine('content-type')); - $this->assertSame('private', $request->getHeaderLine('x-amz-acl')); - $this->assertSame(hash('sha256', 'Hello World'), $request->getHeaderLine('x-amz-content-sha256')); - $this->assertSame(base64_encode(md5('Hello World', true)), $request->getHeaderLine('content-md5')); - $this->assertStringStartsWith('AWS4-HMAC-SHA256 Credential=test-key/', $request->getHeaderLine('authorization')); - $this->assertSame('utopia-php/storage', $request->getHeaderLine('user-agent')); - } - - public function testEndpointPathIsExcludedFromHostHeader(): void - { - $client = new ScriptedClient([new Response(200)->withHeader('etag', '"abc"')]); - $device = new S3( - root: '/', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'http://minio:9000/storage/', - region: 'us-east-1', - client: $client, - ); - - $this->assertSame('abc', $device->write('archive/file.json', new Stream('{}'), 'application/json')); - - $request = $client->requests[0]; - $this->assertSame('minio', $request->getUri()->getHost()); - $this->assertSame(9000, $request->getUri()->getPort()); - $this->assertSame('/storage/archive/file.json', $request->getUri()->getPath()); - $this->assertSame('minio:9000', $request->getHeaderLine('host')); - } - - public function testTransientErrorIsRetriedUntilSuccess(): void - { - $client = new ScriptedClient([$this->slowDown(), $this->slowDown(), new Response(200)->withHeader('etag', '"abc"')]); - - $this->assertSame('abc', $this->device($client)->write('/root/file.txt', new Stream('Hello World'), 'text/plain')); - $this->assertCount(3, $client->requests); - } - - public function testTransientErrorRetriesAreExhausted(): void - { - $client = new ScriptedClient([$this->slowDown(), $this->slowDown(), $this->slowDown(), $this->slowDown()]); - - try { - $this->device($client)->write('/root/file.txt', new Stream('Hello World'), 'text/plain'); - self::fail('Expected exception after exhausting retries'); - } catch (RemoteException $e) { - $this->assertSame(503, $e->getCode()); - $this->assertSame('SlowDown', $e->errorCode); - } - - // Initial attempt plus the default three retries. - $this->assertCount(4, $client->requests); - } - - public function testNoSuchKeyBecomesNotFoundException(): void - { - $body = 'NoSuchKeyThe specified key does not exist.'; - $client = new ScriptedClient([new Response(404, body: new Stream($body))]); - - $this->expectException(NotFoundException::class); - $this->device($client)->read('/root/missing.txt'); - } - - public function testHeadNotFoundHasNoBodyButThrowsNotFound(): void - { - // HEAD error responses carry no body, so the 404 status is the only signal. - $client = new ScriptedClient([new Response(404)]); - - $this->expectException(NotFoundException::class); - $this->device($client)->getFileSize('/root/missing.txt'); - } - - public function testTransportFailureIsWrapped(): void - { - $psrError = new NetworkException(new Request('PUT', Uri::parse('https://s3.example.com/root')), 'Connection reset'); - $client = new ScriptedClient([$psrError]); - - try { - $this->device($client)->write('/root/file.txt', new Stream('Hello World'), 'text/plain'); - self::fail('Expected transport exception'); - } catch (TransportException $e) { - $this->assertSame($psrError, $e->getPrevious()); - } - } - - public function testEveryFailureIsCatchableAsStorageException(): void - { - $body = 'AccessDeniedAccess denied.'; - $client = new ScriptedClient([new Response(403, body: new Stream($body))]); - - try { - $this->device($client)->read('/root/file.txt'); - self::fail('Expected storage exception'); - } catch (StorageException $e) { - $this->assertInstanceOf(RemoteException::class, $e); - $this->assertSame('Access denied.', $e->getMessage()); - $this->assertSame(403, $e->getCode()); - } - } - - private function bucketDevice(): TestableS3 - { - $s3 = new TestableS3( - root: '/root', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'https://s3.example.com', - region: 'us-east-1', - bucket: 'my-bucket', - ); - $s3->objectExists = true; - - return $s3; - } - - public function testCopySameDeviceRunsServerSide(): void - { - $s3 = $this->bucketDevice(); - - $this->assertTrue($s3->copy('/root/a.jpg', '/root/b.jpg')); - $this->assertSame(['s3:info', 's3:copyObject'], $s3->calls); - - $amzHeaders = $s3->amzHeadersByOperation['s3:copyObject'][0]; - $this->assertSame('/my-bucket/root/a.jpg', $amzHeaders['x-amz-copy-source']); - $this->assertSame('COPY', $amzHeaders['x-amz-metadata-directive']); - } - - public function testCopyLargeObjectUsesMultipartServerSideCopy(): void - { - $s3 = $this->bucketDevice(); - $s3->infoContentLength = (string) (6 * 1024 * 1024 * 1024); // 6 GB — above the CopyObject limit - - $this->assertTrue($s3->copy('/root/a.bin', '/root/b.bin')); - $this->assertSame([ - 's3:info', - 's3:createMultipartUpload', - 's3:uploadPartCopy', - 's3:uploadPartCopy', - 's3:completeMultipartUpload', - ], $s3->calls); - - $ranges = array_column($s3->amzHeadersByOperation['s3:uploadPartCopy'], 'x-amz-copy-source-range'); - $this->assertSame(['bytes=0-5368709119', 'bytes=5368709120-6442450943'], $ranges); - $this->assertStringContainsString('etag-2', $s3->completedBody); - } - - public function testCopyWithoutBucketFallsBackToStreaming(): void - { - $this->s3->objectExists = true; - - $this->assertTrue($this->s3->copy('/root/a.jpg', '/root/b.jpg')); - $this->assertNotContains('s3:copyObject', $this->s3->calls); - $this->assertContains('s3:get', $this->s3->calls); - $this->assertContains('s3:write', $this->s3->calls); - } - - public function testZeroLengthReadReturnsEmptyStreamWithoutARequest(): void - { - $client = new ScriptedClient([]); - - $this->assertSame('', (string) $this->device($client)->read('/root/file.txt', 5, 0)); - $this->assertCount(0, $client->requests); - } - - public function testExistsReturnsFalseOnlyForNotFound(): void - { - $client = new ScriptedClient([new Response(404)]); - - $this->assertFalse($this->device($client)->exists('/root/missing.txt')); - } - - public function testExistsPropagatesTransientErrors(): void - { - // One initial attempt plus the default three retries, all throttled. - $client = new ScriptedClient([$this->slowDown(), $this->slowDown(), $this->slowDown(), $this->slowDown()]); - - $this->expectException(RemoteException::class); - $this->device($client)->exists('/root/file.txt'); - } - - public function testErrorMessageIncludesAmzRequestIds(): void - { - $body = 'AccessDeniedAccess denied.'; - $response = new Response(403, body: new Stream($body)) - ->withHeader('x-amz-request-id', 'REQ123') - ->withHeader('x-amz-id-2', 'HOST456'); - $client = new ScriptedClient([$response]); - - try { - $this->device($client)->read('/root/file.txt'); - self::fail('Expected remote exception'); - } catch (RemoteException $e) { - $this->assertStringContainsString('Access denied.', $e->getMessage()); - $this->assertStringContainsString('request-id: REQ123', $e->getMessage()); - $this->assertStringContainsString('id-2: HOST456', $e->getMessage()); - } - } - - public function testCopyAbortsMultipartUploadOnFailure(): void - { - $dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'utopia-storage-' . uniqid(); - mkdir($dir); - $sourcePath = $dir . DIRECTORY_SEPARATOR . 'src.bin'; - file_put_contents($sourcePath, str_repeat('a', 30)); - - $this->s3->failPart = 2; - - try { - new Local($dir)->copy($sourcePath, '/root/dest.bin', $this->s3, 10); - self::fail('Expected the injected part failure to surface'); - } catch (RemoteException $e) { - $this->assertSame('Injected part failure', $e->getMessage()); - } finally { - unlink($sourcePath); - rmdir($dir); - } - - $this->assertContains('s3:createMultipartUpload', $this->s3->calls); - $this->assertContains('s3:abort', $this->s3->calls); - $this->assertNotContains('s3:completeMultipartUpload', $this->s3->calls); - } - - public function testXmlListingIsDecodedIntoTypedFiles(): void - { - $body = '2true1000next-token' - . 'root/a.txt112026-01-02T03:04:05.000Z"abc123"' - . 'root/b.txt222026-01-02T03:04:06.000Z"def456"' - . ''; - $client = new ScriptedClient([new Response(200, body: new Stream($body))->withHeader('content-type', 'application/xml')]); - - $list = $this->device($client)->listFiles('/root/testing'); - - $this->assertCount(2, $list->files); - $this->assertSame('root/a.txt', $list->files[0]->path); - $this->assertSame(11, $list->files[0]->size); - $this->assertSame('abc123', $list->files[0]->etag); - $this->assertSame('2026-01-02', $list->files[0]->modifiedAt?->format('Y-m-d')); - $this->assertSame('next-token', $list->cursor); - } - - /** A lone element decodes as one associative entry rather than a list — the consumer must handle both. */ - public function testXmlListingWithSingleObjectIsDecoded(): void - { - $body = '1false' - . 'root/a.txt112026-01-02T03:04:05.000Z"abc123"' - . ''; - $client = new ScriptedClient([new Response(200, body: new Stream($body))->withHeader('content-type', 'application/xml')]); - - $list = $this->device($client)->listFiles('/root/testing'); - - $this->assertCount(1, $list->files); - $this->assertSame('root/a.txt', $list->files[0]->path); - $this->assertSame(11, $list->files[0]->size); - $this->assertNull($list->cursor); - } - - public function testFinalizeCompletesOverAnExistingObject(): void - { - // The upload replaces whatever is at the path; an object already there is no reason to skip completion. - $this->s3->objectExists = true; - $metadata = []; - $this->s3->prepare('/root/file.txt', 'text/plain', 2, $metadata); - $this->s3->upload(new Stream('a'), '/root/file.txt', 'text/plain', 1, 0, $metadata); - $this->s3->upload(new Stream('b'), '/root/file.txt', 'text/plain', 2, 0, $metadata); - - $this->assertTrue($this->s3->finalize('/root/file.txt', 2, $metadata)); - $this->assertContains('s3:completeMultipartUpload', $this->s3->calls); - } - - public function testFinalizeTwiceIsNotAnError(): void - { - $metadata = []; - $this->s3->prepare('/root/file.txt', 'text/plain', 2, $metadata); - $this->s3->upload(new Stream('a'), '/root/file.txt', 'text/plain', 1, 0, $metadata); - $this->s3->upload(new Stream('b'), '/root/file.txt', 'text/plain', 2, 0, $metadata); - - $this->assertTrue($this->s3->finalize('/root/file.txt', 2, $metadata)); - $this->assertTrue($this->s3->finalize('/root/file.txt', 2, $metadata), 'the upload is gone but the object is there'); - $this->assertCount(2, array_keys($this->s3->calls, 's3:completeMultipartUpload', true)); - } - - public function testFinalizeOfAnAbortedUploadFails(): void - { - $metadata = []; - $this->s3->prepare('/root/file.txt', 'text/plain', 2, $metadata); - $this->s3->upload(new Stream('a'), '/root/file.txt', 'text/plain', 1, 0, $metadata); - $this->s3->upload(new Stream('b'), '/root/file.txt', 'text/plain', 2, 0, $metadata); - $this->s3->completedBody = 'aborted elsewhere'; // makes the next completion answer NoSuchUpload - - $this->expectException(NotFoundException::class); - $this->s3->finalize('/root/file.txt', 2, $metadata); - } - - public function testASingleChunkOfAnUploadWithUnknownCountIsCompleted(): void - { - $this->s3->objectExists = true; // the object being replaced - $metadata = []; - $this->s3->upload(new Stream('a'), '/root/file.txt', 'text/plain', 1, 0, $metadata); - - $this->assertNotContains('s3:completeMultipartUpload', $this->s3->calls); - $this->assertTrue($this->s3->finalize('/root/file.txt', 1, $metadata)); - $this->assertContains('s3:completeMultipartUpload', $this->s3->calls, 'one part is still a part, not a whole object written already'); - } - - public function testUnknownChunkCountNeverFinalizesOnItsOwn(): void - { - $metadata = []; - $this->s3->upload(new Stream('a'), '/root/file.txt', 'text/plain', 1, 0, $metadata); - $this->s3->upload(new Stream('b'), '/root/file.txt', 'text/plain', 2, 0, $metadata); - $this->s3->upload(new Stream('c'), '/root/file.txt', 'text/plain', 3, 0, $metadata); - - $this->assertContains('s3:createMultipartUpload', $this->s3->calls); - $this->assertNotContains('s3:completeMultipartUpload', $this->s3->calls); - $this->assertTrue($this->s3->finalize('/root/file.txt', 3, $metadata)); - $this->assertContains('s3:completeMultipartUpload', $this->s3->calls); - } - - public function testFinalizeOfACompletedUploadWithoutItsIdIsNotAnError(): void - { - $this->s3->objectExists = true; - $metadata = ['parts' => [1 => 'etag-1', 2 => 'etag-2'], 'chunks' => 2]; - - $this->assertTrue($this->s3->finalize('/root/file.txt', 2, $metadata), 'the object is there, so the upload was completed'); - $this->assertNotContains('s3:completeMultipartUpload', $this->s3->calls); - } - - public function testFinalizeOfAnUploadThatNeverExistedFails(): void - { - $metadata = ['parts' => [1 => 'etag-1', 2 => 'etag-2'], 'chunks' => 2]; - - $this->assertFalse($this->s3->finalize('/root/file.txt', 2, $metadata)); - } - - public function testWritesCarryNoAclWhenNoneIsConfigured(): void - { - $client = new ScriptedClient([new Response(200)->withHeader('etag', '"abc"')]); - $device = new S3( - root: '/root', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'https://s3.example.com', - region: 'us-east-1', - acl: null, - client: $client, - ); - - $this->assertSame('abc', $device->write('/root/file.txt', new Stream('Hello World'), 'text/plain')); - $this->assertFalse($client->requests[0]->hasHeader('x-amz-acl')); - } - - public function testMultipartUploadCarriesNoAclWhenNoneIsConfigured(): void - { - $s3 = new TestableS3( - root: '/root', - accessKey: 'test-key', - secretKey: 'test-secret', - host: 'https://s3.example.com', - region: 'us-east-1', - acl: null, - ); - $metadata = []; - $s3->prepare('/root/file.txt', 'text/plain', 2, $metadata); - - $this->assertSame([[]], $s3->amzHeadersByOperation['s3:createMultipartUpload']); - } - - public function testCreateWritesOnlyWhereNothingIsAndReturnsTheEtag(): void - { - $client = new ScriptedClient([new Response(200)->withHeader('etag', '"abc123"')]); - - $this->assertSame('abc123', $this->device($client)->create('/root/lock', new Stream('token'), 'text/plain')); - - $request = $client->requests[0]; - $this->assertSame('PUT', $request->getMethod()); - $this->assertSame('*', $request->getHeaderLine('if-none-match')); - $this->assertFalse($request->hasHeader('if-match')); - $this->assertSame('token', (string) $request->getBody()); - $this->assertStringContainsString('if-none-match', $request->getHeaderLine('authorization'), 'the condition is signed'); - } - - public function testCreateOverAnExistingObjectIsRefused(): void - { - $body = 'PreconditionFailedAt least one of the pre-conditions you specified did not hold'; - $client = new ScriptedClient([new Response(412, body: new Stream($body))]); - - try { - $this->device($client)->create('/root/lock', new Stream('token'), 'text/plain'); - self::fail('Expected precondition failure'); - } catch (PreconditionFailedException $e) { - $this->assertSame(412, $e->getCode()); - $this->assertStringStartsWith('At least one of the pre-conditions', $e->getMessage()); - } - } - - public function testReplaceNamesTheEtagItWritesOver(): void - { - $client = new ScriptedClient([new Response(200)->withHeader('etag', '"new"')]); - - $this->assertSame('new', $this->device($client)->replace('/root/lock', new Stream('token'), 'old', 'text/plain')); - - $request = $client->requests[0]; - $this->assertSame('"old"', $request->getHeaderLine('if-match'), 'the ETag goes out quoted, as S3 reports it'); - $this->assertFalse($request->hasHeader('if-none-match')); - } - - public function testReplaceOfAnotherVersionIsRefused(): void - { - $client = new ScriptedClient([new Response(412)]); - - $this->expectException(PreconditionFailedException::class); - $this->device($client)->replace('/root/lock', new Stream('token'), 'old', 'text/plain'); - } - - public function testReadWithEtagSendsIfMatch(): void - { - $client = new ScriptedClient([new Response(206, body: new Stream('Hello'))->withHeader('etag', '"abc"')->withHeader('content-range', 'bytes 0-4/11')]); - - $this->assertSame('Hello', (string) $this->device($client)->read('/root/file.txt', 0, 5, 'abc')); - - $request = $client->requests[0]; - $this->assertSame('bytes=0-4', $request->getHeaderLine('range')); - $this->assertSame('"abc"', $request->getHeaderLine('if-match')); - } - - public function testReadOfAReplacedObjectIsRefused(): void - { - $body = 'PreconditionFailedAt least one of the pre-conditions you specified did not hold'; - $client = new ScriptedClient([new Response(412, body: new Stream($body))]); - - $this->expectException(PreconditionFailedException::class); - $this->device($client)->read('/root/file.txt', 0, 5, 'abc'); - } - - public function testGetFileInfoReadsTheHeaders(): void - { - $client = new ScriptedClient([new Response(200) - ->withHeader('etag', '"abc123"') - ->withHeader('content-length', '11') - ->withHeader('last-modified', 'Fri, 18 Sep 2026 08:41:25 GMT')]); - - $info = $this->device($client)->getFileInfo('/root/file.txt'); - - $this->assertSame('HEAD', $client->requests[0]->getMethod()); - $this->assertSame('/root/file.txt', $info->path); - $this->assertSame(11, $info->size); - $this->assertSame('abc123', $info->etag, 'without the quotes, like every other ETag the library hands out'); - $this->assertSame('2026-09-18T08:41:25+00:00', $info->modifiedAt?->format(DATE_ATOM)); - } - - public function testGetFileInfoOfAMissingObjectThrowsNotFound(): void - { - $client = new ScriptedClient([new Response(404)]); - - $this->expectException(NotFoundException::class); - $this->device($client)->getFileInfo('/root/missing.txt'); - } - - public function testAWriteWithoutAnEtagInTheResponseIsAnError(): void - { - $client = new ScriptedClient([new Response(200)]); - - $this->expectException(RemoteException::class); - $this->expectExceptionMessage('Missing ETag'); - $this->device($client)->write('/root/file.txt', new Stream('Hello World'), 'text/plain'); - } - - public function testUploadListingIsDecodedIntoTypedUploads(): void - { - $body = 'my-bucketroot/trueroot/b.mp4upload-2' - . 'root/a.mp4upload-12026-01-02T03:04:05.000Z' - . 'root/b.mp4upload-22026-01-02T03:04:06.000Z' - . ''; - $client = new ScriptedClient([new Response(200, body: new Stream($body))->withHeader('content-type', 'application/xml')]); - - $list = $this->device($client)->listUploads('/root/', 2); - - $this->assertSame('/', $client->requests[0]->getUri()->getPath()); - parse_str($client->requests[0]->getUri()->getQuery(), $query); - $this->assertSame(['uploads' => '', 'prefix' => 'root/', 'max-uploads' => '2'], $query); - - $this->assertCount(2, $list->uploads); - $this->assertSame('root/a.mp4', $list->uploads[0]->path); - $this->assertSame('upload-1', $list->uploads[0]->uploadId); - $this->assertSame('2026-01-02', $list->uploads[0]->initiatedAt?->format('Y-m-d')); - $this->assertNotNull($list->cursor); - - // The cursor carries both markers back. - $client = new ScriptedClient([new Response(200, body: new Stream('false'))->withHeader('content-type', 'application/xml')]); - $list = $this->device($client)->listUploads('/root/', 2, $list->cursor); - parse_str($client->requests[0]->getUri()->getQuery(), $query); - $this->assertSame('root/b.mp4', $query['key-marker'] ?? null); - $this->assertSame('upload-2', $query['upload-id-marker'] ?? null); - $this->assertSame([], $list->uploads); - $this->assertNull($list->cursor); - } - - /** A lone element decodes as one associative entry rather than a list — the consumer must handle both. */ - public function testUploadListingWithSingleUploadIsDecoded(): void - { - $body = 'false' - . 'root/a.mp4upload-1' - . ''; - $client = new ScriptedClient([new Response(200, body: new Stream($body))->withHeader('content-type', 'application/xml')]); - - $list = $this->device($client)->listUploads('/root/'); - - $this->assertCount(1, $list->uploads); - $this->assertSame('upload-1', $list->uploads[0]->uploadId); - $this->assertNotInstanceOf(\DateTimeImmutable::class, $list->uploads[0]->initiatedAt); - $this->assertNull($list->cursor); - } - - public function testUploadListingRejectsAForeignCursor(): void - { - $client = new ScriptedClient([]); - - $this->expectException(\InvalidArgumentException::class); - $this->device($client)->listUploads('/root/', 10, 'next-token'); - } -} diff --git a/packages/storage/tests/Storage/Device/TelemetryTest.php b/packages/storage/tests/Storage/Device/TelemetryTest.php deleted file mode 100644 index 126df4c31..000000000 --- a/packages/storage/tests/Storage/Device/TelemetryTest.php +++ /dev/null @@ -1,62 +0,0 @@ -getPath('lorem.txt'); - - $this->assertArrayNotHasKey('storage.operation', $telemetry->histograms); - - $device->exists($path); - - $this->assertArrayHasKey('storage.operation', $telemetry->histograms); - } - - public function testDecoratedDeviceIsAccessible(): void - { - $underlying = new Local(__DIR__ . '/../../resources/disk-a'); - $device = new Telemetry(new TestTelemetry(), $underlying); - - $this->assertSame($underlying, $device->getDevice()); - } - - public function testConditionalOperationsAreForwardedAndMeasured(): void - { - $telemetry = new TestTelemetry(); - $underlying = new Local(sys_get_temp_dir()); - $device = new Telemetry($telemetry, $underlying); - $path = $underlying->getPath('telemetry-' . bin2hex(random_bytes(4)) . '.txt'); - - $etag = $device->create($path, new Stream('one'), 'text/plain'); - $this->assertSame(md5('one'), $etag); - $this->assertSame(md5('two'), $device->replace($path, new Stream('two'), $etag, 'text/plain')); - $this->assertSame('two', (string) $device->read($path, 0, null, md5('two'))); - $this->assertSame(3, $device->getFileInfo($path)->size); - - $underlying->delete($path); - - $this->assertArrayHasKey('storage.operation', $telemetry->histograms); - } - - public function testListingUploadsOnADeviceWithoutThemIsRefused(): void - { - $device = new Telemetry(new TestTelemetry(), new Local(sys_get_temp_dir())); - - $this->expectException(\BadMethodCallException::class); - $device->listUploads(); - } -} diff --git a/packages/storage/tests/Storage/Validator/FileExtTest.php b/packages/storage/tests/Storage/Validator/FileExtTest.php deleted file mode 100644 index 48db187f3..000000000 --- a/packages/storage/tests/Storage/Validator/FileExtTest.php +++ /dev/null @@ -1,39 +0,0 @@ -object = new FileExt([FileExt::TYPE_GIF, FileExt::TYPE_GZIP, FileExt::TYPE_ZIP]); - } - - protected function tearDown(): void {} - - public function testValues(): void - { - $this->assertEquals(false, $this->object->isValid('')); - $this->assertEquals(false, $this->object->isValid(null)); - $this->assertEquals(false, $this->object->isValid(false)); - $this->assertEquals(false, $this->object->isValid('test')); - $this->assertEquals(false, $this->object->isValid('...test.png')); - $this->assertEquals(true, $this->object->isValid('.gif')); - $this->assertEquals(true, $this->object->isValid('x.gif')); - $this->assertEquals(false, $this->object->isValid('gif')); - $this->assertEquals(false, $this->object->isValid('file.tar')); - $this->assertEquals(false, $this->object->isValid('file.tar.g')); - $this->assertEquals(true, $this->object->isValid('file.tar.gz')); - $this->assertEquals(true, $this->object->isValid('file.gz')); - $this->assertEquals(true, $this->object->isValid('file.GIF')); - $this->assertEquals(true, $this->object->isValid('file.zip')); - $this->assertEquals(false, $this->object->isValid('file.7zip')); - } -} diff --git a/packages/storage/tests/Storage/Validator/FileNameTest.php b/packages/storage/tests/Storage/Validator/FileNameTest.php deleted file mode 100644 index 0a38abf3b..000000000 --- a/packages/storage/tests/Storage/Validator/FileNameTest.php +++ /dev/null @@ -1,33 +0,0 @@ -object = new FileName(); - } - - protected function tearDown(): void {} - - public function testValues(): void - { - $this->assertEquals(false, $this->object->isValid('')); - $this->assertEquals(false, $this->object->isValid(null)); - $this->assertEquals(false, $this->object->isValid(false)); - $this->assertEquals(false, $this->object->isValid('../test')); - $this->assertEquals(true, $this->object->isValid('test.png')); - $this->assertEquals(true, $this->object->isValid('test')); - $this->assertEquals(true, $this->object->isValid('test-test')); - $this->assertEquals(true, $this->object->isValid('test_test')); - $this->assertEquals(true, $this->object->isValid('test.test-test_test')); - } -} diff --git a/packages/storage/tests/Storage/Validator/FileSizeTest.php b/packages/storage/tests/Storage/Validator/FileSizeTest.php deleted file mode 100644 index c2b86f3e4..000000000 --- a/packages/storage/tests/Storage/Validator/FileSizeTest.php +++ /dev/null @@ -1,27 +0,0 @@ -object = new FileSize(1000); - } - - protected function tearDown(): void {} - - public function testValues(): void - { - $this->assertEquals(false, $this->object->isValid(1001)); - $this->assertEquals(true, $this->object->isValid(1000)); - $this->assertEquals(true, $this->object->isValid(999)); - } -} diff --git a/packages/storage/tests/Storage/Validator/FileTypeTest.php b/packages/storage/tests/Storage/Validator/FileTypeTest.php deleted file mode 100644 index 3dfef1cfd..000000000 --- a/packages/storage/tests/Storage/Validator/FileTypeTest.php +++ /dev/null @@ -1,28 +0,0 @@ -object = new FileType([FileType::FILE_TYPE_JPEG]); - } - - protected function tearDown(): void {} - - public function testValues(): void - { - $this->assertEquals(true, $this->object->isValid(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $this->assertEquals(true, $this->object->isValid(__DIR__ . '/../../resources/disk-a/kitten-2.jpg')); - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-b/kitten-1.png')); - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-b/kitten-2.png')); - } -} diff --git a/packages/storage/tests/Storage/Validator/UploadTest.php b/packages/storage/tests/Storage/Validator/UploadTest.php deleted file mode 100644 index d6730c03e..000000000 --- a/packages/storage/tests/Storage/Validator/UploadTest.php +++ /dev/null @@ -1,29 +0,0 @@ -object = new Upload(); - } - - protected function tearDown(): void {} - - public function testValues(): void - { - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-a/kitten-1.jpg')); - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-a/kitten-2.jpg')); - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-b/kitten-1.png')); - $this->assertEquals(false, $this->object->isValid(__DIR__ . '/../../resources/disk-b/kitten-2.png')); - $this->assertEquals(false, $this->object->isValid(__FILE__)); - } -} diff --git a/packages/storage/tests/resources/disk-a/.gitignore b/packages/storage/tests/resources/disk-a/.gitignore deleted file mode 100644 index fceac3a54..000000000 --- a/packages/storage/tests/resources/disk-a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -* -!.gitignore -!config.xml -!kitten-1.jpg -!kitten-2.jpg -!kitten-3.gif -!large_file.mp4 -!lorem.txt diff --git a/packages/storage/tests/resources/disk-a/config.xml b/packages/storage/tests/resources/disk-a/config.xml deleted file mode 100644 index b25240927..000000000 --- a/packages/storage/tests/resources/disk-a/config.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - Charter Group -
- 100 Main - Framingham - MA - 01701 -
-
- 720 Prospect - Framingham - MA - 01701 -
-
- 120 Ridge - MA - 01760 -
-
-
\ No newline at end of file diff --git a/packages/storage/tests/resources/disk-a/kitten-1.jpg b/packages/storage/tests/resources/disk-a/kitten-1.jpg deleted file mode 100644 index 1ef767faf..000000000 Binary files a/packages/storage/tests/resources/disk-a/kitten-1.jpg and /dev/null differ diff --git a/packages/storage/tests/resources/disk-a/kitten-2.jpg b/packages/storage/tests/resources/disk-a/kitten-2.jpg deleted file mode 100644 index e50021f95..000000000 Binary files a/packages/storage/tests/resources/disk-a/kitten-2.jpg and /dev/null differ diff --git a/packages/storage/tests/resources/disk-a/kitten-3.gif b/packages/storage/tests/resources/disk-a/kitten-3.gif deleted file mode 100644 index 9e460bcff..000000000 Binary files a/packages/storage/tests/resources/disk-a/kitten-3.gif and /dev/null differ diff --git a/packages/storage/tests/resources/disk-a/large_file.mp4 b/packages/storage/tests/resources/disk-a/large_file.mp4 deleted file mode 100644 index 66d56ae65..000000000 Binary files a/packages/storage/tests/resources/disk-a/large_file.mp4 and /dev/null differ diff --git a/packages/storage/tests/resources/disk-a/lorem.txt b/packages/storage/tests/resources/disk-a/lorem.txt deleted file mode 100644 index b25e9534d..000000000 --- a/packages/storage/tests/resources/disk-a/lorem.txt +++ /dev/null @@ -1,999 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mattis molestie a iaculis at erat pellentesque adipiscing commodo elit. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. In nulla posuere sollicitudin aliquam ultrices. Arcu risus quis varius quam quisque. Odio ut enim blandit volutpat. Egestas diam in arcu cursus euismod quis viverra nibh. A diam sollicitudin tempor id eu nisl nunc. Nibh venenatis cras sed felis eget velit aliquet sagittis id. Volutpat maecenas volutpat blandit aliquam etiam erat. Bibendum ut tristique et egestas quis. Et leo duis ut diam quam nulla porttitor. Cum sociis natoque penatibus et. Aliquam malesuada bibendum arcu vitae elementum curabitur vitae. Sagittis purus sit amet volutpat consequat mauris nunc congue. Aliquet nibh praesent tristique magna sit. Tortor id aliquet lectus proin nibh. Pharetra vel turpis nunc eget lorem dolor sed viverra ipsum. Sagittis vitae et leo duis ut diam. - -Varius morbi enim nunc faucibus a. Diam sit amet nisl suscipit adipiscing. Elit at imperdiet dui accumsan sit amet nulla facilisi morbi. Urna condimentum mattis pellentesque id nibh. Massa tincidunt dui ut ornare lectus sit amet est. Id semper risus in hendrerit gravida. Cursus vitae congue mauris rhoncus. Faucibus scelerisque eleifend donec pretium vulputate sapien nec. Amet massa vitae tortor condimentum lacinia quis. Eu mi bibendum neque egestas congue quisque egestas diam in. Pretium fusce id velit ut tortor. Magnis dis parturient montes nascetur ridiculus mus mauris. Velit aliquet sagittis id consectetur purus ut faucibus pulvinar. Sed enim ut sem viverra aliquet eget sit amet tellus. Malesuada nunc vel risus commodo viverra maecenas. Dignissim enim sit amet venenatis urna. - -Nulla porttitor massa id neque aliquam vestibulum morbi. Sapien pellentesque habitant morbi tristique senectus et. Mauris a diam maecenas sed. Massa id neque aliquam vestibulum morbi blandit cursus. Tortor dignissim convallis aenean et tortor. Nulla aliquet porttitor lacus luctus accumsan tortor posuere. Maecenas volutpat blandit aliquam etiam erat velit scelerisque in. Aliquet enim tortor at auctor. Blandit massa enim nec dui nunc mattis enim ut tellus. Scelerisque eu ultrices vitae auctor. Nulla facilisi morbi tempus iaculis urna id volutpat lacus laoreet. In eu mi bibendum neque egestas congue quisque egestas diam. Leo duis ut diam quam nulla porttitor massa id. Habitant morbi tristique senectus et netus et malesuada. Convallis tellus id interdum velit laoreet id donec ultrices. Orci nulla pellentesque dignissim enim sit amet venenatis. Ultricies tristique nulla aliquet enim tortor at auctor urna. - -Viverra maecenas accumsan lacus vel. Amet aliquam id diam maecenas ultricies mi. Nec feugiat in fermentum posuere urna nec tincidunt praesent semper. Aliquet lectus proin nibh nisl. In est ante in nibh mauris cursus mattis. Et tortor consequat id porta nibh venenatis cras. Sit amet nisl suscipit adipiscing bibendum est ultricies integer. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Sagittis vitae et leo duis ut diam quam nulla porttitor. Fermentum leo vel orci porta non pulvinar neque laoreet. Est ultricies integer quis auctor elit. Sit amet venenatis urna cursus eget nunc scelerisque viverra mauris. - -Massa tempor nec feugiat nisl pretium fusce. Feugiat nisl pretium fusce id. Vel elit scelerisque mauris pellentesque pulvinar. Velit aliquet sagittis id consectetur purus ut faucibus. Molestie nunc non blandit massa enim nec dui nunc. Nec ultrices dui sapien eget mi. Sem fringilla ut morbi tincidunt augue. Sollicitudin tempor id eu nisl nunc. Ultrices in iaculis nunc sed augue lacus viverra vitae congue. Nunc aliquet bibendum enim facilisis gravida neque. Risus sed vulputate odio ut enim blandit volutpat maecenas volutpat. Amet volutpat consequat mauris nunc. - -Tincidunt id aliquet risus feugiat in ante metus. Feugiat nisl pretium fusce id velit ut tortor pretium. Risus nec feugiat in fermentum posuere. Dui accumsan sit amet nulla facilisi. Massa tempor nec feugiat nisl pretium fusce id velit. A erat nam at lectus urna duis convallis. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere. Id diam maecenas ultricies mi eget mauris pharetra. Odio ut sem nulla pharetra diam sit amet nisl. Diam vel quam elementum pulvinar etiam. Urna cursus eget nunc scelerisque viverra mauris in. - -Aliquet porttitor lacus luctus accumsan tortor. Porta nibh venenatis cras sed felis eget. Et pharetra pharetra massa massa ultricies mi quis. Eget velit aliquet sagittis id consectetur purus ut faucibus. Sed elementum tempus egestas sed sed risus pretium quam vulputate. Turpis in eu mi bibendum neque egestas congue quisque. In fermentum posuere urna nec tincidunt praesent semper feugiat nibh. Adipiscing bibendum est ultricies integer quis. Donec enim diam vulputate ut pharetra. Tellus cras adipiscing enim eu turpis egestas. Gravida cum sociis natoque penatibus. Magna eget est lorem ipsum dolor sit. Et malesuada fames ac turpis. - -Tristique et egestas quis ipsum suspendisse ultrices. Viverra vitae congue eu consequat ac. Leo urna molestie at elementum eu. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Nunc sed velit dignissim sodales ut eu sem integer. Sodales neque sodales ut etiam sit amet. Nec dui nunc mattis enim ut tellus elementum. Ultricies integer quis auctor elit sed vulputate. Dignissim enim sit amet venenatis. Duis ut diam quam nulla porttitor. Tellus elementum sagittis vitae et leo duis ut. Sed nisi lacus sed viverra tellus in hac habitasse. Pretium lectus quam id leo. Nisi quis eleifend quam adipiscing vitae proin. - -Vitae auctor eu augue ut lectus. Ac tincidunt vitae semper quis lectus. Consequat ac felis donec et odio pellentesque diam volutpat commodo. Augue ut lectus arcu bibendum at varius vel pharetra vel. Arcu felis bibendum ut tristique et egestas quis. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Adipiscing enim eu turpis egestas pretium aenean pharetra. Adipiscing diam donec adipiscing tristique risus nec feugiat in. Euismod quis viverra nibh cras pulvinar mattis nunc. Nec sagittis aliquam malesuada bibendum arcu. Vitae elementum curabitur vitae nunc sed velit dignissim sodales. Elementum tempus egestas sed sed. Iaculis nunc sed augue lacus viverra vitae. Risus feugiat in ante metus. Fringilla urna porttitor rhoncus dolor purus non enim praesent elementum. - -Elit pellentesque habitant morbi tristique senectus et netus et. Tortor dignissim convallis aenean et. Faucibus in ornare quam viverra orci sagittis eu volutpat. Fames ac turpis egestas integer eget aliquet. Sit amet volutpat consequat mauris nunc congue. Ornare aenean euismod elementum nisi quis eleifend quam. Nibh praesent tristique magna sit. Non diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Consequat semper viverra nam libero justo laoreet sit. Lorem donec massa sapien faucibus et molestie ac. Malesuada proin libero nunc consequat interdum varius. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Viverra orci sagittis eu volutpat odio. - -Malesuada pellentesque elit eget gravida cum sociis natoque. Laoreet non curabitur gravida arcu ac tortor dignissim. Amet mattis vulputate enim nulla aliquet porttitor lacus luctus. Tempor nec feugiat nisl pretium fusce id velit. Ut tellus elementum sagittis vitae et leo duis ut diam. Massa placerat duis ultricies lacus sed turpis tincidunt. Nunc consequat interdum varius sit amet. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Pulvinar pellentesque habitant morbi tristique. Feugiat nisl pretium fusce id. Vel orci porta non pulvinar neque. Pellentesque adipiscing commodo elit at imperdiet dui. Ut aliquam purus sit amet luctus venenatis. Egestas fringilla phasellus faucibus scelerisque. Nisl purus in mollis nunc sed id semper risus. Volutpat diam ut venenatis tellus in metus vulputate eu scelerisque. Consequat interdum varius sit amet. Pretium viverra suspendisse potenti nullam ac tortor vitae purus faucibus. - -Eleifend donec pretium vulputate sapien nec. Lectus arcu bibendum at varius. Arcu risus quis varius quam quisque id. Est ullamcorper eget nulla facilisi etiam dignissim diam quis. Vitae aliquet nec ullamcorper sit amet risus nullam eget felis. At lectus urna duis convallis convallis tellus id interdum. Gravida quis blandit turpis cursus in. Elit duis tristique sollicitudin nibh sit amet commodo nulla. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Sit amet luctus venenatis lectus. Pellentesque diam volutpat commodo sed. Vulputate dignissim suspendisse in est ante in. Blandit libero volutpat sed cras ornare arcu dui vivamus arcu. Arcu ac tortor dignissim convallis aenean et tortor at risus. Vitae nunc sed velit dignissim sodales ut eu sem integer. Duis tristique sollicitudin nibh sit. Et sollicitudin ac orci phasellus egestas. Senectus et netus et malesuada fames ac turpis. Tincidunt arcu non sodales neque sodales ut etiam sit. Enim tortor at auctor urna nunc id. - -Tellus elementum sagittis vitae et. Odio aenean sed adipiscing diam donec adipiscing tristique. Libero id faucibus nisl tincidunt eget nullam non nisi est. Laoreet id donec ultrices tincidunt. Dolor sed viverra ipsum nunc aliquet bibendum. Auctor neque vitae tempus quam pellentesque nec nam. Nulla porttitor massa id neque aliquam vestibulum. Risus viverra adipiscing at in. Lacus vel facilisis volutpat est. Egestas fringilla phasellus faucibus scelerisque eleifend. Praesent tristique magna sit amet purus gravida quis blandit turpis. Massa massa ultricies mi quis hendrerit dolor magna. Sed elementum tempus egestas sed sed risus. Nunc consequat interdum varius sit amet mattis vulputate enim. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at. - -Arcu felis bibendum ut tristique et egestas quis. Vestibulum lorem sed risus ultricies tristique nulla. Donec massa sapien faucibus et molestie ac. Adipiscing bibendum est ultricies integer quis auctor elit. Ornare massa eget egestas purus viverra accumsan in nisl nisi. Dui accumsan sit amet nulla facilisi morbi tempus. Pulvinar elementum integer enim neque volutpat ac tincidunt. Non diam phasellus vestibulum lorem sed. Mi bibendum neque egestas congue quisque egestas. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. Lectus urna duis convallis convallis tellus id interdum. In nibh mauris cursus mattis molestie a. Risus sed vulputate odio ut enim blandit volutpat maecenas. - -Nunc sed augue lacus viverra vitae congue eu consequat. Maecenas ultricies mi eget mauris pharetra. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Elit sed vulputate mi sit. Mauris pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus. Tempor orci dapibus ultrices in iaculis nunc sed. Vestibulum sed arcu non odio euismod lacinia. Neque viverra justo nec ultrices dui sapien eget. Mi in nulla posuere sollicitudin aliquam. In hac habitasse platea dictumst vestibulum rhoncus. Sit amet porttitor eget dolor morbi. - -Amet commodo nulla facilisi nullam vehicula ipsum a arcu. Vitae purus faucibus ornare suspendisse sed. Quam pellentesque nec nam aliquam sem et tortor consequat id. Consectetur adipiscing elit pellentesque habitant morbi tristique. Mattis aliquam faucibus purus in massa tempor nec feugiat. Amet volutpat consequat mauris nunc. Ac orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Mi eget mauris pharetra et ultrices neque ornare. Aliquet sagittis id consectetur purus ut. Eget gravida cum sociis natoque penatibus et magnis. At tempor commodo ullamcorper a lacus vestibulum sed arcu non. Consectetur adipiscing elit ut aliquam purus sit amet. Risus at ultrices mi tempus imperdiet nulla malesuada. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Neque gravida in fermentum et sollicitudin. Nunc sed blandit libero volutpat sed. Ridiculus mus mauris vitae ultricies leo integer malesuada nunc. Ac turpis egestas sed tempus urna et pharetra. Velit ut tortor pretium viverra suspendisse potenti nullam ac. Purus in mollis nunc sed id semper risus in. - -Pretium quam vulputate dignissim suspendisse in est ante in nibh. Pulvinar elementum integer enim neque volutpat. Vitae elementum curabitur vitae nunc sed. Suscipit adipiscing bibendum est ultricies integer quis auctor elit. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Adipiscing tristique risus nec feugiat. Quis auctor elit sed vulputate mi sit amet. Id faucibus nisl tincidunt eget nullam non nisi est sit. Curabitur vitae nunc sed velit. At elementum eu facilisis sed odio morbi quis commodo. - -Eu facilisis sed odio morbi quis commodo odio aenean sed. Pellentesque id nibh tortor id aliquet. Quis lectus nulla at volutpat diam. Faucibus vitae aliquet nec ullamcorper sit amet risus nullam eget. A cras semper auctor neque vitae tempus quam pellentesque. Sollicitudin tempor id eu nisl nunc. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus. Volutpat est velit egestas dui id ornare. Curabitur vitae nunc sed velit dignissim. Vestibulum lectus mauris ultrices eros in cursus. Vestibulum sed arcu non odio euismod lacinia. Arcu cursus euismod quis viverra nibh cras pulvinar mattis. Ut porttitor leo a diam sollicitudin tempor id. - -Dui nunc mattis enim ut tellus. Id interdum velit laoreet id donec. Ipsum nunc aliquet bibendum enim facilisis gravida neque. Vulputate mi sit amet mauris commodo quis imperdiet massa. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Malesuada pellentesque elit eget gravida cum sociis natoque penatibus et. Diam ut venenatis tellus in. Id diam vel quam elementum pulvinar. Eu scelerisque felis imperdiet proin fermentum leo vel. Euismod quis viverra nibh cras pulvinar mattis. Sed pulvinar proin gravida hendrerit. Orci sagittis eu volutpat odio. Elit eget gravida cum sociis natoque penatibus. Tincidunt eget nullam non nisi est sit. Eget mi proin sed libero enim sed. Tortor consequat id porta nibh. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. - -Duis convallis convallis tellus id interdum velit. Cras ornare arcu dui vivamus arcu felis bibendum ut. Nam libero justo laoreet sit amet. Scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Sed id semper risus in hendrerit gravida. Risus in hendrerit gravida rutrum quisque non tellus orci. Cras sed felis eget velit aliquet sagittis. Mattis molestie a iaculis at erat. Quisque id diam vel quam elementum pulvinar etiam non quam. Sit amet purus gravida quis. Enim praesent elementum facilisis leo vel fringilla est ullamcorper eget. Fermentum iaculis eu non diam phasellus vestibulum. Neque convallis a cras semper auctor neque vitae tempus quam. - -Elit scelerisque mauris pellentesque pulvinar pellentesque. Id volutpat lacus laoreet non curabitur gravida arcu. Odio ut sem nulla pharetra diam sit amet. Enim facilisis gravida neque convallis a cras semper auctor neque. Interdum posuere lorem ipsum dolor sit. A diam sollicitudin tempor id eu nisl nunc. Sit amet nisl purus in mollis nunc. Porttitor lacus luctus accumsan tortor posuere. Dictum non consectetur a erat nam at lectus urna duis. Ullamcorper morbi tincidunt ornare massa. Ac placerat vestibulum lectus mauris ultrices eros in cursus turpis. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque. Lectus arcu bibendum at varius vel pharetra vel turpis. Ut tortor pretium viverra suspendisse potenti nullam. Senectus et netus et malesuada fames ac. Massa eget egestas purus viverra accumsan in nisl nisi scelerisque. Phasellus egestas tellus rutrum tellus pellentesque eu tincidunt tortor. Aliquam eleifend mi in nulla posuere sollicitudin aliquam. - -Risus sed vulputate odio ut enim blandit volutpat. Pharetra diam sit amet nisl suscipit. Fermentum leo vel orci porta non pulvinar. Maecenas volutpat blandit aliquam etiam erat velit scelerisque in dictum. Vulputate dignissim suspendisse in est ante. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Duis at tellus at urna condimentum mattis pellentesque id. Eget nunc scelerisque viverra mauris. Ipsum faucibus vitae aliquet nec ullamcorper sit amet risus nullam. Aliquam id diam maecenas ultricies mi eget. Vel fringilla est ullamcorper eget nulla facilisi etiam. A scelerisque purus semper eget duis at tellus at. Felis imperdiet proin fermentum leo vel orci. Non arcu risus quis varius quam quisque. Egestas quis ipsum suspendisse ultrices gravida dictum fusce. - -Pellentesque nec nam aliquam sem et tortor consequat id porta. Proin nibh nisl condimentum id venenatis a condimentum vitae sapien. Est sit amet facilisis magna etiam tempor orci. Viverra aliquet eget sit amet tellus cras. Molestie nunc non blandit massa enim nec. Tellus molestie nunc non blandit massa. In est ante in nibh. Venenatis lectus magna fringilla urna porttitor rhoncus. Eget arcu dictum varius duis at consectetur lorem donec. Nulla facilisi etiam dignissim diam quis enim lobortis scelerisque. Mi tempus imperdiet nulla malesuada pellentesque. - -Et netus et malesuada fames ac turpis egestas. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Mi sit amet mauris commodo quis imperdiet. Mi bibendum neque egestas congue quisque egestas diam in arcu. Facilisis leo vel fringilla est. Pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. Eget egestas purus viverra accumsan. Magnis dis parturient montes nascetur ridiculus mus mauris vitae. Mi bibendum neque egestas congue quisque egestas diam in arcu. Diam vulputate ut pharetra sit. Sed velit dignissim sodales ut eu sem integer vitae. Tristique risus nec feugiat in fermentum posuere urna. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Faucibus purus in massa tempor nec feugiat nisl pretium fusce. In arcu cursus euismod quis. Ultrices dui sapien eget mi proin sed libero. Posuere lorem ipsum dolor sit amet consectetur adipiscing. Leo integer malesuada nunc vel risus. Varius vel pharetra vel turpis nunc eget lorem. Viverra adipiscing at in tellus integer feugiat. - -Blandit turpis cursus in hac habitasse platea dictumst. In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Elit sed vulputate mi sit amet mauris commodo quis. Ut morbi tincidunt augue interdum velit euismod in. Vitae sapien pellentesque habitant morbi tristique. Mi proin sed libero enim sed faucibus turpis in. Sed risus ultricies tristique nulla. Facilisis sed odio morbi quis commodo odio aenean. Tempus iaculis urna id volutpat lacus laoreet non curabitur. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus interdum. Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Tristique senectus et netus et malesuada fames ac. - -Vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Interdum posuere lorem ipsum dolor sit amet. Quisque sagittis purus sit amet volutpat consequat. Duis at consectetur lorem donec massa sapien faucibus et. Et malesuada fames ac turpis egestas. Rhoncus urna neque viverra justo nec ultrices dui sapien. Eget arcu dictum varius duis at consectetur lorem donec. Lobortis feugiat vivamus at augue eget arcu dictum varius duis. Orci eu lobortis elementum nibh. A scelerisque purus semper eget duis at tellus at. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Nibh venenatis cras sed felis. Neque laoreet suspendisse interdum consectetur libero. Elit eget gravida cum sociis natoque penatibus et. Quisque egestas diam in arcu cursus. Diam sollicitudin tempor id eu nisl. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Phasellus egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam. Sed adipiscing diam donec adipiscing. Auctor elit sed vulputate mi. - -Dui faucibus in ornare quam. Ultricies mi eget mauris pharetra et ultrices neque. Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin. Amet nisl purus in mollis nunc sed. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Tortor id aliquet lectus proin nibh nisl condimentum id. Metus dictum at tempor commodo ullamcorper a lacus vestibulum sed. Adipiscing enim eu turpis egestas pretium. Donec et odio pellentesque diam. Tellus in metus vulputate eu scelerisque. Ut sem viverra aliquet eget sit amet tellus cras. Purus faucibus ornare suspendisse sed nisi. Penatibus et magnis dis parturient montes nascetur ridiculus. Nec feugiat nisl pretium fusce. Nunc scelerisque viverra mauris in aliquam sem fringilla ut morbi. - -Ut tristique et egestas quis ipsum suspendisse ultrices gravida. Volutpat maecenas volutpat blandit aliquam. Consequat ac felis donec et odio pellentesque diam volutpat. Ac tortor dignissim convallis aenean. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Dui vivamus arcu felis bibendum ut tristique. Ut venenatis tellus in metus vulputate eu scelerisque felis. Eget mi proin sed libero enim. Felis imperdiet proin fermentum leo vel. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Neque egestas congue quisque egestas diam in arcu. - -Dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Morbi tristique senectus et netus et. Ipsum consequat nisl vel pretium lectus quam. Sit amet commodo nulla facilisi nullam vehicula ipsum a arcu. Bibendum arcu vitae elementum curabitur vitae nunc sed. Nam at lectus urna duis. Massa eget egestas purus viverra accumsan in nisl nisi scelerisque. Justo eget magna fermentum iaculis eu non diam. Mauris commodo quis imperdiet massa. Nibh sed pulvinar proin gravida. Nibh praesent tristique magna sit amet purus gravida. Suscipit tellus mauris a diam maecenas sed enim ut. Vitae purus faucibus ornare suspendisse sed nisi lacus. Non enim praesent elementum facilisis. Tincidunt lobortis feugiat vivamus at augue. Sit amet massa vitae tortor condimentum lacinia quis vel. Id volutpat lacus laoreet non curabitur gravida arcu ac. Tristique senectus et netus et. Non diam phasellus vestibulum lorem sed risus. - -Congue quisque egestas diam in. Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc. Habitasse platea dictumst vestibulum rhoncus est. Augue neque gravida in fermentum et sollicitudin. Scelerisque in dictum non consectetur a erat nam at. Sit amet consectetur adipiscing elit duis tristique sollicitudin. Amet purus gravida quis blandit turpis. Sit amet justo donec enim diam vulputate ut pharetra. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam. Non tellus orci ac auctor augue mauris. Vitae et leo duis ut diam quam. - -Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Eu scelerisque felis imperdiet proin fermentum leo vel orci porta. Fermentum leo vel orci porta non pulvinar neque. Dignissim diam quis enim lobortis scelerisque fermentum dui. Eget mauris pharetra et ultrices neque. Blandit turpis cursus in hac. Elementum eu facilisis sed odio morbi quis commodo odio. A scelerisque purus semper eget. Id eu nisl nunc mi ipsum faucibus vitae aliquet nec. Vitae tortor condimentum lacinia quis vel eros donec ac. Ultrices gravida dictum fusce ut. Condimentum id venenatis a condimentum vitae. Ultricies lacus sed turpis tincidunt id aliquet. Orci nulla pellentesque dignissim enim sit amet venenatis. - -Ut porttitor leo a diam sollicitudin. Eros donec ac odio tempor orci dapibus ultrices in iaculis. In est ante in nibh mauris cursus mattis. Eu volutpat odio facilisis mauris sit amet massa vitae tortor. Amet risus nullam eget felis eget nunc lobortis mattis. Quis blandit turpis cursus in hac. Nulla aliquet enim tortor at auctor urna nunc. Risus viverra adipiscing at in tellus integer feugiat scelerisque varius. Est ante in nibh mauris cursus mattis molestie a iaculis. Nibh ipsum consequat nisl vel pretium lectus quam id leo. Diam vel quam elementum pulvinar etiam non quam lacus suspendisse. Maecenas accumsan lacus vel facilisis volutpat est velit egestas dui. Sagittis nisl rhoncus mattis rhoncus urna neque. Sit amet nisl purus in mollis nunc sed id semper. - -Scelerisque purus semper eget duis at tellus at urna. Mattis vulputate enim nulla aliquet porttitor. Consequat semper viverra nam libero justo. Turpis egestas integer eget aliquet nibh. Nullam eget felis eget nunc lobortis mattis aliquam faucibus. Faucibus turpis in eu mi bibendum. Quam quisque id diam vel quam elementum pulvinar. Orci nulla pellentesque dignissim enim. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Egestas integer eget aliquet nibh praesent. Id diam vel quam elementum pulvinar etiam. Non consectetur a erat nam. Sagittis orci a scelerisque purus semper eget duis at. Laoreet sit amet cursus sit amet dictum. In pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. Eu ultrices vitae auctor eu. Et malesuada fames ac turpis egestas sed tempus. Magna sit amet purus gravida quis blandit turpis. Sit amet mattis vulputate enim nulla aliquet porttitor lacus luctus. - -Integer vitae justo eget magna fermentum iaculis. Imperdiet massa tincidunt nunc pulvinar. Sit amet mauris commodo quis. Pellentesque adipiscing commodo elit at imperdiet dui accumsan. Id velit ut tortor pretium viverra suspendisse. Adipiscing enim eu turpis egestas pretium aenean pharetra magna ac. In eu mi bibendum neque egestas congue. Magna etiam tempor orci eu lobortis elementum nibh. Arcu odio ut sem nulla pharetra diam sit amet. Elit duis tristique sollicitudin nibh sit amet commodo. Egestas pretium aenean pharetra magna ac placerat vestibulum lectus. Sed libero enim sed faucibus turpis in. Amet cursus sit amet dictum sit amet justo donec. Ornare massa eget egestas purus viverra accumsan in. Imperdiet massa tincidunt nunc pulvinar. - -Integer eget aliquet nibh praesent tristique magna sit. Faucibus pulvinar elementum integer enim neque. A diam sollicitudin tempor id eu. Platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Pellentesque massa placerat duis ultricies lacus sed turpis tincidunt id. Consectetur adipiscing elit ut aliquam purus sit amet luctus. Diam ut venenatis tellus in metus. Elit pellentesque habitant morbi tristique senectus et netus. Etiam sit amet nisl purus in. Morbi tincidunt ornare massa eget egestas purus viverra accumsan. At erat pellentesque adipiscing commodo elit at. Id nibh tortor id aliquet lectus proin nibh nisl. Amet nisl purus in mollis. Donec ultrices tincidunt arcu non sodales neque sodales. Blandit aliquam etiam erat velit scelerisque in dictum non. Nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque. Venenatis a condimentum vitae sapien pellentesque habitant morbi. - -In ante metus dictum at tempor commodo ullamcorper a lacus. Arcu dictum varius duis at consectetur lorem donec massa. Arcu non sodales neque sodales ut. Neque ornare aenean euismod elementum nisi quis eleifend. Nibh praesent tristique magna sit amet purus. Turpis massa sed elementum tempus egestas sed sed risus. Non tellus orci ac auctor augue. Nisi lacus sed viverra tellus in. Risus pretium quam vulputate dignissim suspendisse in est ante. Ipsum dolor sit amet consectetur adipiscing elit. Laoreet sit amet cursus sit amet dictum sit. Etiam erat velit scelerisque in dictum. Scelerisque viverra mauris in aliquam sem. Sagittis id consectetur purus ut faucibus pulvinar. Velit laoreet id donec ultrices tincidunt arcu non sodales neque. At ultrices mi tempus imperdiet nulla malesuada. Massa tincidunt dui ut ornare. - -Ultrices sagittis orci a scelerisque purus semper. Velit dignissim sodales ut eu. Egestas erat imperdiet sed euismod nisi porta lorem mollis. Nunc scelerisque viverra mauris in aliquam sem fringilla. Maecenas accumsan lacus vel facilisis volutpat est. Mi tempus imperdiet nulla malesuada pellentesque elit eget. Sit amet commodo nulla facilisi nullam vehicula ipsum a arcu. Duis ultricies lacus sed turpis. Tristique sollicitudin nibh sit amet commodo nulla. Orci phasellus egestas tellus rutrum. Scelerisque eleifend donec pretium vulputate. Quis hendrerit dolor magna eget. Nibh sit amet commodo nulla. Tortor dignissim convallis aenean et tortor at risus viverra. Mi tempus imperdiet nulla malesuada pellentesque elit eget gravida. Lobortis feugiat vivamus at augue eget. Amet est placerat in egestas erat imperdiet sed euismod nisi. - -Pharetra sit amet aliquam id diam maecenas. Arcu cursus euismod quis viverra. Risus pretium quam vulputate dignissim suspendisse in est ante in. Non odio euismod lacinia at quis risus sed vulputate odio. Eget est lorem ipsum dolor sit amet consectetur adipiscing. Sed viverra tellus in hac. Massa eget egestas purus viverra accumsan in nisl nisi. Tempus imperdiet nulla malesuada pellentesque elit eget gravida cum. Hac habitasse platea dictumst vestibulum rhoncus est. Rhoncus dolor purus non enim praesent elementum facilisis. Tellus molestie nunc non blandit massa enim nec dui. Aliquet risus feugiat in ante. Leo a diam sollicitudin tempor id. Et tortor consequat id porta nibh. Nibh mauris cursus mattis molestie a iaculis at erat pellentesque. Magna fringilla urna porttitor rhoncus dolor purus non. Consequat interdum varius sit amet mattis. - -Sed vulputate odio ut enim blandit volutpat. Viverra aliquet eget sit amet tellus cras adipiscing. Id diam vel quam elementum. Condimentum mattis pellentesque id nibh tortor id aliquet lectus. Vulputate odio ut enim blandit volutpat maecenas volutpat blandit aliquam. Sed vulputate mi sit amet mauris commodo. Sit amet venenatis urna cursus eget. Egestas sed sed risus pretium quam. Velit laoreet id donec ultrices tincidunt arcu. Id aliquet lectus proin nibh nisl condimentum id. Risus commodo viverra maecenas accumsan lacus vel. Arcu cursus vitae congue mauris rhoncus. Blandit libero volutpat sed cras ornare. - -Amet venenatis urna cursus eget nunc scelerisque viverra mauris in. Ultrices in iaculis nunc sed augue lacus viverra vitae congue. Pellentesque adipiscing commodo elit at imperdiet dui accumsan. Mattis pellentesque id nibh tortor id. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Maecenas sed enim ut sem. Elit at imperdiet dui accumsan sit amet nulla facilisi. Faucibus et molestie ac feugiat sed lectus vestibulum. Commodo ullamcorper a lacus vestibulum sed arcu. Sociis natoque penatibus et magnis. Iaculis at erat pellentesque adipiscing commodo elit. Ornare quam viverra orci sagittis. Ultrices in iaculis nunc sed augue lacus. - -Odio aenean sed adipiscing diam donec adipiscing tristique risus. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Ac turpis egestas sed tempus urna et pharetra. Auctor augue mauris augue neque gravida in fermentum et sollicitudin. Nulla pellentesque dignissim enim sit amet venenatis urna cursus eget. Semper risus in hendrerit gravida rutrum quisque non. Dapibus ultrices in iaculis nunc. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. Bibendum ut tristique et egestas quis ipsum suspendisse ultrices gravida. Nisl nisi scelerisque eu ultrices vitae auctor eu augue ut. Enim ut sem viverra aliquet eget sit amet tellus. Fringilla ut morbi tincidunt augue interdum velit euismod in pellentesque. Faucibus a pellentesque sit amet porttitor eget. Quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Viverra mauris in aliquam sem fringilla ut. Sollicitudin aliquam ultrices sagittis orci a scelerisque purus. Vulputate odio ut enim blandit volutpat maecenas volutpat. - -Sed arcu non odio euismod lacinia at quis risus sed. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. At tempor commodo ullamcorper a. Lacus viverra vitae congue eu consequat ac felis donec. Diam in arcu cursus euismod quis. Faucibus interdum posuere lorem ipsum dolor sit amet. Adipiscing diam donec adipiscing tristique risus nec feugiat in. Egestas sed sed risus pretium. Blandit turpis cursus in hac habitasse platea dictumst. Pretium quam vulputate dignissim suspendisse in est ante. - -Eu augue ut lectus arcu bibendum at. Mauris rhoncus aenean vel elit scelerisque mauris. Quam quisque id diam vel quam elementum pulvinar. In hac habitasse platea dictumst vestibulum. Risus viverra adipiscing at in tellus integer. Eu non diam phasellus vestibulum lorem sed risus ultricies tristique. Ut eu sem integer vitae justo eget magna. Quam lacus suspendisse faucibus interdum posuere lorem. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Nibh venenatis cras sed felis eget velit. Habitant morbi tristique senectus et netus et. Et magnis dis parturient montes nascetur ridiculus mus. Diam in arcu cursus euismod quis viverra nibh cras. Gravida in fermentum et sollicitudin ac orci phasellus egestas tellus. Nascetur ridiculus mus mauris vitae ultricies leo. Egestas dui id ornare arcu odio ut. - -Egestas quis ipsum suspendisse ultrices gravida dictum fusce. Eget aliquet nibh praesent tristique magna sit amet purus gravida. Viverra orci sagittis eu volutpat odio facilisis. Sodales ut etiam sit amet nisl purus in mollis nunc. Id neque aliquam vestibulum morbi blandit cursus risus at. Ipsum nunc aliquet bibendum enim facilisis gravida neque. Donec et odio pellentesque diam. Amet porttitor eget dolor morbi non arcu risus quis varius. Ultrices mi tempus imperdiet nulla. Blandit volutpat maecenas volutpat blandit aliquam. Porttitor rhoncus dolor purus non enim. Congue mauris rhoncus aenean vel elit scelerisque mauris. - -Nunc eget lorem dolor sed viverra. Nulla facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum. Nunc lobortis mattis aliquam faucibus purus. Neque vitae tempus quam pellentesque. Interdum varius sit amet mattis. Tincidunt tortor aliquam nulla facilisi cras. Nibh sit amet commodo nulla facilisi nullam. Pellentesque adipiscing commodo elit at. Nunc eget lorem dolor sed viverra ipsum. Ipsum a arcu cursus vitae. Ultrices tincidunt arcu non sodales. Pellentesque elit eget gravida cum. Velit scelerisque in dictum non. Amet nisl suscipit adipiscing bibendum est. Viverra aliquet eget sit amet tellus. Amet luctus venenatis lectus magna fringilla urna. Eget egestas purus viverra accumsan in nisl nisi. Bibendum est ultricies integer quis auctor elit. Nullam vehicula ipsum a arcu cursus. Malesuada proin libero nunc consequat. - -Ipsum dolor sit amet consectetur adipiscing elit duis. At varius vel pharetra vel turpis nunc. Pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Nibh praesent tristique magna sit. Fusce ut placerat orci nulla. Nisi vitae suscipit tellus mauris a diam maecenas sed enim. Pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus. Dui id ornare arcu odio. Amet aliquam id diam maecenas ultricies mi eget mauris pharetra. Imperdiet sed euismod nisi porta lorem. Justo eget magna fermentum iaculis. Vitae justo eget magna fermentum iaculis eu non diam phasellus. Ac turpis egestas integer eget aliquet nibh praesent tristique. Et tortor at risus viverra adipiscing. - -Feugiat sed lectus vestibulum mattis ullamcorper. In hac habitasse platea dictumst. Dui faucibus in ornare quam viverra orci. Nisl pretium fusce id velit ut tortor. Cum sociis natoque penatibus et magnis. Adipiscing elit ut aliquam purus sit. Amet aliquam id diam maecenas ultricies mi eget mauris. Ornare lectus sit amet est placerat. Duis at tellus at urna condimentum mattis. Amet cursus sit amet dictum sit amet justo donec enim. Arcu non sodales neque sodales ut etiam sit. Urna condimentum mattis pellentesque id nibh tortor id. Est sit amet facilisis magna etiam tempor orci eu lobortis. Cras ornare arcu dui vivamus arcu felis. - -Netus et malesuada fames ac turpis egestas integer eget aliquet. At elementum eu facilisis sed odio morbi quis commodo. Tellus cras adipiscing enim eu turpis egestas pretium. Rutrum tellus pellentesque eu tincidunt tortor aliquam nulla facilisi. Magna ac placerat vestibulum lectus mauris. At in tellus integer feugiat scelerisque. Magna etiam tempor orci eu lobortis elementum nibh. Dolor purus non enim praesent elementum. Id neque aliquam vestibulum morbi blandit cursus risus at. Cursus euismod quis viverra nibh cras. Ut tellus elementum sagittis vitae et leo duis ut diam. Tincidunt ornare massa eget egestas purus. Viverra nam libero justo laoreet sit. Scelerisque fermentum dui faucibus in ornare quam viverra orci. - -Dignissim suspendisse in est ante in. Aenean euismod elementum nisi quis eleifend quam adipiscing vitae proin. Interdum varius sit amet mattis vulputate enim. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Sit amet luctus venenatis lectus magna. Id leo in vitae turpis massa sed elementum tempus egestas. Id volutpat lacus laoreet non curabitur. Lacus viverra vitae congue eu consequat ac felis. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Etiam dignissim diam quis enim lobortis scelerisque fermentum. Ornare massa eget egestas purus. Facilisi morbi tempus iaculis urna id volutpat lacus laoreet. Urna duis convallis convallis tellus id interdum. Eleifend donec pretium vulputate sapien nec. Dolor sed viverra ipsum nunc aliquet bibendum enim. Nulla pharetra diam sit amet nisl suscipit adipiscing bibendum est. Turpis egestas maecenas pharetra convallis posuere morbi leo urna molestie. - -Mauris a diam maecenas sed. Faucibus nisl tincidunt eget nullam non nisi est sit amet. Cursus mattis molestie a iaculis at erat pellentesque adipiscing. Neque vitae tempus quam pellentesque nec. Lorem ipsum dolor sit amet. Eget mauris pharetra et ultrices neque. Eleifend quam adipiscing vitae proin sagittis nisl. Mi eget mauris pharetra et ultrices neque ornare aenean. Ipsum suspendisse ultrices gravida dictum fusce. Posuere ac ut consequat semper viverra nam libero justo laoreet. - -Pharetra diam sit amet nisl suscipit adipiscing bibendum est. Vitae aliquet nec ullamcorper sit amet risus nullam. Tellus integer feugiat scelerisque varius morbi. Neque aliquam vestibulum morbi blandit. Massa enim nec dui nunc mattis enim. Urna porttitor rhoncus dolor purus non enim praesent. Facilisis gravida neque convallis a. Donec massa sapien faucibus et molestie ac feugiat. Volutpat maecenas volutpat blandit aliquam etiam erat velit. Massa ultricies mi quis hendrerit. Volutpat blandit aliquam etiam erat velit scelerisque. Ultricies leo integer malesuada nunc vel. Dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Sed vulputate odio ut enim blandit volutpat maecenas volutpat. Consequat nisl vel pretium lectus. Pretium fusce id velit ut tortor pretium. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Sed enim ut sem viverra aliquet eget sit amet. - -Urna neque viverra justo nec ultrices dui sapien. Potenti nullam ac tortor vitae purus. Consequat mauris nunc congue nisi vitae suscipit tellus mauris a. At quis risus sed vulputate odio ut enim. Ut venenatis tellus in metus vulputate eu scelerisque felis imperdiet. Nisi porta lorem mollis aliquam ut porttitor. Commodo viverra maecenas accumsan lacus vel. Nisl purus in mollis nunc sed. Dui id ornare arcu odio ut. Scelerisque felis imperdiet proin fermentum leo. Aliquam malesuada bibendum arcu vitae elementum. Morbi quis commodo odio aenean sed. - -Arcu felis bibendum ut tristique et egestas quis. In nibh mauris cursus mattis molestie a iaculis at erat. Pellentesque sit amet porttitor eget dolor morbi. Risus in hendrerit gravida rutrum quisque non tellus. Enim facilisis gravida neque convallis. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Dictum at tempor commodo ullamcorper. Vitae purus faucibus ornare suspendisse sed nisi lacus sed. Magna fermentum iaculis eu non diam phasellus vestibulum lorem. Amet massa vitae tortor condimentum lacinia quis vel. Amet luctus venenatis lectus magna fringilla. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam. Risus ultricies tristique nulla aliquet enim. Quisque sagittis purus sit amet volutpat consequat. Sed elementum tempus egestas sed sed risus pretium quam vulputate. Potenti nullam ac tortor vitae purus faucibus ornare. - -Tincidunt eget nullam non nisi. Id leo in vitae turpis massa sed elementum tempus. Nec ultrices dui sapien eget mi proin sed libero. Mollis nunc sed id semper risus. Mattis rhoncus urna neque viverra justo nec ultrices dui sapien. Vulputate sapien nec sagittis aliquam. Est ante in nibh mauris. Quam lacus suspendisse faucibus interdum posuere lorem ipsum dolor. Eros donec ac odio tempor orci. Ullamcorper dignissim cras tincidunt lobortis feugiat. Egestas maecenas pharetra convallis posuere morbi leo urna. Tristique nulla aliquet enim tortor at auctor urna. Congue nisi vitae suscipit tellus mauris. Malesuada proin libero nunc consequat. Adipiscing commodo elit at imperdiet dui accumsan. In cursus turpis massa tincidunt dui ut ornare. Magna ac placerat vestibulum lectus mauris. - -Condimentum id venenatis a condimentum vitae. Diam donec adipiscing tristique risus nec feugiat in fermentum. Nec sagittis aliquam malesuada bibendum arcu vitae. Dignissim sodales ut eu sem integer. Integer vitae justo eget magna fermentum iaculis eu. Purus sit amet volutpat consequat. Duis convallis convallis tellus id interdum. Morbi tincidunt ornare massa eget egestas purus viverra accumsan. Congue mauris rhoncus aenean vel elit. Lectus urna duis convallis convallis tellus id interdum. Tincidunt augue interdum velit euismod in pellentesque massa placerat. Sit amet nisl purus in mollis nunc. - -Sed enim ut sem viverra. Vel turpis nunc eget lorem dolor sed viverra. Cras semper auctor neque vitae tempus quam pellentesque nec. Viverra accumsan in nisl nisi scelerisque eu. Urna porttitor rhoncus dolor purus. Diam vel quam elementum pulvinar etiam non. Urna et pharetra pharetra massa massa ultricies mi. Dui ut ornare lectus sit amet est placerat. Tempus imperdiet nulla malesuada pellentesque elit eget gravida cum sociis. Faucibus nisl tincidunt eget nullam non nisi. Vel facilisis volutpat est velit egestas dui. Rutrum quisque non tellus orci. Morbi blandit cursus risus at. Tempus iaculis urna id volutpat lacus. Sit amet nisl suscipit adipiscing bibendum. Nibh sit amet commodo nulla facilisi. Fames ac turpis egestas integer eget aliquet. Elit ut aliquam purus sit. Nibh cras pulvinar mattis nunc. Et sollicitudin ac orci phasellus egestas. - -Montes nascetur ridiculus mus mauris vitae. Arcu bibendum at varius vel pharetra. Ante metus dictum at tempor commodo ullamcorper a. Et tortor consequat id porta nibh venenatis cras. Enim blandit volutpat maecenas volutpat blandit aliquam. Morbi blandit cursus risus at ultrices mi. Tempor nec feugiat nisl pretium fusce id velit ut tortor. Id leo in vitae turpis massa sed. Laoreet id donec ultrices tincidunt arcu. Quam nulla porttitor massa id neque aliquam vestibulum. Arcu vitae elementum curabitur vitae nunc. - -Sapien eget mi proin sed. Ut ornare lectus sit amet. Quisque sagittis purus sit amet volutpat consequat mauris nunc. Urna id volutpat lacus laoreet non curabitur gravida arcu. Eu scelerisque felis imperdiet proin fermentum. Porttitor eget dolor morbi non arcu risus quis. Ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. Et malesuada fames ac turpis egestas sed tempus. Aliquam ultrices sagittis orci a scelerisque. Molestie nunc non blandit massa enim nec dui nunc. Diam maecenas sed enim ut sem viverra aliquet eget sit. Amet mattis vulputate enim nulla aliquet porttitor. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget gravida. - -In nulla posuere sollicitudin aliquam ultrices sagittis. Non enim praesent elementum facilisis leo vel fringilla. Fames ac turpis egestas maecenas. Orci dapibus ultrices in iaculis nunc sed augue lacus viverra. Morbi tincidunt ornare massa eget egestas purus viverra. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Sagittis eu volutpat odio facilisis mauris. At augue eget arcu dictum varius. Vitae ultricies leo integer malesuada. Aliquam sem fringilla ut morbi tincidunt augue interdum velit euismod. Dui ut ornare lectus sit amet est placerat in. Habitasse platea dictumst vestibulum rhoncus est. Ut venenatis tellus in metus vulputate eu scelerisque felis imperdiet. Adipiscing bibendum est ultricies integer quis auctor elit sed vulputate. Neque viverra justo nec ultrices dui sapien eget. Vivamus arcu felis bibendum ut. Neque ornare aenean euismod elementum nisi quis eleifend. Morbi tristique senectus et netus. - -Porta nibh venenatis cras sed felis eget velit aliquet. Morbi non arcu risus quis varius quam quisque. Et netus et malesuada fames ac turpis egestas integer. Nisl purus in mollis nunc sed id semper. Porta non pulvinar neque laoreet. Lorem sed risus ultricies tristique nulla aliquet enim tortor. Elit duis tristique sollicitudin nibh sit. Accumsan lacus vel facilisis volutpat est velit egestas. Facilisi morbi tempus iaculis urna. Vestibulum morbi blandit cursus risus at. Ut tellus elementum sagittis vitae. At augue eget arcu dictum varius duis at. Nisi porta lorem mollis aliquam ut porttitor leo a. Gravida cum sociis natoque penatibus. Donec ultrices tincidunt arcu non sodales neque. - -Lacinia at quis risus sed vulputate odio ut enim blandit. Eu feugiat pretium nibh ipsum consequat. Aliquet lectus proin nibh nisl condimentum id venenatis. Felis eget velit aliquet sagittis id consectetur purus ut. Velit aliquet sagittis id consectetur purus ut. Fringilla ut morbi tincidunt augue interdum velit euismod in pellentesque. Egestas pretium aenean pharetra magna ac placerat vestibulum lectus mauris. Sit amet est placerat in egestas erat. Feugiat in ante metus dictum at tempor commodo. Lacus vestibulum sed arcu non odio euismod. Integer vitae justo eget magna fermentum iaculis eu. Proin sed libero enim sed faucibus turpis. - -Iaculis eu non diam phasellus vestibulum lorem sed risus ultricies. Amet venenatis urna cursus eget nunc scelerisque viverra mauris. Vitae auctor eu augue ut lectus arcu bibendum. Purus semper eget duis at tellus at urna condimentum. Massa tincidunt dui ut ornare lectus. Nibh ipsum consequat nisl vel pretium. Amet commodo nulla facilisi nullam. Sem et tortor consequat id porta nibh venenatis. Tincidunt arcu non sodales neque sodales ut. Quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna. - -Porttitor massa id neque aliquam vestibulum morbi. Nunc pulvinar sapien et ligula ullamcorper malesuada. Hendrerit dolor magna eget est lorem. Nulla porttitor massa id neque aliquam vestibulum morbi. Bibendum neque egestas congue quisque. Pellentesque habitant morbi tristique senectus et netus et. Amet risus nullam eget felis eget nunc lobortis mattis. Non enim praesent elementum facilisis leo vel fringilla est. Faucibus et molestie ac feugiat sed lectus. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. Mauris nunc congue nisi vitae suscipit tellus mauris. Varius vel pharetra vel turpis nunc eget lorem dolor. Vitae tempus quam pellentesque nec nam aliquam sem. Feugiat pretium nibh ipsum consequat. Morbi tristique senectus et netus et malesuada. - -Ridiculus mus mauris vitae ultricies leo. Viverra aliquet eget sit amet tellus cras. Id faucibus nisl tincidunt eget nullam non nisi. Pharetra convallis posuere morbi leo urna molestie at. Vulputate odio ut enim blandit volutpat. Vitae et leo duis ut diam quam nulla porttitor massa. Eu non diam phasellus vestibulum lorem sed risus. Dignissim cras tincidunt lobortis feugiat vivamus at augue. In arcu cursus euismod quis viverra nibh. Urna et pharetra pharetra massa massa ultricies. Ut sem nulla pharetra diam sit amet nisl. - -Morbi blandit cursus risus at. Et leo duis ut diam quam nulla porttitor massa. Vestibulum morbi blandit cursus risus. Facilisi nullam vehicula ipsum a arcu cursus. A iaculis at erat pellentesque. Sit amet volutpat consequat mauris nunc congue nisi vitae suscipit. Odio eu feugiat pretium nibh. Dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras. Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc consequat. Nulla pellentesque dignissim enim sit amet venenatis. Turpis egestas sed tempus urna et pharetra. Mi proin sed libero enim. Semper eget duis at tellus at urna condimentum mattis. Integer quis auctor elit sed. - -Amet consectetur adipiscing elit pellentesque habitant morbi tristique. Molestie nunc non blandit massa enim. Sed risus pretium quam vulputate dignissim suspendisse. Iaculis nunc sed augue lacus viverra vitae congue eu. Bibendum neque egestas congue quisque egestas diam. Lacus vestibulum sed arcu non odio euismod lacinia at quis. Aliquet bibendum enim facilisis gravida neque convallis a. Feugiat nibh sed pulvinar proin. Praesent tristique magna sit amet purus gravida quis blandit turpis. In nulla posuere sollicitudin aliquam ultrices. In vitae turpis massa sed elementum tempus egestas sed sed. Sed viverra tellus in hac. Nisl purus in mollis nunc sed id semper. Scelerisque felis imperdiet proin fermentum leo vel. Sed nisi lacus sed viverra tellus in hac. Quisque non tellus orci ac auctor augue mauris augue. Id consectetur purus ut faucibus pulvinar. Id ornare arcu odio ut sem nulla pharetra diam. Accumsan tortor posuere ac ut consequat semper viverra nam. - -Porttitor massa id neque aliquam vestibulum morbi blandit. In nisl nisi scelerisque eu ultrices vitae. Eget gravida cum sociis natoque. Laoreet sit amet cursus sit amet dictum sit amet. Mauris nunc congue nisi vitae suscipit tellus mauris a. Amet consectetur adipiscing elit pellentesque habitant morbi. Sit amet mauris commodo quis imperdiet massa tincidunt. Facilisis mauris sit amet massa vitae tortor condimentum. Varius morbi enim nunc faucibus a pellentesque sit. Fringilla urna porttitor rhoncus dolor purus. Massa tincidunt dui ut ornare lectus. Risus ultricies tristique nulla aliquet enim tortor at auctor urna. Proin nibh nisl condimentum id venenatis a condimentum vitae sapien. Sed id semper risus in hendrerit. Habitant morbi tristique senectus et. - -Sit amet volutpat consequat mauris nunc congue nisi. Mauris nunc congue nisi vitae suscipit tellus. Euismod nisi porta lorem mollis aliquam. Nunc vel risus commodo viverra. Tempus imperdiet nulla malesuada pellentesque elit. Consequat mauris nunc congue nisi. Purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus. Posuere urna nec tincidunt praesent. Ac auctor augue mauris augue neque gravida. Cras ornare arcu dui vivamus arcu felis bibendum ut. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere. Platea dictumst quisque sagittis purus sit. Ac turpis egestas sed tempus urna et pharetra pharetra. Sed pulvinar proin gravida hendrerit lectus a. Pellentesque habitant morbi tristique senectus et netus et malesuada. Elementum curabitur vitae nunc sed velit dignissim sodales ut. Est ultricies integer quis auctor elit sed vulputate mi sit. Tristique magna sit amet purus. - -Vitae elementum curabitur vitae nunc sed velit dignissim sodales. Enim blandit volutpat maecenas volutpat blandit. Dolor sit amet consectetur adipiscing elit duis. Non arcu risus quis varius quam quisque. Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Augue neque gravida in fermentum et sollicitudin ac. Fringilla urna porttitor rhoncus dolor purus non enim. Neque laoreet suspendisse interdum consectetur libero id faucibus nisl tincidunt. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Elementum eu facilisis sed odio morbi quis commodo odio aenean. Sem et tortor consequat id porta nibh venenatis. Pulvinar mattis nunc sed blandit. Justo donec enim diam vulputate ut pharetra. - -Mus mauris vitae ultricies leo integer malesuada nunc. Diam maecenas sed enim ut sem viverra. Est ullamcorper eget nulla facilisi etiam dignissim. Vel risus commodo viverra maecenas accumsan lacus vel facilisis. Neque sodales ut etiam sit amet nisl purus. Ut faucibus pulvinar elementum integer. Leo duis ut diam quam nulla porttitor massa id. Tempor orci dapibus ultrices in iaculis nunc sed. Ligula ullamcorper malesuada proin libero nunc consequat interdum varius. Diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Amet justo donec enim diam vulputate. Suspendisse potenti nullam ac tortor vitae purus. In vitae turpis massa sed elementum tempus. - -Congue quisque egestas diam in arcu cursus euismod. In eu mi bibendum neque egestas congue quisque. Vitae suscipit tellus mauris a diam. Purus non enim praesent elementum facilisis leo. Tristique magna sit amet purus gravida quis blandit turpis cursus. Ut tellus elementum sagittis vitae et leo. Amet facilisis magna etiam tempor orci eu lobortis elementum nibh. Ut sem nulla pharetra diam sit amet nisl suscipit adipiscing. Vivamus arcu felis bibendum ut. Euismod quis viverra nibh cras pulvinar mattis nunc. Non sodales neque sodales ut. Eros in cursus turpis massa tincidunt. Vitae auctor eu augue ut lectus. Phasellus faucibus scelerisque eleifend donec pretium vulputate. Arcu dictum varius duis at consectetur lorem donec massa. Iaculis urna id volutpat lacus laoreet. Pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Interdum consectetur libero id faucibus nisl. - -Tempus iaculis urna id volutpat lacus laoreet. Natoque penatibus et magnis dis. Donec et odio pellentesque diam volutpat commodo. Tempor commodo ullamcorper a lacus vestibulum. Sed viverra tellus in hac habitasse. At tellus at urna condimentum mattis pellentesque id nibh. Sed blandit libero volutpat sed cras ornare. Neque sodales ut etiam sit amet. At erat pellentesque adipiscing commodo elit at imperdiet. Iaculis nunc sed augue lacus viverra vitae congue eu consequat. Duis at consectetur lorem donec massa sapien faucibus. Sit amet facilisis magna etiam. Nascetur ridiculus mus mauris vitae ultricies. Et leo duis ut diam. - -Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. Aenean sed adipiscing diam donec adipiscing tristique risus nec feugiat. Duis convallis convallis tellus id interdum velit laoreet. Mauris a diam maecenas sed. Nec tincidunt praesent semper feugiat nibh sed pulvinar. Enim nec dui nunc mattis. Elit at imperdiet dui accumsan sit amet nulla facilisi. Non tellus orci ac auctor augue. Habitasse platea dictumst vestibulum rhoncus est. - -Bibendum neque egestas congue quisque egestas diam. Diam phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet. Tempus quam pellentesque nec nam aliquam sem et tortor consequat. Et malesuada fames ac turpis egestas. Mauris nunc congue nisi vitae suscipit tellus mauris a. Sed risus ultricies tristique nulla aliquet enim tortor at. Semper auctor neque vitae tempus quam pellentesque nec nam. Vulputate eu scelerisque felis imperdiet proin. Et ligula ullamcorper malesuada proin libero nunc consequat. Nisl nunc mi ipsum faucibus vitae aliquet. Iaculis urna id volutpat lacus laoreet non curabitur gravida. Ultricies tristique nulla aliquet enim tortor. Ut etiam sit amet nisl purus in mollis. Elementum eu facilisis sed odio morbi. Massa placerat duis ultricies lacus sed turpis. A pellentesque sit amet porttitor eget dolor morbi. Purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus. Lacus viverra vitae congue eu consequat. Velit egestas dui id ornare arcu odio. Urna porttitor rhoncus dolor purus non enim praesent. - -Felis bibendum ut tristique et egestas quis ipsum suspendisse. Nec ultrices dui sapien eget mi proin sed. Egestas congue quisque egestas diam in arcu cursus euismod quis. Egestas sed sed risus pretium quam vulputate dignissim suspendisse. Gravida arcu ac tortor dignissim convallis. Arcu felis bibendum ut tristique. Libero volutpat sed cras ornare arcu dui vivamus arcu felis. Tempus urna et pharetra pharetra massa massa ultricies mi quis. Commodo nulla facilisi nullam vehicula ipsum a arcu. Volutpat ac tincidunt vitae semper quis lectus. Pellentesque nec nam aliquam sem et tortor consequat id porta. Pellentesque dignissim enim sit amet venenatis urna cursus. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat in. Nec ultrices dui sapien eget mi proin sed libero. Ac odio tempor orci dapibus ultrices in. Quis blandit turpis cursus in hac habitasse platea dictumst quisque. Hendrerit dolor magna eget est lorem ipsum dolor. Quis viverra nibh cras pulvinar. - -Semper auctor neque vitae tempus quam pellentesque. Arcu non odio euismod lacinia. Neque vitae tempus quam pellentesque. In nulla posuere sollicitudin aliquam ultrices sagittis orci. Habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Aliquet eget sit amet tellus cras adipiscing. Eget duis at tellus at urna. Est ullamcorper eget nulla facilisi. Urna duis convallis convallis tellus id interdum velit laoreet id. Nec ullamcorper sit amet risus nullam eget felis. Faucibus ornare suspendisse sed nisi lacus sed. Ipsum consequat nisl vel pretium lectus. Imperdiet sed euismod nisi porta lorem. Nunc pulvinar sapien et ligula ullamcorper malesuada proin libero nunc. Risus quis varius quam quisque id diam. In massa tempor nec feugiat nisl pretium fusce id velit. - -Sed vulputate odio ut enim blandit volutpat maecenas. Malesuada fames ac turpis egestas integer eget aliquet nibh. Ipsum consequat nisl vel pretium lectus. Aliquam nulla facilisi cras fermentum odio eu. In cursus turpis massa tincidunt dui ut ornare. Ultrices dui sapien eget mi proin sed libero enim sed. Malesuada bibendum arcu vitae elementum. Id neque aliquam vestibulum morbi blandit. Facilisi cras fermentum odio eu feugiat. Etiam erat velit scelerisque in dictum non consectetur a erat. Faucibus nisl tincidunt eget nullam non. Non nisi est sit amet facilisis magna etiam. Sed sed risus pretium quam vulputate dignissim suspendisse in est. Cursus risus at ultrices mi tempus imperdiet. Non pulvinar neque laoreet suspendisse. Id diam vel quam elementum pulvinar etiam non quam lacus. Habitant morbi tristique senectus et. - -In egestas erat imperdiet sed euismod nisi porta lorem. Massa sapien faucibus et molestie ac feugiat. Erat imperdiet sed euismod nisi. Semper feugiat nibh sed pulvinar proin. Ut faucibus pulvinar elementum integer enim neque volutpat ac tincidunt. Urna neque viverra justo nec ultrices dui sapien eget. Malesuada pellentesque elit eget gravida cum sociis. Amet massa vitae tortor condimentum lacinia quis vel eros donec. In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Aenean pharetra magna ac placerat. Dictum at tempor commodo ullamcorper a lacus vestibulum. Egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. Convallis aenean et tortor at risus. Ultricies leo integer malesuada nunc. Suscipit tellus mauris a diam. Lorem ipsum dolor sit amet consectetur adipiscing. Duis at tellus at urna condimentum mattis pellentesque id. Nisi quis eleifend quam adipiscing vitae. Orci dapibus ultrices in iaculis nunc sed. - -Ut aliquam purus sit amet luctus venenatis lectus magna fringilla. Eget nullam non nisi est. Urna duis convallis convallis tellus id interdum. In nisl nisi scelerisque eu ultrices vitae auctor. Facilisis gravida neque convallis a cras semper auctor neque vitae. Purus sit amet volutpat consequat mauris nunc congue. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Ut tellus elementum sagittis vitae et leo. Sit amet est placerat in egestas. Nam aliquam sem et tortor consequat id. Elementum eu facilisis sed odio. - -Sit amet est placerat in. Viverra vitae congue eu consequat. Dui accumsan sit amet nulla. Vitae suscipit tellus mauris a diam. Et netus et malesuada fames ac turpis egestas. Quisque id diam vel quam elementum pulvinar etiam. Sit amet mattis vulputate enim. Praesent tristique magna sit amet. At ultrices mi tempus imperdiet nulla malesuada pellentesque elit. Tellus elementum sagittis vitae et. Cursus risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Quis viverra nibh cras pulvinar mattis. Convallis tellus id interdum velit laoreet. - -Bibendum est ultricies integer quis auctor elit sed vulputate. Elit sed vulputate mi sit amet mauris commodo quis. Faucibus et molestie ac feugiat sed lectus vestibulum mattis. Nullam vehicula ipsum a arcu cursus vitae congue mauris rhoncus. Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Sem viverra aliquet eget sit amet tellus cras adipiscing enim. Leo urna molestie at elementum eu facilisis sed. Congue nisi vitae suscipit tellus mauris a diam maecenas. Hendrerit gravida rutrum quisque non tellus. Fames ac turpis egestas maecenas pharetra convallis posuere. Odio morbi quis commodo odio aenean sed adipiscing diam. - -Sit amet justo donec enim diam vulputate ut pharetra. Porta nibh venenatis cras sed felis eget velit aliquet. Cras fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Mi proin sed libero enim sed faucibus. Leo in vitae turpis massa sed elementum tempus. Euismod in pellentesque massa placerat duis ultricies. Dictum at tempor commodo ullamcorper a lacus vestibulum. Magna fringilla urna porttitor rhoncus dolor purus non enim praesent. Odio tempor orci dapibus ultrices in iaculis. Massa vitae tortor condimentum lacinia quis vel eros. Urna neque viverra justo nec ultrices dui. Tristique nulla aliquet enim tortor. - -Tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Facilisi morbi tempus iaculis urna id volutpat lacus. Metus aliquam eleifend mi in. Elementum integer enim neque volutpat ac tincidunt. Pellentesque dignissim enim sit amet venenatis. Quam viverra orci sagittis eu volutpat odio facilisis mauris sit. Lacus viverra vitae congue eu consequat ac felis donec et. Id interdum velit laoreet id. Arcu cursus euismod quis viverra nibh cras. Tincidunt ornare massa eget egestas purus viverra accumsan in. Justo eget magna fermentum iaculis eu non diam. Est ultricies integer quis auctor. - -Enim facilisis gravida neque convallis a cras semper. Vitae auctor eu augue ut. Id aliquet risus feugiat in. Enim lobortis scelerisque fermentum dui faucibus in. Integer quis auctor elit sed vulputate mi sit. Nulla aliquet enim tortor at auctor urna nunc id. Nascetur ridiculus mus mauris vitae ultricies leo integer. Non curabitur gravida arcu ac tortor dignissim. Vel fringilla est ullamcorper eget nulla facilisi etiam. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna. Nunc aliquet bibendum enim facilisis gravida. Sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis. Nunc lobortis mattis aliquam faucibus purus in. Massa sed elementum tempus egestas sed sed risus. Risus viverra adipiscing at in tellus integer feugiat scelerisque varius. Id ornare arcu odio ut sem nulla pharetra. Quis viverra nibh cras pulvinar mattis nunc. - -Rutrum quisque non tellus orci ac auctor augue mauris. Ipsum nunc aliquet bibendum enim. Dictum at tempor commodo ullamcorper a lacus vestibulum sed arcu. Montes nascetur ridiculus mus mauris vitae ultricies leo integer. Id velit ut tortor pretium viverra suspendisse potenti. Eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Mauris pharetra et ultrices neque ornare aenean euismod. Aliquet porttitor lacus luctus accumsan tortor. Netus et malesuada fames ac turpis. Neque convallis a cras semper auctor neque. Vestibulum sed arcu non odio euismod lacinia at. Libero enim sed faucibus turpis in eu. Elit ut aliquam purus sit amet. Id velit ut tortor pretium viverra suspendisse potenti nullam ac. Aliquam ut porttitor leo a diam sollicitudin. Quam quisque id diam vel. Commodo viverra maecenas accumsan lacus vel facilisis. Porta lorem mollis aliquam ut porttitor leo a. Vitae sapien pellentesque habitant morbi tristique senectus et. Non odio euismod lacinia at quis risus sed vulputate odio. - -Faucibus scelerisque eleifend donec pretium vulputate sapien nec. Amet luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. Ac felis donec et odio. Scelerisque purus semper eget duis at tellus at urna condimentum. Maecenas volutpat blandit aliquam etiam erat velit scelerisque in dictum. Facilisi morbi tempus iaculis urna id. In vitae turpis massa sed elementum tempus. Nulla facilisi morbi tempus iaculis urna id volutpat lacus laoreet. At tellus at urna condimentum mattis pellentesque id nibh. Pharetra vel turpis nunc eget lorem dolor sed viverra ipsum. Commodo quis imperdiet massa tincidunt. Augue eget arcu dictum varius duis at consectetur lorem donec. Adipiscing at in tellus integer feugiat scelerisque varius. Nibh mauris cursus mattis molestie a. Neque viverra justo nec ultrices. Morbi tristique senectus et netus et malesuada. Dui faucibus in ornare quam viverra orci sagittis. Risus pretium quam vulputate dignissim suspendisse. Nunc congue nisi vitae suscipit tellus. - -Pellentesque adipiscing commodo elit at imperdiet dui accumsan. Amet mauris commodo quis imperdiet. Nisl tincidunt eget nullam non nisi est sit amet facilisis. Montes nascetur ridiculus mus mauris. Orci dapibus ultrices in iaculis. Facilisi etiam dignissim diam quis enim lobortis scelerisque. Consequat ac felis donec et. Fames ac turpis egestas sed tempus. In ante metus dictum at tempor commodo. Viverra orci sagittis eu volutpat odio facilisis mauris sit. Donec enim diam vulputate ut pharetra sit amet. Pretium lectus quam id leo in vitae turpis. Aliquam sem fringilla ut morbi tincidunt. Ultricies tristique nulla aliquet enim tortor. Neque egestas congue quisque egestas diam in. Ultrices in iaculis nunc sed augue. Ultricies mi eget mauris pharetra. Eget sit amet tellus cras adipiscing. Lectus proin nibh nisl condimentum id venenatis. Quis ipsum suspendisse ultrices gravida dictum. - -Risus viverra adipiscing at in tellus integer feugiat scelerisque varius. Ut consequat semper viverra nam libero. Rutrum tellus pellentesque eu tincidunt tortor aliquam nulla facilisi. Egestas quis ipsum suspendisse ultrices gravida dictum. Orci nulla pellentesque dignissim enim sit amet venenatis. Pellentesque nec nam aliquam sem et tortor. Tortor posuere ac ut consequat. Amet nisl suscipit adipiscing bibendum est. Egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Varius sit amet mattis vulputate enim. Fames ac turpis egestas maecenas pharetra convallis posuere morbi. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Sodales ut eu sem integer vitae justo eget magna. - -Rhoncus urna neque viverra justo nec ultrices. Dui ut ornare lectus sit amet est placerat in. Dui ut ornare lectus sit amet. Erat velit scelerisque in dictum non. Cras tincidunt lobortis feugiat vivamus at augue eget. Augue ut lectus arcu bibendum at varius vel pharetra. Et tortor consequat id porta nibh. Mauris a diam maecenas sed. Venenatis a condimentum vitae sapien pellentesque habitant morbi tristique senectus. Lorem dolor sed viverra ipsum nunc aliquet bibendum. Mi quis hendrerit dolor magna. Faucibus scelerisque eleifend donec pretium. Risus nec feugiat in fermentum posuere urna. Odio euismod lacinia at quis risus. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. Ac tincidunt vitae semper quis lectus. - -Non diam phasellus vestibulum lorem sed risus ultricies tristique. Tristique senectus et netus et malesuada fames ac. Urna cursus eget nunc scelerisque viverra. Dui vivamus arcu felis bibendum ut tristique et egestas. Sapien nec sagittis aliquam malesuada bibendum arcu. Est ullamcorper eget nulla facilisi etiam dignissim. Mi eget mauris pharetra et ultrices neque. Blandit cursus risus at ultrices mi tempus imperdiet. Sem viverra aliquet eget sit amet tellus. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis. Fermentum posuere urna nec tincidunt. Commodo nulla facilisi nullam vehicula ipsum a. Mi ipsum faucibus vitae aliquet nec. At tellus at urna condimentum mattis pellentesque id nibh. - -Nisl rhoncus mattis rhoncus urna neque. Vulputate ut pharetra sit amet aliquam id. Nulla aliquet enim tortor at auctor urna nunc id. Semper viverra nam libero justo laoreet sit amet. Vel quam elementum pulvinar etiam non quam. Non arcu risus quis varius quam quisque id. Viverra vitae congue eu consequat ac felis donec et. Quis lectus nulla at volutpat diam ut venenatis tellus in. Vel pharetra vel turpis nunc eget lorem. Nisl rhoncus mattis rhoncus urna neque viverra justo nec ultrices. Pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at. Lorem ipsum dolor sit amet. Nisi vitae suscipit tellus mauris. Faucibus a pellentesque sit amet porttitor eget. Cursus sit amet dictum sit amet justo. - -Ultricies leo integer malesuada nunc vel. Mattis nunc sed blandit libero volutpat sed cras ornare arcu. In metus vulputate eu scelerisque felis. Vitae congue mauris rhoncus aenean. Id aliquet risus feugiat in ante. Quis lectus nulla at volutpat diam ut venenatis tellus in. Sed felis eget velit aliquet. Sagittis vitae et leo duis ut. Morbi tristique senectus et netus et malesuada. Nulla facilisi cras fermentum odio eu feugiat pretium. Et egestas quis ipsum suspendisse ultrices gravida dictum. Velit dignissim sodales ut eu sem integer vitae justo eget. Natoque penatibus et magnis dis parturient montes. Viverra vitae congue eu consequat ac felis. Congue quisque egestas diam in. Cursus risus at ultrices mi tempus imperdiet nulla malesuada. Tellus elementum sagittis vitae et leo duis ut diam. Vel facilisis volutpat est velit egestas dui id. Cursus in hac habitasse platea dictumst quisque sagittis purus sit. Adipiscing enim eu turpis egestas. - -Nullam non nisi est sit amet facilisis magna etiam tempor. Tortor dignissim convallis aenean et tortor at risus viverra adipiscing. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan. Eu mi bibendum neque egestas congue quisque egestas diam. Venenatis urna cursus eget nunc scelerisque. Eu ultrices vitae auctor eu augue. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. Et netus et malesuada fames ac turpis egestas. Imperdiet dui accumsan sit amet. Amet massa vitae tortor condimentum. Dolor sit amet consectetur adipiscing elit pellentesque. - -Dui faucibus in ornare quam viverra. Ridiculus mus mauris vitae ultricies. Id leo in vitae turpis massa sed elementum tempus. Interdum varius sit amet mattis vulputate enim nulla. Mattis rhoncus urna neque viverra justo nec. Urna condimentum mattis pellentesque id nibh tortor id aliquet lectus. Egestas sed sed risus pretium quam. Et molestie ac feugiat sed. Elementum facilisis leo vel fringilla est ullamcorper eget nulla. Ultricies tristique nulla aliquet enim tortor at. Sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis. Est ultricies integer quis auctor elit sed vulputate mi. Proin sed libero enim sed faucibus. - -Faucibus nisl tincidunt eget nullam non nisi. Et netus et malesuada fames ac turpis egestas. Eget velit aliquet sagittis id consectetur purus ut faucibus. Risus nec feugiat in fermentum posuere urna nec tincidunt praesent. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque. Vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Vulputate sapien nec sagittis aliquam malesuada bibendum. Tincidunt tortor aliquam nulla facilisi cras fermentum odio eu feugiat. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum. Velit ut tortor pretium viverra suspendisse potenti nullam ac. Nunc scelerisque viverra mauris in aliquam sem. Egestas tellus rutrum tellus pellentesque eu tincidunt. Lectus quam id leo in vitae turpis massa. - -Risus nec feugiat in fermentum posuere urna nec. Euismod lacinia at quis risus. Pretium vulputate sapien nec sagittis aliquam malesuada bibendum. Ut lectus arcu bibendum at varius vel pharetra. Laoreet non curabitur gravida arcu ac tortor dignissim convallis. Morbi enim nunc faucibus a pellentesque sit. Suspendisse faucibus interdum posuere lorem ipsum dolor. Dui id ornare arcu odio. Eu nisl nunc mi ipsum. Interdum velit laoreet id donec ultrices tincidunt arcu non sodales. Velit sed ullamcorper morbi tincidunt. Eros donec ac odio tempor orci dapibus ultrices. Curabitur gravida arcu ac tortor dignissim convallis aenean. Eget nullam non nisi est. Egestas diam in arcu cursus euismod. Aenean et tortor at risus viverra adipiscing at in tellus. Morbi tristique senectus et netus et malesuada fames ac turpis. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. - -Aliquam id diam maecenas ultricies mi eget mauris pharetra. Id aliquet risus feugiat in ante. Ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Morbi tincidunt augue interdum velit euismod in. Quis vel eros donec ac odio tempor orci dapibus ultrices. Consequat interdum varius sit amet mattis vulputate enim nulla aliquet. Sem nulla pharetra diam sit amet. Mi eget mauris pharetra et ultrices neque ornare aenean. At tellus at urna condimentum mattis pellentesque id nibh tortor. Faucibus ornare suspendisse sed nisi lacus sed viverra tellus. Sit amet aliquam id diam maecenas ultricies mi. - -Arcu felis bibendum ut tristique et egestas. Ornare suspendisse sed nisi lacus sed viverra. Cursus turpis massa tincidunt dui ut. Ultrices sagittis orci a scelerisque. Vulputate mi sit amet mauris. Dignissim suspendisse in est ante. Elementum tempus egestas sed sed risus pretium. Ut venenatis tellus in metus vulputate eu scelerisque felis imperdiet. Faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam. Tempus egestas sed sed risus pretium quam. Magna sit amet purus gravida quis blandit turpis. Auctor augue mauris augue neque gravida in fermentum et. Ornare quam viverra orci sagittis. Amet porttitor eget dolor morbi non arcu risus. Egestas pretium aenean pharetra magna ac placerat vestibulum. - -Egestas sed tempus urna et pharetra pharetra massa. Massa placerat duis ultricies lacus sed turpis. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Massa ultricies mi quis hendrerit dolor. Venenatis a condimentum vitae sapien pellentesque habitant morbi. Luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. Pellentesque habitant morbi tristique senectus et netus et. Ac turpis egestas sed tempus. Ullamcorper a lacus vestibulum sed arcu non odio euismod. Felis eget velit aliquet sagittis id consectetur purus. Proin sagittis nisl rhoncus mattis rhoncus urna. Et molestie ac feugiat sed lectus vestibulum. Vel turpis nunc eget lorem. Et magnis dis parturient montes nascetur ridiculus mus. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. Volutpat diam ut venenatis tellus in metus vulputate eu. Netus et malesuada fames ac turpis egestas integer. - -Auctor elit sed vulputate mi sit amet mauris. Dui ut ornare lectus sit amet est placerat in egestas. Faucibus nisl tincidunt eget nullam non. Leo integer malesuada nunc vel risus commodo. Quam viverra orci sagittis eu volutpat odio facilisis mauris sit. Consequat ac felis donec et odio. Lorem ipsum dolor sit amet consectetur adipiscing. Sapien eget mi proin sed libero enim sed faucibus. Ut tristique et egestas quis ipsum suspendisse ultrices gravida dictum. Cursus eget nunc scelerisque viverra mauris in aliquam sem. Tortor aliquam nulla facilisi cras fermentum odio eu feugiat pretium. Bibendum enim facilisis gravida neque convallis a cras. Porttitor massa id neque aliquam vestibulum. Vel fringilla est ullamcorper eget nulla. - -Ac feugiat sed lectus vestibulum mattis ullamcorper velit. Nec tincidunt praesent semper feugiat. Mattis pellentesque id nibh tortor. Sem nulla pharetra diam sit amet nisl suscipit adipiscing. Sit amet aliquam id diam. Orci porta non pulvinar neque laoreet suspendisse. Cursus euismod quis viverra nibh cras. Cursus in hac habitasse platea dictumst quisque sagittis purus sit. Tortor at auctor urna nunc id cursus. Posuere sollicitudin aliquam ultrices sagittis orci. Nisl condimentum id venenatis a. Nulla facilisi cras fermentum odio eu feugiat. Pulvinar mattis nunc sed blandit libero volutpat sed. Maecenas pharetra convallis posuere morbi. Enim sed faucibus turpis in eu mi bibendum. Viverra tellus in hac habitasse. Ante in nibh mauris cursus mattis molestie a iaculis. Ornare arcu odio ut sem. Dui ut ornare lectus sit amet est placerat in. - -Et netus et malesuada fames ac turpis egestas sed. A scelerisque purus semper eget duis. Rhoncus dolor purus non enim praesent elementum facilisis leo vel. Nisl rhoncus mattis rhoncus urna neque viverra justo nec ultrices. Habitant morbi tristique senectus et netus et. Pellentesque diam volutpat commodo sed egestas. Purus faucibus ornare suspendisse sed. Mauris nunc congue nisi vitae suscipit tellus. Semper quis lectus nulla at. Vel orci porta non pulvinar. Magna ac placerat vestibulum lectus mauris. Vitae sapien pellentesque habitant morbi. Convallis aenean et tortor at risus viverra adipiscing at in. At lectus urna duis convallis convallis tellus id. Scelerisque felis imperdiet proin fermentum. Eu facilisis sed odio morbi quis commodo odio aenean sed. Adipiscing elit ut aliquam purus sit. - -Enim ut sem viverra aliquet eget sit. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Nunc aliquet bibendum enim facilisis gravida. Tristique sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus. Augue interdum velit euismod in pellentesque massa placerat duis ultricies. Volutpat diam ut venenatis tellus in. Sed euismod nisi porta lorem mollis aliquam ut porttitor leo. Et egestas quis ipsum suspendisse ultrices. Massa tincidunt nunc pulvinar sapien et ligula. A diam maecenas sed enim ut sem viverra. Sem fringilla ut morbi tincidunt augue interdum velit euismod. Arcu cursus euismod quis viverra nibh cras. Vel eros donec ac odio tempor orci dapibus. Eu non diam phasellus vestibulum lorem sed risus ultricies. Senectus et netus et malesuada fames ac turpis egestas. Consectetur adipiscing elit ut aliquam purus sit amet luctus. - -Eu scelerisque felis imperdiet proin fermentum leo vel. Tincidunt dui ut ornare lectus sit. Fames ac turpis egestas maecenas pharetra. Risus quis varius quam quisque id. Praesent tristique magna sit amet purus gravida quis blandit. Morbi tristique senectus et netus et. Turpis in eu mi bibendum neque egestas congue. Elementum integer enim neque volutpat ac tincidunt. Porta nibh venenatis cras sed felis. Nibh tortor id aliquet lectus proin. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Eget gravida cum sociis natoque penatibus et. Sem fringilla ut morbi tincidunt augue interdum velit euismod in. Elit ut aliquam purus sit amet. Penatibus et magnis dis parturient montes nascetur ridiculus. Turpis nunc eget lorem dolor sed viverra ipsum nunc aliquet. Pulvinar mattis nunc sed blandit. Hendrerit dolor magna eget est lorem ipsum dolor sit amet. - -Duis at consectetur lorem donec massa sapien. Eu ultrices vitae auctor eu augue. Dui sapien eget mi proin sed libero. Egestas tellus rutrum tellus pellentesque eu tincidunt. Ut tristique et egestas quis ipsum. Iaculis nunc sed augue lacus viverra. Enim facilisis gravida neque convallis. Nunc lobortis mattis aliquam faucibus purus. Sed felis eget velit aliquet sagittis. Ultricies integer quis auctor elit sed vulputate mi. Orci ac auctor augue mauris augue neque gravida in. Luctus accumsan tortor posuere ac ut consequat semper viverra nam. Nunc non blandit massa enim. Lacus sed turpis tincidunt id aliquet risus. - -Blandit volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque. Commodo elit at imperdiet dui accumsan sit amet nulla. Odio aenean sed adipiscing diam donec adipiscing tristique risus nec. Egestas dui id ornare arcu odio ut sem nulla. Natoque penatibus et magnis dis parturient montes. Odio ut sem nulla pharetra diam sit amet nisl. Magna sit amet purus gravida quis blandit turpis. Nisl tincidunt eget nullam non nisi est. Faucibus et molestie ac feugiat sed lectus. Dapibus ultrices in iaculis nunc sed augue lacus viverra. Dignissim cras tincidunt lobortis feugiat vivamus at augue. - -Auctor neque vitae tempus quam. Ultrices neque ornare aenean euismod elementum. Facilisis leo vel fringilla est ullamcorper eget. Et leo duis ut diam quam nulla porttitor. Sit amet nisl suscipit adipiscing bibendum. Cursus euismod quis viverra nibh cras pulvinar mattis. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam quis. Sit amet venenatis urna cursus eget nunc scelerisque viverra mauris. Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula ipsum. Tristique magna sit amet purus gravida quis blandit turpis. - -Mauris a diam maecenas sed enim ut sem. Iaculis at erat pellentesque adipiscing commodo elit. Sit amet facilisis magna etiam tempor. Quam id leo in vitae turpis. Odio aenean sed adipiscing diam donec adipiscing tristique. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. Tortor id aliquet lectus proin nibh nisl condimentum id. Commodo quis imperdiet massa tincidunt. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque. Urna condimentum mattis pellentesque id. Tempus urna et pharetra pharetra massa massa ultricies mi quis. Luctus venenatis lectus magna fringilla urna. Id diam maecenas ultricies mi eget mauris pharetra et. - -Morbi tristique senectus et netus. Pellentesque habitant morbi tristique senectus et netus. Accumsan sit amet nulla facilisi morbi tempus iaculis. Volutpat est velit egestas dui. Egestas diam in arcu cursus euismod quis viverra. Libero id faucibus nisl tincidunt. Parturient montes nascetur ridiculus mus. Quis ipsum suspendisse ultrices gravida dictum fusce ut placerat orci. Venenatis tellus in metus vulputate eu scelerisque. Volutpat blandit aliquam etiam erat. Turpis massa tincidunt dui ut ornare lectus sit amet. Feugiat nibh sed pulvinar proin gravida hendrerit lectus. Nisi est sit amet facilisis magna etiam tempor. Commodo quis imperdiet massa tincidunt. Pretium lectus quam id leo in vitae turpis massa sed. Tellus in hac habitasse platea dictumst vestibulum rhoncus est. Vel orci porta non pulvinar neque. Egestas integer eget aliquet nibh praesent. - -Eget magna fermentum iaculis eu. Viverra tellus in hac habitasse platea. Ac odio tempor orci dapibus ultrices in iaculis. Vitae aliquet nec ullamcorper sit amet risus nullam eget. Molestie a iaculis at erat. Sed arcu non odio euismod lacinia at. Purus semper eget duis at tellus. Aliquam id diam maecenas ultricies. At in tellus integer feugiat scelerisque. Maecenas volutpat blandit aliquam etiam erat velit. Adipiscing elit ut aliquam purus sit amet. Diam donec adipiscing tristique risus nec feugiat in. Lectus urna duis convallis convallis tellus. Viverra aliquet eget sit amet tellus cras adipiscing enim. Venenatis tellus in metus vulputate eu scelerisque. Orci sagittis eu volutpat odio facilisis mauris. Tincidunt dui ut ornare lectus sit amet est placerat in. Nec sagittis aliquam malesuada bibendum. - -Fermentum iaculis eu non diam phasellus vestibulum lorem sed. Metus dictum at tempor commodo. Sit amet porttitor eget dolor morbi non arcu risus. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at augue. Semper risus in hendrerit gravida rutrum quisque non tellus orci. Dignissim diam quis enim lobortis scelerisque fermentum. Ultricies mi eget mauris pharetra. Porta non pulvinar neque laoreet suspendisse interdum consectetur libero id. Purus ut faucibus pulvinar elementum integer enim neque volutpat ac. Nibh ipsum consequat nisl vel pretium lectus quam id leo. Dolor purus non enim praesent elementum facilisis leo vel. - -Et malesuada fames ac turpis egestas maecenas pharetra convallis. In pellentesque massa placerat duis ultricies lacus sed turpis. Libero justo laoreet sit amet cursus. Integer malesuada nunc vel risus. Nunc sed id semper risus in hendrerit gravida rutrum. Volutpat lacus laoreet non curabitur gravida arcu. Duis ut diam quam nulla porttitor massa id neque aliquam. Vitae aliquet nec ullamcorper sit amet risus nullam eget felis. Pulvinar neque laoreet suspendisse interdum consectetur libero. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Adipiscing diam donec adipiscing tristique risus nec feugiat. Vitae purus faucibus ornare suspendisse sed nisi lacus sed. Vulputate ut pharetra sit amet. Lacus sed turpis tincidunt id aliquet risus feugiat in. Sed egestas egestas fringilla phasellus. Quis lectus nulla at volutpat diam. Aliquam faucibus purus in massa tempor nec feugiat. Amet mattis vulputate enim nulla aliquet. Eget sit amet tellus cras adipiscing enim. - -Nisl suscipit adipiscing bibendum est ultricies integer. Mattis aliquam faucibus purus in massa. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices. Eu augue ut lectus arcu bibendum. Duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Lobortis feugiat vivamus at augue eget arcu dictum. Vel elit scelerisque mauris pellentesque. Id aliquet lectus proin nibh nisl condimentum id venenatis a. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. In ante metus dictum at. Varius vel pharetra vel turpis. - -Placerat in egestas erat imperdiet sed euismod. Vitae sapien pellentesque habitant morbi tristique senectus et netus. Nulla posuere sollicitudin aliquam ultrices sagittis. Maecenas accumsan lacus vel facilisis volutpat. Convallis convallis tellus id interdum velit. Habitant morbi tristique senectus et netus et malesuada. Ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae. Justo eget magna fermentum iaculis. Nulla facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum. Gravida neque convallis a cras semper auctor neque. Mattis rhoncus urna neque viverra. Pellentesque habitant morbi tristique senectus. Vitae et leo duis ut diam quam nulla porttitor massa. Natoque penatibus et magnis dis parturient montes nascetur ridiculus. Turpis massa tincidunt dui ut ornare lectus sit. Tempor orci eu lobortis elementum nibh tellus molestie nunc non. Nisl nunc mi ipsum faucibus vitae aliquet nec. Feugiat scelerisque varius morbi enim nunc faucibus. Id aliquet risus feugiat in. - -Dictum sit amet justo donec enim diam. Augue interdum velit euismod in pellentesque massa placerat duis ultricies. Tristique senectus et netus et malesuada fames. Diam ut venenatis tellus in metus vulputate. Sagittis vitae et leo duis ut diam quam nulla. Vitae ultricies leo integer malesuada. Tellus in metus vulputate eu scelerisque felis imperdiet. Leo vel fringilla est ullamcorper eget. Venenatis a condimentum vitae sapien. A lacus vestibulum sed arcu non odio euismod lacinia. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Quam vulputate dignissim suspendisse in est ante in nibh. Duis tristique sollicitudin nibh sit. Diam phasellus vestibulum lorem sed. Ultrices neque ornare aenean euismod. Vel eros donec ac odio tempor orci dapibus ultrices in. Sit amet justo donec enim diam vulputate ut pharetra sit. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Eu scelerisque felis imperdiet proin fermentum leo vel orci. Sit amet volutpat consequat mauris nunc congue nisi. - -Tincidunt id aliquet risus feugiat in ante metus dictum at. Platea dictumst quisque sagittis purus sit. Ullamcorper a lacus vestibulum sed arcu non odio. Pharetra sit amet aliquam id diam maecenas. Metus aliquam eleifend mi in. Egestas quis ipsum suspendisse ultrices gravida dictum fusce ut. Varius duis at consectetur lorem donec massa. Dis parturient montes nascetur ridiculus. Amet massa vitae tortor condimentum. Est placerat in egestas erat imperdiet sed euismod nisi. Nunc non blandit massa enim nec dui. - -Adipiscing at in tellus integer feugiat scelerisque varius. Eu sem integer vitae justo eget magna. Sit amet tellus cras adipiscing enim eu turpis egestas pretium. Massa sed elementum tempus egestas sed. Sit amet porttitor eget dolor. Porta non pulvinar neque laoreet suspendisse. Ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae. Iaculis urna id volutpat lacus laoreet non curabitur. Semper auctor neque vitae tempus quam. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. - -Non odio euismod lacinia at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Lobortis feugiat vivamus at augue eget. Orci a scelerisque purus semper eget duis at. Ut enim blandit volutpat maecenas volutpat blandit. Netus et malesuada fames ac turpis egestas. Scelerisque viverra mauris in aliquam sem fringilla. Dolor magna eget est lorem ipsum. Donec ac odio tempor orci dapibus. Cras sed felis eget velit aliquet sagittis id. Nam at lectus urna duis convallis. - -Quis enim lobortis scelerisque fermentum dui faucibus. Pulvinar pellentesque habitant morbi tristique senectus et netus et. In pellentesque massa placerat duis ultricies lacus. Nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Integer malesuada nunc vel risus. Faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Aliquam nulla facilisi cras fermentum odio. Feugiat pretium nibh ipsum consequat nisl vel. Ornare quam viverra orci sagittis eu volutpat. Enim nulla aliquet porttitor lacus. Nulla at volutpat diam ut venenatis. Vestibulum lorem sed risus ultricies tristique nulla. Id leo in vitae turpis massa sed elementum tempus. Sed risus pretium quam vulputate dignissim suspendisse. - -Semper quis lectus nulla at volutpat diam ut venenatis. Sit amet risus nullam eget felis eget nunc lobortis mattis. Fermentum posuere urna nec tincidunt. Ut sem nulla pharetra diam sit amet nisl suscipit. Sit amet massa vitae tortor condimentum. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Urna condimentum mattis pellentesque id nibh tortor id. Interdum posuere lorem ipsum dolor sit amet consectetur. Odio euismod lacinia at quis risus sed vulputate odio ut. Mollis aliquam ut porttitor leo a diam sollicitudin tempor id. Urna nunc id cursus metus aliquam eleifend. Id leo in vitae turpis. Nulla facilisi cras fermentum odio eu feugiat pretium nibh ipsum. Vitae congue mauris rhoncus aenean vel elit scelerisque mauris pellentesque. Pharetra diam sit amet nisl suscipit adipiscing. Quis commodo odio aenean sed. Mattis rhoncus urna neque viverra justo nec ultrices dui. Volutpat commodo sed egestas egestas fringilla. Gravida in fermentum et sollicitudin ac orci. Nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi. - -Nunc pulvinar sapien et ligula ullamcorper malesuada. Elementum sagittis vitae et leo. In tellus integer feugiat scelerisque varius. Montes nascetur ridiculus mus mauris vitae. Eget lorem dolor sed viverra ipsum nunc aliquet. Sed cras ornare arcu dui. Elementum nibh tellus molestie nunc non blandit massa. Cras fermentum odio eu feugiat. Ipsum dolor sit amet consectetur adipiscing. Non pulvinar neque laoreet suspendisse interdum. Sit amet tellus cras adipiscing enim eu turpis. Fames ac turpis egestas integer eget aliquet nibh. Laoreet sit amet cursus sit amet dictum sit amet. Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna. Vitae ultricies leo integer malesuada. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. - -Non consectetur a erat nam at lectus urna duis convallis. Amet risus nullam eget felis. Id velit ut tortor pretium viverra suspendisse potenti nullam ac. Massa id neque aliquam vestibulum morbi blandit cursus risus. Pharetra pharetra massa massa ultricies mi. Id volutpat lacus laoreet non. At quis risus sed vulputate odio. Erat nam at lectus urna duis convallis convallis tellus. Eros donec ac odio tempor orci dapibus ultrices. Gravida rutrum quisque non tellus orci ac. Metus vulputate eu scelerisque felis imperdiet proin fermentum leo vel. Imperdiet sed euismod nisi porta lorem. Orci nulla pellentesque dignissim enim. Blandit turpis cursus in hac habitasse platea. Pellentesque nec nam aliquam sem et tortor consequat id porta. At erat pellentesque adipiscing commodo elit at. Egestas sed sed risus pretium quam. Varius morbi enim nunc faucibus a pellentesque sit. Mi eget mauris pharetra et ultrices neque ornare aenean. - -Mattis vulputate enim nulla aliquet porttitor lacus luctus. Morbi tincidunt ornare massa eget egestas purus. Adipiscing at in tellus integer feugiat scelerisque varius morbi enim. Pulvinar mattis nunc sed blandit. Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Ut consequat semper viverra nam libero justo. Massa placerat duis ultricies lacus sed turpis tincidunt id. Id consectetur purus ut faucibus pulvinar elementum integer. Viverra aliquet eget sit amet tellus. Facilisi etiam dignissim diam quis enim. Felis donec et odio pellentesque diam volutpat commodo sed egestas. Nec ultrices dui sapien eget mi proin sed libero. Leo urna molestie at elementum eu. Nulla porttitor massa id neque aliquam vestibulum. - -Semper eget duis at tellus at. Elit sed vulputate mi sit amet. Sit amet porttitor eget dolor morbi non arcu risus quis. Pellentesque elit eget gravida cum. Sagittis nisl rhoncus mattis rhoncus. Aliquet enim tortor at auctor urna nunc id cursus metus. Sed faucibus turpis in eu mi. Urna neque viverra justo nec. Facilisis volutpat est velit egestas dui id ornare. Dictum sit amet justo donec. Massa sapien faucibus et molestie. Enim nunc faucibus a pellentesque sit amet. Sed euismod nisi porta lorem mollis aliquam ut. Nulla at volutpat diam ut venenatis tellus in metus vulputate. Vel pharetra vel turpis nunc. - -Id diam maecenas ultricies mi eget mauris pharetra et ultrices. Vulputate mi sit amet mauris commodo quis imperdiet massa tincidunt. Nunc mi ipsum faucibus vitae aliquet nec. In ornare quam viverra orci sagittis. Luctus accumsan tortor posuere ac ut consequat semper. Tempus imperdiet nulla malesuada pellentesque elit eget. Sed felis eget velit aliquet sagittis id consectetur purus. Ut sem nulla pharetra diam. Eget nullam non nisi est sit amet facilisis magna. Malesuada fames ac turpis egestas integer. - -Amet nulla facilisi morbi tempus iaculis urna id. Massa sapien faucibus et molestie ac feugiat sed. Pellentesque habitant morbi tristique senectus. Mauris a diam maecenas sed enim ut sem. Ultrices sagittis orci a scelerisque purus. Commodo ullamcorper a lacus vestibulum sed arcu non odio. Sed faucibus turpis in eu. Orci nulla pellentesque dignissim enim sit. Donec ultrices tincidunt arcu non sodales neque. Velit euismod in pellentesque massa. Nibh tortor id aliquet lectus proin nibh nisl. Eget lorem dolor sed viverra ipsum nunc. Nunc congue nisi vitae suscipit tellus mauris a diam maecenas. Quis varius quam quisque id diam vel quam elementum pulvinar. Aliquet lectus proin nibh nisl. Urna duis convallis convallis tellus id interdum velit. Aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Turpis egestas integer eget aliquet. Interdum varius sit amet mattis vulputate enim. Magna ac placerat vestibulum lectus mauris ultrices eros in cursus. - -Lacus vel facilisis volutpat est velit egestas. Massa massa ultricies mi quis. Gravida cum sociis natoque penatibus et magnis dis parturient. Condimentum mattis pellentesque id nibh tortor. Metus aliquam eleifend mi in nulla posuere. Est ullamcorper eget nulla facilisi etiam dignissim diam quis enim. Enim eu turpis egestas pretium aenean pharetra magna ac placerat. Duis tristique sollicitudin nibh sit. Tincidunt nunc pulvinar sapien et ligula ullamcorper. Blandit libero volutpat sed cras. Etiam sit amet nisl purus in mollis nunc sed. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Enim lobortis scelerisque fermentum dui faucibus in. - -Pellentesque habitant morbi tristique senectus et. Enim sed faucibus turpis in eu mi bibendum neque egestas. Ut sem viverra aliquet eget sit amet tellus. Enim neque volutpat ac tincidunt. Justo eget magna fermentum iaculis. Tincidunt augue interdum velit euismod. Sed enim ut sem viverra aliquet eget. Vitae congue eu consequat ac. Morbi leo urna molestie at elementum eu facilisis. Sit amet risus nullam eget felis eget nunc lobortis mattis. Eget arcu dictum varius duis at consectetur lorem. Eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Interdum posuere lorem ipsum dolor sit. Ac felis donec et odio pellentesque diam. Ridiculus mus mauris vitae ultricies. Nascetur ridiculus mus mauris vitae ultricies leo. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Scelerisque fermentum dui faucibus in ornare quam viverra orci. Non enim praesent elementum facilisis leo vel. - -Proin nibh nisl condimentum id. Volutpat blandit aliquam etiam erat velit. Convallis tellus id interdum velit. Purus in mollis nunc sed id semper. Adipiscing commodo elit at imperdiet dui accumsan sit amet. Elit at imperdiet dui accumsan sit amet. Enim sit amet venenatis urna. Lectus magna fringilla urna porttitor rhoncus. Mauris pharetra et ultrices neque ornare aenean euismod elementum nisi. Magna fermentum iaculis eu non. Nulla pellentesque dignissim enim sit amet. Suspendisse faucibus interdum posuere lorem. Quis blandit turpis cursus in. Porttitor eget dolor morbi non arcu. - -Enim neque volutpat ac tincidunt vitae semper quis lectus. Scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam. Est pellentesque elit ullamcorper dignissim. Scelerisque purus semper eget duis. Egestas sed sed risus pretium. Senectus et netus et malesuada fames ac turpis egestas. Ultricies leo integer malesuada nunc vel risus commodo. Erat velit scelerisque in dictum non consectetur. Vel orci porta non pulvinar neque laoreet suspendisse interdum consectetur. Malesuada pellentesque elit eget gravida cum. Ac tincidunt vitae semper quis. Est lorem ipsum dolor sit amet. Aliquam ultrices sagittis orci a scelerisque purus semper. Tellus elementum sagittis vitae et leo duis ut. Sapien faucibus et molestie ac. Placerat in egestas erat imperdiet sed. Tellus mauris a diam maecenas sed. Pretium aenean pharetra magna ac placerat vestibulum lectus mauris. - -Lorem sed risus ultricies tristique nulla. Suspendisse interdum consectetur libero id faucibus nisl. Purus faucibus ornare suspendisse sed nisi lacus sed viverra tellus. Arcu felis bibendum ut tristique et. Eget lorem dolor sed viverra. Mattis vulputate enim nulla aliquet. Iaculis eu non diam phasellus vestibulum lorem sed risus. Leo a diam sollicitudin tempor id eu nisl. Et molestie ac feugiat sed lectus vestibulum mattis. Urna cursus eget nunc scelerisque viverra mauris in. Aenean et tortor at risus viverra adipiscing at in tellus. - -Etiam non quam lacus suspendisse faucibus interdum posuere lorem. Mi eget mauris pharetra et ultrices neque. Dui faucibus in ornare quam viverra orci. Pretium nibh ipsum consequat nisl. Non consectetur a erat nam. Gravida cum sociis natoque penatibus et magnis dis. Lacinia at quis risus sed vulputate. Sed vulputate odio ut enim blandit volutpat. Fames ac turpis egestas sed. Sit amet consectetur adipiscing elit duis tristique sollicitudin nibh. Leo duis ut diam quam nulla porttitor. Nisl purus in mollis nunc sed. Donec adipiscing tristique risus nec feugiat. Pharetra et ultrices neque ornare aenean euismod elementum nisi quis. Nunc lobortis mattis aliquam faucibus. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. - -Non consectetur a erat nam. Egestas integer eget aliquet nibh praesent tristique magna. Morbi non arcu risus quis varius quam quisque. Eget est lorem ipsum dolor sit amet consectetur. Tincidunt lobortis feugiat vivamus at augue eget. Accumsan tortor posuere ac ut consequat semper viverra. Lectus nulla at volutpat diam ut venenatis tellus in metus. Fermentum posuere urna nec tincidunt. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Nunc congue nisi vitae suscipit tellus mauris a diam maecenas. Non blandit massa enim nec dui. Augue lacus viverra vitae congue eu consequat. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget. Diam vel quam elementum pulvinar etiam. Blandit massa enim nec dui. Tempus imperdiet nulla malesuada pellentesque elit eget gravida. Nisi lacus sed viverra tellus. Quis blandit turpis cursus in hac habitasse. - -Senectus et netus et malesuada fames. Lorem ipsum dolor sit amet consectetur adipiscing. Malesuada nunc vel risus commodo viverra maecenas accumsan lacus vel. Blandit cursus risus at ultrices. Dictum fusce ut placerat orci nulla pellentesque dignissim enim. Faucibus in ornare quam viverra orci sagittis eu. Malesuada bibendum arcu vitae elementum curabitur vitae nunc. Tortor id aliquet lectus proin nibh nisl condimentum. Volutpat ac tincidunt vitae semper quis lectus nulla at. Risus nullam eget felis eget nunc lobortis. Pharetra convallis posuere morbi leo urna molestie at elementum. Non consectetur a erat nam at. Vitae auctor eu augue ut lectus arcu bibendum at varius. Auctor urna nunc id cursus metus aliquam eleifend mi in. Sed risus pretium quam vulputate dignissim. Pellentesque habitant morbi tristique senectus et netus et malesuada. Tincidunt praesent semper feugiat nibh sed pulvinar proin. - -Sed viverra ipsum nunc aliquet bibendum enim facilisis. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing vitae. Amet mattis vulputate enim nulla aliquet porttitor. Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Bibendum arcu vitae elementum curabitur vitae nunc. Integer eget aliquet nibh praesent tristique magna. Suspendisse faucibus interdum posuere lorem ipsum dolor sit amet. Venenatis urna cursus eget nunc. Amet commodo nulla facilisi nullam vehicula ipsum. At erat pellentesque adipiscing commodo. Imperdiet sed euismod nisi porta lorem mollis aliquam ut porttitor. Pellentesque eu tincidunt tortor aliquam. Et ultrices neque ornare aenean euismod elementum nisi quis eleifend. Urna et pharetra pharetra massa massa ultricies mi. Nam libero justo laoreet sit. Faucibus pulvinar elementum integer enim neque volutpat. - -In massa tempor nec feugiat nisl pretium fusce. Cras fermentum odio eu feugiat pretium nibh. Pharetra massa massa ultricies mi quis hendrerit dolor magna. Dignissim enim sit amet venenatis urna cursus eget nunc scelerisque. Sed faucibus turpis in eu mi bibendum neque egestas congue. Quisque sagittis purus sit amet volutpat consequat mauris. In vitae turpis massa sed elementum tempus egestas sed. Cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum. Eget dolor morbi non arcu risus quis varius quam. Nunc eget lorem dolor sed viverra ipsum nunc aliquet. Tristique et egestas quis ipsum. Viverra vitae congue eu consequat ac felis. Nunc congue nisi vitae suscipit tellus mauris. Mauris pharetra et ultrices neque ornare aenean euismod. Ipsum faucibus vitae aliquet nec ullamcorper sit. Eget nunc scelerisque viverra mauris. Cursus risus at ultrices mi tempus imperdiet nulla malesuada. - -Pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus et. Amet nisl purus in mollis nunc. Sed vulputate mi sit amet mauris commodo quis imperdiet. Id volutpat lacus laoreet non curabitur gravida arcu. Quis hendrerit dolor magna eget. Vitae proin sagittis nisl rhoncus. Placerat orci nulla pellentesque dignissim enim sit amet venenatis urna. Amet est placerat in egestas erat imperdiet sed. Ipsum dolor sit amet consectetur. Risus in hendrerit gravida rutrum quisque non tellus. Sed velit dignissim sodales ut eu sem. Laoreet sit amet cursus sit amet dictum sit amet. Amet risus nullam eget felis eget nunc lobortis. - -Nec feugiat in fermentum posuere urna nec tincidunt praesent. Nunc eget lorem dolor sed viverra ipsum nunc aliquet. Libero id faucibus nisl tincidunt eget nullam. Eget gravida cum sociis natoque. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Diam maecenas ultricies mi eget mauris pharetra et ultrices. Donec massa sapien faucibus et. Porttitor eget dolor morbi non arcu risus quis varius quam. Molestie at elementum eu facilisis sed odio morbi quis. Velit sed ullamcorper morbi tincidunt. Et leo duis ut diam. Ullamcorper a lacus vestibulum sed arcu non odio. Purus faucibus ornare suspendisse sed nisi lacus. Nisl nisi scelerisque eu ultrices vitae auctor. Feugiat nibh sed pulvinar proin gravida hendrerit. Tortor aliquam nulla facilisi cras fermentum odio eu feugiat pretium. Ultricies leo integer malesuada nunc vel risus commodo viverra. Quis commodo odio aenean sed adipiscing. Quis lectus nulla at volutpat diam ut venenatis tellus in. - -Vulputate mi sit amet mauris commodo quis. Volutpat blandit aliquam etiam erat velit scelerisque in. Non diam phasellus vestibulum lorem sed risus ultricies. Vitae sapien pellentesque habitant morbi tristique. Imperdiet nulla malesuada pellentesque elit eget gravida cum sociis. At risus viverra adipiscing at in. Hendrerit dolor magna eget est. Ornare suspendisse sed nisi lacus sed viverra tellus. Adipiscing at in tellus integer. Ipsum dolor sit amet consectetur adipiscing. Porttitor lacus luctus accumsan tortor posuere ac. Odio ut sem nulla pharetra diam sit amet. Enim lobortis scelerisque fermentum dui faucibus in. Iaculis nunc sed augue lacus. Amet dictum sit amet justo. Bibendum at varius vel pharetra vel turpis nunc eget. Non tellus orci ac auctor augue mauris augue neque. Semper auctor neque vitae tempus quam. Ut sem nulla pharetra diam sit. - -Cursus vitae congue mauris rhoncus aenean. Habitant morbi tristique senectus et netus et malesuada fames ac. Tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin libero. Accumsan lacus vel facilisis volutpat est velit egestas dui id. Nascetur ridiculus mus mauris vitae ultricies. Turpis massa sed elementum tempus egestas sed sed risus pretium. Arcu non sodales neque sodales ut etiam sit amet nisl. Amet nisl suscipit adipiscing bibendum est ultricies. Accumsan lacus vel facilisis volutpat est velit egestas. Egestas maecenas pharetra convallis posuere morbi leo urna. Vulputate dignissim suspendisse in est ante in. - -Tristique senectus et netus et malesuada fames ac turpis egestas. Amet massa vitae tortor condimentum lacinia quis. Cras semper auctor neque vitae. Etiam erat velit scelerisque in dictum. Egestas sed tempus urna et pharetra pharetra massa. Fermentum dui faucibus in ornare quam viverra orci sagittis eu. Turpis egestas maecenas pharetra convallis posuere morbi leo urna. Erat nam at lectus urna. Nullam eget felis eget nunc lobortis mattis. Sed blandit libero volutpat sed cras ornare arcu. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Egestas congue quisque egestas diam in arcu. Cursus sit amet dictum sit amet justo. Purus non enim praesent elementum facilisis leo vel fringilla est. Venenatis cras sed felis eget. - -Eu non diam phasellus vestibulum lorem sed risus ultricies tristique. At ultrices mi tempus imperdiet. Pretium viverra suspendisse potenti nullam ac tortor. A iaculis at erat pellentesque. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque. Orci eu lobortis elementum nibh. Gravida neque convallis a cras semper auctor. Felis donec et odio pellentesque. Cras ornare arcu dui vivamus arcu. Nibh praesent tristique magna sit amet. Volutpat lacus laoreet non curabitur gravida arcu ac. Varius duis at consectetur lorem donec massa. Nunc congue nisi vitae suscipit tellus mauris. Sed risus ultricies tristique nulla aliquet enim. Massa tincidunt nunc pulvinar sapien. Duis tristique sollicitudin nibh sit amet commodo nulla facilisi nullam. Aliquam ultrices sagittis orci a scelerisque purus semper. Proin libero nunc consequat interdum varius sit amet mattis vulputate. - -Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere lorem. Mi quis hendrerit dolor magna eget est lorem ipsum. Neque laoreet suspendisse interdum consectetur libero id faucibus. Massa massa ultricies mi quis hendrerit dolor magna eget. Sed turpis tincidunt id aliquet risus feugiat in ante. Gravida neque convallis a cras semper auctor neque vitae. Massa sapien faucibus et molestie ac feugiat. Ultricies mi eget mauris pharetra et ultrices neque. Erat pellentesque adipiscing commodo elit. Etiam erat velit scelerisque in dictum non consectetur a. Nullam ac tortor vitae purus faucibus ornare suspendisse. Sapien et ligula ullamcorper malesuada proin libero nunc consequat interdum. Velit ut tortor pretium viverra suspendisse potenti. At tempor commodo ullamcorper a lacus vestibulum sed. - -Semper viverra nam libero justo laoreet. Hendrerit gravida rutrum quisque non tellus orci. Amet purus gravida quis blandit turpis cursus in. Amet porttitor eget dolor morbi non arcu risus. Fames ac turpis egestas maecenas pharetra convallis posuere. Leo vel orci porta non. Nibh mauris cursus mattis molestie a iaculis at erat. Fusce id velit ut tortor. Pellentesque nec nam aliquam sem. Accumsan sit amet nulla facilisi. Amet venenatis urna cursus eget nunc scelerisque viverra mauris. Iaculis nunc sed augue lacus viverra vitae congue eu. Pharetra et ultrices neque ornare aenean. Odio ut sem nulla pharetra diam sit amet. Quis blandit turpis cursus in. Maecenas ultricies mi eget mauris pharetra et ultrices neque. Eros donec ac odio tempor orci dapibus. Enim neque volutpat ac tincidunt vitae semper. Nunc faucibus a pellentesque sit. - -Semper risus in hendrerit gravida rutrum quisque non. Dui accumsan sit amet nulla facilisi. Nec feugiat in fermentum posuere urna nec tincidunt praesent. Vel orci porta non pulvinar neque laoreet suspendisse. Ultrices dui sapien eget mi proin. Nisi quis eleifend quam adipiscing vitae proin sagittis nisl. At imperdiet dui accumsan sit. Blandit volutpat maecenas volutpat blandit. Sit amet consectetur adipiscing elit. Purus sit amet luctus venenatis lectus magna fringilla urna porttitor. - -Praesent tristique magna sit amet purus gravida. Sagittis id consectetur purus ut. Sit amet luctus venenatis lectus magna. Fermentum leo vel orci porta non pulvinar neque laoreet. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing. Turpis egestas pretium aenean pharetra magna ac placerat. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Eu ultrices vitae auctor eu. Malesuada pellentesque elit eget gravida. Sem nulla pharetra diam sit amet. Sed viverra tellus in hac habitasse platea dictumst vestibulum. Augue mauris augue neque gravida. Faucibus a pellentesque sit amet porttitor eget. Cras sed felis eget velit aliquet sagittis id consectetur purus. Ornare quam viverra orci sagittis eu volutpat. Sit amet mauris commodo quis. Habitant morbi tristique senectus et netus et malesuada fames. - -Ornare arcu odio ut sem nulla pharetra. Vitae aliquet nec ullamcorper sit amet risus nullam eget. Eget nunc lobortis mattis aliquam faucibus purus in. Donec ultrices tincidunt arcu non sodales neque sodales ut etiam. Integer eget aliquet nibh praesent tristique magna sit amet purus. Arcu dictum varius duis at. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl vel. Vitae sapien pellentesque habitant morbi tristique. Sit amet mauris commodo quis imperdiet massa. Eget sit amet tellus cras adipiscing enim eu turpis egestas. Arcu odio ut sem nulla. Nam libero justo laoreet sit. Cursus metus aliquam eleifend mi in nulla. - -Diam in arcu cursus euismod quis. Elit at imperdiet dui accumsan sit. Sem fringilla ut morbi tincidunt. Ut lectus arcu bibendum at varius vel pharetra vel turpis. Vitae elementum curabitur vitae nunc sed velit dignissim. Nunc scelerisque viverra mauris in aliquam sem fringilla ut. Accumsan in nisl nisi scelerisque eu. Sodales neque sodales ut etiam sit amet. Ut porttitor leo a diam sollicitudin tempor id eu. Scelerisque in dictum non consectetur. Adipiscing elit pellentesque habitant morbi tristique senectus et. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Neque vitae tempus quam pellentesque. Eu consequat ac felis donec et odio pellentesque diam. Quam quisque id diam vel quam elementum pulvinar. Eleifend mi in nulla posuere sollicitudin aliquam ultrices sagittis. Auctor eu augue ut lectus arcu. At tellus at urna condimentum mattis. - -Est lorem ipsum dolor sit amet consectetur adipiscing elit. Eu consequat ac felis donec. Massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada. Nibh praesent tristique magna sit. Eget nunc lobortis mattis aliquam faucibus purus in massa tempor. Vitae tortor condimentum lacinia quis. Sed arcu non odio euismod lacinia at quis risus sed. Etiam non quam lacus suspendisse faucibus interdum posuere. Mauris commodo quis imperdiet massa tincidunt. Maecenas volutpat blandit aliquam etiam erat. Mi proin sed libero enim sed faucibus turpis in eu. Eu lobortis elementum nibh tellus. Convallis a cras semper auctor. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor eu. - -Nulla facilisi nullam vehicula ipsum. Eu scelerisque felis imperdiet proin fermentum leo. Orci sagittis eu volutpat odio facilisis mauris sit amet. Etiam erat velit scelerisque in. Elit duis tristique sollicitudin nibh sit. Egestas sed tempus urna et pharetra pharetra. Elementum nibh tellus molestie nunc non. Felis eget velit aliquet sagittis id consectetur. Nec feugiat in fermentum posuere urna nec tincidunt. Lacus sed turpis tincidunt id aliquet risus feugiat. Nullam vehicula ipsum a arcu. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies leo. In mollis nunc sed id semper risus. Massa sed elementum tempus egestas sed sed risus pretium. Suscipit tellus mauris a diam. Eget gravida cum sociis natoque. - -Vitae suscipit tellus mauris a. Neque egestas congue quisque egestas diam in arcu cursus. Pellentesque habitant morbi tristique senectus. Fermentum odio eu feugiat pretium nibh ipsum. Eu non diam phasellus vestibulum lorem sed risus ultricies. Pulvinar etiam non quam lacus. Metus vulputate eu scelerisque felis imperdiet proin fermentum leo. Maecenas sed enim ut sem viverra aliquet eget. Nulla at volutpat diam ut venenatis tellus. Aliquet eget sit amet tellus cras adipiscing. Enim tortor at auctor urna nunc id cursus. Pellentesque dignissim enim sit amet venenatis urna cursus eget. A diam maecenas sed enim ut sem viverra aliquet. Faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam. Sed enim ut sem viverra. Magna ac placerat vestibulum lectus mauris ultrices. Egestas sed tempus urna et. Mollis nunc sed id semper risus in hendrerit gravida. Velit sed ullamcorper morbi tincidunt ornare massa eget egestas purus. Sit amet justo donec enim diam vulputate. - -Et sollicitudin ac orci phasellus egestas tellus. Non diam phasellus vestibulum lorem sed risus ultricies tristique. Volutpat ac tincidunt vitae semper quis lectus nulla at volutpat. Eros donec ac odio tempor orci dapibus ultrices in iaculis. Tincidunt ornare massa eget egestas purus viverra accumsan. Luctus accumsan tortor posuere ac ut consequat semper. Sagittis eu volutpat odio facilisis mauris. Enim facilisis gravida neque convallis a. Cursus mattis molestie a iaculis at erat pellentesque adipiscing. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Sit amet tellus cras adipiscing enim eu. Adipiscing elit duis tristique sollicitudin. Ut enim blandit volutpat maecenas volutpat blandit aliquam. Ac tortor dignissim convallis aenean et tortor at. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis. - -Felis bibendum ut tristique et egestas quis. Tristique senectus et netus et malesuada fames ac turpis egestas. Pretium lectus quam id leo in vitae turpis. Tempus egestas sed sed risus pretium. Tristique sollicitudin nibh sit amet commodo nulla. Viverra nam libero justo laoreet. Magna sit amet purus gravida quis blandit. Arcu non odio euismod lacinia at quis risus sed vulputate. Ipsum dolor sit amet consectetur adipiscing elit duis tristique. Sed vulputate odio ut enim blandit. Iaculis at erat pellentesque adipiscing. Suscipit tellus mauris a diam maecenas sed enim. Faucibus a pellentesque sit amet porttitor eget dolor morbi non. Morbi tempus iaculis urna id. Varius quam quisque id diam vel. Mauris a diam maecenas sed enim ut sem viverra. - -Ut eu sem integer vitae justo eget. Cras tincidunt lobortis feugiat vivamus at augue. Sed viverra tellus in hac habitasse platea dictumst. Sapien eget mi proin sed libero enim. Vulputate dignissim suspendisse in est ante in nibh mauris cursus. Phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Blandit turpis cursus in hac. Euismod quis viverra nibh cras pulvinar. Et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit. Ut consequat semper viverra nam libero justo laoreet. Faucibus nisl tincidunt eget nullam non. Mi bibendum neque egestas congue quisque egestas. Viverra orci sagittis eu volutpat. Libero enim sed faucibus turpis in. Dictum sit amet justo donec enim diam vulputate. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis. Aliquet lectus proin nibh nisl condimentum id venenatis a condimentum. - -Elementum nisi quis eleifend quam adipiscing vitae proin sagittis. Imperdiet dui accumsan sit amet nulla facilisi morbi tempus. Quam viverra orci sagittis eu volutpat odio facilisis mauris. Pretium nibh ipsum consequat nisl vel pretium lectus quam. Tellus mauris a diam maecenas sed enim ut. Eu volutpat odio facilisis mauris sit amet. Sapien faucibus et molestie ac feugiat sed lectus vestibulum mattis. Sollicitudin aliquam ultrices sagittis orci a scelerisque. Sagittis orci a scelerisque purus semper eget duis at. Id leo in vitae turpis massa sed. - -Augue eget arcu dictum varius duis at consectetur. Placerat duis ultricies lacus sed turpis tincidunt id aliquet. Quis vel eros donec ac odio tempor orci dapibus ultrices. Accumsan lacus vel facilisis volutpat est velit egestas. Dui accumsan sit amet nulla facilisi morbi tempus. Convallis a cras semper auctor neque vitae tempus. Amet commodo nulla facilisi nullam vehicula ipsum a. Consectetur lorem donec massa sapien. Sed adipiscing diam donec adipiscing tristique risus. Cras semper auctor neque vitae tempus quam pellentesque. Sed augue lacus viverra vitae congue eu consequat ac felis. Rutrum quisque non tellus orci ac auctor augue. Sed felis eget velit aliquet sagittis id consectetur purus. Ac feugiat sed lectus vestibulum mattis ullamcorper velit sed. Adipiscing enim eu turpis egestas pretium aenean. Non odio euismod lacinia at quis risus. Amet mauris commodo quis imperdiet massa tincidunt nunc pulvinar. Tortor condimentum lacinia quis vel eros donec ac. - -Nibh cras pulvinar mattis nunc sed blandit libero volutpat. Quis imperdiet massa tincidunt nunc pulvinar sapien et. Ipsum a arcu cursus vitae congue. Eu consequat ac felis donec et odio pellentesque. Neque gravida in fermentum et sollicitudin ac. Sit amet consectetur adipiscing elit duis tristique. Pharetra et ultrices neque ornare. Ut tristique et egestas quis ipsum suspendisse. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Egestas diam in arcu cursus euismod quis. Rhoncus dolor purus non enim praesent elementum facilisis leo. Ultricies mi eget mauris pharetra et ultrices neque ornare aenean. Tortor condimentum lacinia quis vel eros donec ac odio. Orci eu lobortis elementum nibh tellus molestie nunc non. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. - -Habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Nibh mauris cursus mattis molestie a iaculis at erat pellentesque. Lacus vestibulum sed arcu non odio euismod lacinia at quis. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum. Diam sit amet nisl suscipit adipiscing bibendum est ultricies. Gravida quis blandit turpis cursus in. Placerat orci nulla pellentesque dignissim enim sit amet. Donec ac odio tempor orci dapibus. Ac tortor vitae purus faucibus ornare suspendisse sed nisi. Malesuada fames ac turpis egestas sed tempus urna et pharetra. - -At volutpat diam ut venenatis tellus in metus vulputate. Amet consectetur adipiscing elit duis tristique sollicitudin. Id semper risus in hendrerit gravida rutrum. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. Tincidunt arcu non sodales neque sodales ut etiam sit amet. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Viverra nam libero justo laoreet sit amet cursus sit. Quam viverra orci sagittis eu volutpat odio facilisis mauris sit. Sollicitudin nibh sit amet commodo nulla. Vel eros donec ac odio tempor orci dapibus ultrices. Praesent semper feugiat nibh sed. Egestas sed sed risus pretium quam vulputate. Augue neque gravida in fermentum. Sodales neque sodales ut etiam sit amet nisl purus in. Ut tellus elementum sagittis vitae et leo duis ut diam. At in tellus integer feugiat scelerisque. Justo eget magna fermentum iaculis eu non. - -Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Non quam lacus suspendisse faucibus interdum posuere. Dui sapien eget mi proin sed. Quisque non tellus orci ac auctor augue mauris augue neque. Pharetra magna ac placerat vestibulum. Viverra suspendisse potenti nullam ac. Ipsum dolor sit amet consectetur adipiscing. Gravida in fermentum et sollicitudin ac orci. Rhoncus urna neque viverra justo nec ultrices dui sapien eget. Nunc aliquet bibendum enim facilisis gravida neque convallis a cras. Tempor id eu nisl nunc mi ipsum faucibus vitae aliquet. - -Viverra adipiscing at in tellus integer. Amet risus nullam eget felis eget nunc lobortis mattis. Sed odio morbi quis commodo odio aenean sed. Imperdiet nulla malesuada pellentesque elit eget gravida. Diam vulputate ut pharetra sit amet aliquam id. Aliquam purus sit amet luctus venenatis lectus magna. Vitae tempus quam pellentesque nec nam aliquam sem et. Fusce ut placerat orci nulla pellentesque dignissim. Lacus vel facilisis volutpat est velit egestas dui id ornare. Mi bibendum neque egestas congue quisque egestas diam in. Mauris commodo quis imperdiet massa tincidunt. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing. Mauris cursus mattis molestie a. Vitae tortor condimentum lacinia quis. Duis at tellus at urna condimentum. Egestas sed sed risus pretium quam vulputate dignissim suspendisse. Imperdiet massa tincidunt nunc pulvinar sapien. - -Justo eget magna fermentum iaculis. Cursus in hac habitasse platea dictumst. Nam aliquam sem et tortor consequat. Elementum pulvinar etiam non quam lacus suspendisse faucibus interdum. Pretium lectus quam id leo in vitae turpis massa. Libero justo laoreet sit amet. Nulla posuere sollicitudin aliquam ultrices sagittis orci. Id ornare arcu odio ut sem nulla pharetra. Viverra ipsum nunc aliquet bibendum enim. Mauris pharetra et ultrices neque ornare aenean euismod elementum. Ultrices neque ornare aenean euismod elementum nisi quis eleifend. Nulla facilisi nullam vehicula ipsum a arcu cursus. Et leo duis ut diam quam nulla porttitor massa id. A arcu cursus vitae congue mauris. Id aliquet risus feugiat in ante metus. Amet tellus cras adipiscing enim eu turpis egestas pretium aenean. Ipsum faucibus vitae aliquet nec ullamcorper sit. Libero justo laoreet sit amet cursus. Egestas diam in arcu cursus euismod quis viverra nibh. Proin sed libero enim sed faucibus turpis in. - -Lacus viverra vitae congue eu consequat. Elementum tempus egestas sed sed. Ante in nibh mauris cursus mattis molestie a. Euismod in pellentesque massa placerat duis ultricies. Cras sed felis eget velit. Elementum integer enim neque volutpat ac tincidunt vitae semper quis. Ut etiam sit amet nisl purus in mollis nunc sed. Odio euismod lacinia at quis risus sed vulputate. Mi sit amet mauris commodo quis imperdiet. Sollicitudin nibh sit amet commodo nulla facilisi. Malesuada nunc vel risus commodo viverra maecenas accumsan lacus. Vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa. - -Porta non pulvinar neque laoreet suspendisse. Pellentesque nec nam aliquam sem et tortor consequat id porta. Gravida arcu ac tortor dignissim convallis aenean et tortor at. Quis hendrerit dolor magna eget. Diam maecenas sed enim ut sem viverra. Enim nunc faucibus a pellentesque. Amet nisl suscipit adipiscing bibendum est. Ac orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Varius quam quisque id diam vel quam elementum pulvinar. Rhoncus dolor purus non enim praesent elementum. Massa enim nec dui nunc mattis enim ut tellus. - -Nisi est sit amet facilisis magna etiam. Lobortis feugiat vivamus at augue eget arcu. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere. Convallis posuere morbi leo urna. Sed adipiscing diam donec adipiscing tristique risus. Enim nec dui nunc mattis enim ut tellus. Sed viverra ipsum nunc aliquet bibendum enim. Sagittis nisl rhoncus mattis rhoncus. Etiam tempor orci eu lobortis elementum nibh. Pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus. Purus gravida quis blandit turpis cursus in. Nunc vel risus commodo viverra maecenas accumsan lacus vel facilisis. Maecenas sed enim ut sem viverra aliquet eget sit. Sed vulputate odio ut enim blandit volutpat maecenas volutpat. Quisque egestas diam in arcu cursus euismod quis. Orci a scelerisque purus semper eget duis at tellus at. Lorem ipsum dolor sit amet consectetur adipiscing elit duis. Sed id semper risus in hendrerit gravida rutrum quisque non. Et egestas quis ipsum suspendisse ultrices gravida dictum fusce ut. Non curabitur gravida arcu ac tortor dignissim convallis aenean et. - -Erat nam at lectus urna duis convallis convallis tellus. Tortor at risus viverra adipiscing at. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. Adipiscing commodo elit at imperdiet dui accumsan. Ut sem nulla pharetra diam sit amet nisl suscipit adipiscing. Enim praesent elementum facilisis leo vel fringilla. Aenean sed adipiscing diam donec adipiscing tristique risus nec. Cras adipiscing enim eu turpis. Aliquam nulla facilisi cras fermentum odio eu. Dictum at tempor commodo ullamcorper a lacus vestibulum sed. Iaculis eu non diam phasellus vestibulum lorem. Curabitur vitae nunc sed velit dignissim sodales ut. Nulla at volutpat diam ut venenatis tellus in metus vulputate. Nec feugiat in fermentum posuere. - -Lacus sed turpis tincidunt id aliquet. Sagittis purus sit amet volutpat consequat mauris nunc congue nisi. Vel facilisis volutpat est velit egestas dui id. Quis enim lobortis scelerisque fermentum. Turpis massa sed elementum tempus egestas sed sed risus. Amet nisl purus in mollis nunc sed id. Nunc eget lorem dolor sed viverra ipsum nunc aliquet. Lectus arcu bibendum at varius vel. Amet massa vitae tortor condimentum. Dignissim cras tincidunt lobortis feugiat vivamus at augue eget arcu. - -Lectus mauris ultrices eros in cursus turpis massa. Lacus suspendisse faucibus interdum posuere lorem ipsum dolor. Tempor orci eu lobortis elementum nibh tellus molestie. Euismod in pellentesque massa placerat duis ultricies lacus sed. Massa massa ultricies mi quis hendrerit dolor magna eget est. Semper feugiat nibh sed pulvinar proin gravida. Eu nisl nunc mi ipsum faucibus vitae aliquet. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat in. Et leo duis ut diam quam nulla. Vitae tempus quam pellentesque nec. Convallis a cras semper auctor neque vitae. Praesent semper feugiat nibh sed pulvinar proin gravida. Id ornare arcu odio ut. Mauris rhoncus aenean vel elit scelerisque mauris. At varius vel pharetra vel turpis. Posuere ac ut consequat semper. - -Urna et pharetra pharetra massa massa ultricies mi quis hendrerit. Mi in nulla posuere sollicitudin aliquam ultrices sagittis. Lobortis mattis aliquam faucibus purus in massa tempor nec feugiat. Integer quis auctor elit sed vulputate mi sit amet mauris. Donec pretium vulputate sapien nec sagittis. Et malesuada fames ac turpis egestas maecenas pharetra convallis. Orci a scelerisque purus semper eget duis. Scelerisque felis imperdiet proin fermentum leo. Cras ornare arcu dui vivamus. Enim sed faucibus turpis in eu mi bibendum neque. Justo donec enim diam vulputate ut pharetra sit amet aliquam. Enim ut sem viverra aliquet eget. Sed libero enim sed faucibus turpis in eu. - -Et pharetra pharetra massa massa ultricies mi. Porttitor leo a diam sollicitudin tempor. Lacus viverra vitae congue eu consequat ac felis. Sapien nec sagittis aliquam malesuada bibendum. Nec nam aliquam sem et tortor. Faucibus et molestie ac feugiat sed lectus vestibulum mattis. Proin sagittis nisl rhoncus mattis rhoncus. Hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit. Eget nullam non nisi est sit. Elementum integer enim neque volutpat ac tincidunt vitae semper. Mi in nulla posuere sollicitudin aliquam. Sagittis purus sit amet volutpat consequat mauris nunc. Aliquet nibh praesent tristique magna sit amet. Purus non enim praesent elementum facilisis leo. - -Scelerisque eu ultrices vitae auctor eu augue. Vel quam elementum pulvinar etiam non quam lacus. Arcu cursus euismod quis viverra nibh cras pulvinar. Ac placerat vestibulum lectus mauris ultrices eros. Ullamcorper dignissim cras tincidunt lobortis. Pretium fusce id velit ut tortor. Ipsum a arcu cursus vitae. Neque volutpat ac tincidunt vitae semper. Senectus et netus et malesuada fames ac turpis. Lacinia at quis risus sed vulputate odio ut. Pharetra diam sit amet nisl suscipit adipiscing. Elementum sagittis vitae et leo duis ut. Purus in massa tempor nec feugiat nisl pretium fusce. Porttitor leo a diam sollicitudin. Id neque aliquam vestibulum morbi blandit cursus risus at ultrices. Consectetur adipiscing elit duis tristique sollicitudin nibh sit amet commodo. Ut enim blandit volutpat maecenas volutpat blandit. Quisque egestas diam in arcu cursus euismod. Tortor at auctor urna nunc id cursus metus. - -Sem fringilla ut morbi tincidunt augue interdum velit. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Lectus nulla at volutpat diam ut venenatis tellus. Gravida cum sociis natoque penatibus et magnis. Urna porttitor rhoncus dolor purus non enim praesent elementum facilisis. Sagittis orci a scelerisque purus semper eget duis at tellus. Mauris a diam maecenas sed. Cras fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna. Viverra adipiscing at in tellus. Malesuada pellentesque elit eget gravida cum sociis natoque penatibus et. Velit dignissim sodales ut eu sem integer. Nibh ipsum consequat nisl vel pretium lectus. Convallis convallis tellus id interdum velit. Est lorem ipsum dolor sit amet consectetur. Adipiscing diam donec adipiscing tristique risus nec. Pharetra et ultrices neque ornare aenean euismod elementum nisi quis. Nunc pulvinar sapien et ligula. Scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Lectus sit amet est placerat in. - -Id neque aliquam vestibulum morbi blandit cursus risus at ultrices. Adipiscing elit ut aliquam purus. Maecenas volutpat blandit aliquam etiam erat. Neque convallis a cras semper auctor neque. Fames ac turpis egestas maecenas pharetra convallis posuere morbi leo. Odio ut sem nulla pharetra diam. Quis imperdiet massa tincidunt nunc pulvinar. Penatibus et magnis dis parturient. A erat nam at lectus. Proin libero nunc consequat interdum. Aliquet porttitor lacus luctus accumsan tortor posuere. Turpis nunc eget lorem dolor sed viverra. Nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus. At tellus at urna condimentum. Tristique sollicitudin nibh sit amet. Neque egestas congue quisque egestas diam in arcu cursus euismod. Adipiscing at in tellus integer feugiat scelerisque. Consequat semper viverra nam libero justo laoreet. Nisl nunc mi ipsum faucibus vitae aliquet nec. Consequat ac felis donec et odio pellentesque diam volutpat. - -Auctor elit sed vulputate mi sit amet mauris commodo. Tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Elit eget gravida cum sociis natoque penatibus et magnis. Ut pharetra sit amet aliquam id diam maecenas ultricies. Pretium vulputate sapien nec sagittis. Et netus et malesuada fames ac. Duis ultricies lacus sed turpis tincidunt id aliquet risus. Scelerisque in dictum non consectetur a erat nam. Enim facilisis gravida neque convallis a cras semper auctor neque. Duis tristique sollicitudin nibh sit amet commodo. Eget aliquet nibh praesent tristique magna sit amet purus gravida. Non pulvinar neque laoreet suspendisse. At tellus at urna condimentum. Enim ut sem viverra aliquet. Proin fermentum leo vel orci porta non pulvinar neque. Commodo viverra maecenas accumsan lacus vel facilisis volutpat. In ante metus dictum at tempor. Sed cras ornare arcu dui vivamus arcu felis. Neque sodales ut etiam sit amet nisl purus in. - -A condimentum vitae sapien pellentesque habitant morbi tristique senectus. Odio tempor orci dapibus ultrices in iaculis nunc sed augue. Eu volutpat odio facilisis mauris sit. Sed pulvinar proin gravida hendrerit lectus. Sed id semper risus in hendrerit gravida. Nulla aliquet enim tortor at auctor urna. Nullam vehicula ipsum a arcu cursus vitae congue mauris. Diam sollicitudin tempor id eu nisl nunc mi ipsum faucibus. Quam elementum pulvinar etiam non quam lacus suspendisse faucibus. Ipsum dolor sit amet consectetur adipiscing elit duis. Turpis nunc eget lorem dolor sed viverra ipsum nunc. Dignissim convallis aenean et tortor at risus. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit. Id velit ut tortor pretium viverra. Risus viverra adipiscing at in tellus integer. Leo vel fringilla est ullamcorper eget nulla facilisi. Semper eget duis at tellus at urna condimentum mattis. Enim eu turpis egestas pretium aenean pharetra. Ligula ullamcorper malesuada proin libero nunc consequat. Tellus cras adipiscing enim eu turpis. - -Euismod lacinia at quis risus sed vulputate. Id aliquet lectus proin nibh nisl. Nunc sed velit dignissim sodales ut. Risus ultricies tristique nulla aliquet enim tortor. Egestas egestas fringilla phasellus faucibus scelerisque. Nunc faucibus a pellentesque sit amet porttitor eget. Et netus et malesuada fames. Et molestie ac feugiat sed lectus vestibulum mattis. Tortor at auctor urna nunc id cursus metus aliquam. Proin fermentum leo vel orci porta non. Massa sed elementum tempus egestas sed sed risus pretium quam. Nec feugiat in fermentum posuere urna. Quis eleifend quam adipiscing vitae proin. Tortor pretium viverra suspendisse potenti. Varius duis at consectetur lorem donec massa. Ipsum a arcu cursus vitae congue mauris rhoncus aenean vel. Rutrum quisque non tellus orci ac auctor augue mauris. - -Eleifend quam adipiscing vitae proin sagittis nisl rhoncus. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Pellentesque sit amet porttitor eget dolor morbi. Sit amet nulla facilisi morbi. Senectus et netus et malesuada fames. Nunc scelerisque viverra mauris in aliquam sem fringilla ut morbi. Purus sit amet volutpat consequat mauris nunc. Ac felis donec et odio. Tincidunt augue interdum velit euismod in pellentesque massa. Nec feugiat in fermentum posuere urna nec tincidunt. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Tristique senectus et netus et malesuada fames ac turpis egestas. Enim diam vulputate ut pharetra sit amet. Nibh tellus molestie nunc non. Nec ullamcorper sit amet risus nullam eget felis eget nunc. Arcu felis bibendum ut tristique et. Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Nisi est sit amet facilisis magna etiam tempor. Libero justo laoreet sit amet cursus sit amet. - -Diam sollicitudin tempor id eu nisl nunc. Eu non diam phasellus vestibulum lorem sed risus. In fermentum et sollicitudin ac orci phasellus egestas tellus rutrum. Imperdiet dui accumsan sit amet nulla facilisi morbi. Consectetur adipiscing elit duis tristique. Aliquam purus sit amet luctus venenatis lectus magna fringilla urna. Enim sed faucibus turpis in eu mi bibendum neque. Urna id volutpat lacus laoreet. Condimentum vitae sapien pellentesque habitant morbi. Pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. Scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Scelerisque varius morbi enim nunc faucibus. Urna et pharetra pharetra massa massa. Lacinia at quis risus sed vulputate odio ut enim blandit. - -Ipsum faucibus vitae aliquet nec ullamcorper sit amet. Odio eu feugiat pretium nibh ipsum consequat nisl vel. Ut consequat semper viverra nam libero justo. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque. At tellus at urna condimentum mattis pellentesque id. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant. Habitant morbi tristique senectus et. In ornare quam viverra orci sagittis. Etiam erat velit scelerisque in dictum. Quam pellentesque nec nam aliquam sem et tortor consequat id. Massa tincidunt nunc pulvinar sapien et. Accumsan lacus vel facilisis volutpat est velit egestas dui. Tortor condimentum lacinia quis vel eros donec ac. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Odio facilisis mauris sit amet massa vitae tortor condimentum lacinia. Pharetra diam sit amet nisl. Lacus luctus accumsan tortor posuere ac. Quis commodo odio aenean sed adipiscing diam donec. Turpis egestas integer eget aliquet nibh praesent tristique magna sit. - -Justo eget magna fermentum iaculis eu non diam phasellus. Nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque. Mauris pharetra et ultrices neque ornare aenean euismod. Nibh sed pulvinar proin gravida hendrerit. Eget egestas purus viverra accumsan in nisl nisi scelerisque. In arcu cursus euismod quis viverra nibh cras. Scelerisque in dictum non consectetur. Sed enim ut sem viverra aliquet eget sit. Morbi non arcu risus quis varius quam quisque id. Dignissim suspendisse in est ante. Elementum nisi quis eleifend quam adipiscing vitae. Consequat interdum varius sit amet mattis vulputate enim. Ut eu sem integer vitae justo eget magna fermentum. Elit duis tristique sollicitudin nibh sit amet commodo. Et malesuada fames ac turpis egestas sed tempus urna et. - -Ac turpis egestas integer eget aliquet. Eget nunc lobortis mattis aliquam faucibus purus in. Velit sed ullamcorper morbi tincidunt ornare. Turpis nunc eget lorem dolor sed viverra ipsum nunc. Tellus cras adipiscing enim eu. Augue interdum velit euismod in pellentesque massa placerat duis. Sagittis purus sit amet volutpat consequat mauris. Blandit cursus risus at ultrices. Nec dui nunc mattis enim. Sit amet volutpat consequat mauris. Vitae aliquet nec ullamcorper sit amet risus nullam. Pellentesque habitant morbi tristique senectus et netus et. Sit amet risus nullam eget felis eget nunc lobortis. Sodales neque sodales ut etiam sit amet nisl purus. Velit dignissim sodales ut eu sem. Aliquam faucibus purus in massa tempor nec feugiat. Lacus sed turpis tincidunt id aliquet risus feugiat in ante. Tellus pellentesque eu tincidunt tortor aliquam nulla facilisi cras. Aliquet porttitor lacus luctus accumsan tortor posuere ac. - -Magnis dis parturient montes nascetur ridiculus mus mauris vitae. Interdum consectetur libero id faucibus nisl tincidunt eget nullam. Volutpat lacus laoreet non curabitur gravida arcu ac tortor dignissim. Non curabitur gravida arcu ac tortor dignissim convallis aenean. Suspendisse ultrices gravida dictum fusce ut placerat. Morbi tincidunt ornare massa eget. Mi in nulla posuere sollicitudin aliquam ultrices sagittis orci. Adipiscing elit ut aliquam purus sit amet luctus. Sagittis orci a scelerisque purus semper eget duis at. Quis auctor elit sed vulputate mi. Massa massa ultricies mi quis hendrerit dolor magna. Nam at lectus urna duis convallis convallis tellus. Blandit aliquam etiam erat velit scelerisque in dictum non. Facilisis mauris sit amet massa vitae. Ultrices in iaculis nunc sed augue lacus. - -Commodo viverra maecenas accumsan lacus vel facilisis. Massa tincidunt nunc pulvinar sapien et ligula. Eu turpis egestas pretium aenean pharetra. Consectetur libero id faucibus nisl tincidunt eget nullam non. Id porta nibh venenatis cras sed felis eget velit aliquet. Fermentum iaculis eu non diam phasellus vestibulum lorem. Orci dapibus ultrices in iaculis. Maecenas pharetra convallis posuere morbi leo urna. Neque laoreet suspendisse interdum consectetur libero id faucibus. Felis eget nunc lobortis mattis aliquam faucibus purus. Iaculis urna id volutpat lacus laoreet non. Semper risus in hendrerit gravida rutrum quisque non tellus. Sed augue lacus viverra vitae congue eu consequat. Facilisis magna etiam tempor orci eu lobortis elementum. Pulvinar sapien et ligula ullamcorper malesuada proin. - -Sapien pellentesque habitant morbi tristique senectus. Risus nullam eget felis eget nunc lobortis mattis. Sit amet venenatis urna cursus eget nunc scelerisque viverra. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Enim praesent elementum facilisis leo vel fringilla est. Eget nunc scelerisque viverra mauris in aliquam sem fringilla ut. Ut eu sem integer vitae justo eget magna fermentum. Senectus et netus et malesuada fames ac. Mi tempus imperdiet nulla malesuada pellentesque elit eget gravida. Quam pellentesque nec nam aliquam. Vulputate enim nulla aliquet porttitor lacus. Porttitor lacus luctus accumsan tortor posuere ac. Enim ut tellus elementum sagittis. Euismod lacinia at quis risus. Enim sit amet venenatis urna cursus eget nunc scelerisque viverra. In ornare quam viverra orci sagittis eu volutpat. Euismod quis viverra nibh cras pulvinar mattis nunc sed. Feugiat pretium nibh ipsum consequat nisl vel pretium. - -Nullam vehicula ipsum a arcu cursus vitae congue mauris rhoncus. Eu sem integer vitae justo. Scelerisque felis imperdiet proin fermentum. Massa tempor nec feugiat nisl. Laoreet suspendisse interdum consectetur libero id. Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat. Tristique senectus et netus et malesuada fames ac turpis. Massa eget egestas purus viverra accumsan in nisl. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Arcu cursus vitae congue mauris rhoncus. Eleifend quam adipiscing vitae proin sagittis. - -Non odio euismod lacinia at quis risus sed. Accumsan lacus vel facilisis volutpat. Sed adipiscing diam donec adipiscing tristique risus. In aliquam sem fringilla ut morbi tincidunt. Viverra aliquet eget sit amet tellus. Cursus turpis massa tincidunt dui ut ornare. Lacus luctus accumsan tortor posuere ac ut consequat. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Velit euismod in pellentesque massa. Lectus nulla at volutpat diam ut venenatis tellus in. Mi quis hendrerit dolor magna eget est. - -Tincidunt praesent semper feugiat nibh. Tortor at auctor urna nunc id. Volutpat blandit aliquam etiam erat velit scelerisque in. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Ipsum consequat nisl vel pretium lectus quam. Etiam tempor orci eu lobortis elementum nibh. Eget sit amet tellus cras. Neque sodales ut etiam sit amet nisl purus in mollis. Condimentum lacinia quis vel eros donec ac odio tempor. Dictumst quisque sagittis purus sit amet. Orci sagittis eu volutpat odio facilisis. Quis imperdiet massa tincidunt nunc pulvinar. Nisl condimentum id venenatis a. Vitae et leo duis ut diam quam nulla. Vitae congue mauris rhoncus aenean vel. Viverra aliquet eget sit amet tellus cras adipiscing. Tincidunt ornare massa eget egestas purus viverra accumsan in nisl. Nibh venenatis cras sed felis. - -Ut porttitor leo a diam sollicitudin tempor. Laoreet suspendisse interdum consectetur libero id faucibus nisl. Senectus et netus et malesuada. Mi eget mauris pharetra et ultrices neque ornare aenean euismod. Id aliquet risus feugiat in ante metus dictum. Cum sociis natoque penatibus et magnis dis parturient montes. Ipsum consequat nisl vel pretium lectus quam id leo in. Quam vulputate dignissim suspendisse in est ante. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Mattis pellentesque id nibh tortor id. Dignissim enim sit amet venenatis urna cursus eget. In fermentum posuere urna nec tincidunt. Cras adipiscing enim eu turpis egestas pretium aenean pharetra magna. Tellus mauris a diam maecenas. Egestas egestas fringilla phasellus faucibus scelerisque. Amet nulla facilisi morbi tempus iaculis urna id volutpat lacus. Orci sagittis eu volutpat odio facilisis mauris sit amet massa. Etiam non quam lacus suspendisse faucibus. Lectus sit amet est placerat in. - -Id diam maecenas ultricies mi eget mauris. Dolor sit amet consectetur adipiscing elit ut aliquam purus. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. Turpis egestas sed tempus urna et pharetra pharetra massa. Donec massa sapien faucibus et molestie ac feugiat sed. Nisl suscipit adipiscing bibendum est ultricies integer. Magna sit amet purus gravida quis. Massa placerat duis ultricies lacus sed turpis. Turpis massa sed elementum tempus egestas. Fermentum iaculis eu non diam phasellus vestibulum lorem sed risus. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. Amet aliquam id diam maecenas ultricies. Tincidunt eget nullam non nisi. At varius vel pharetra vel turpis nunc eget lorem dolor. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Ultrices gravida dictum fusce ut placerat. Commodo viverra maecenas accumsan lacus vel facilisis volutpat. - -Sit amet venenatis urna cursus. Arcu dictum varius duis at consectetur lorem donec. Pulvinar neque laoreet suspendisse interdum consectetur libero id. Aliquam nulla facilisi cras fermentum odio eu feugiat pretium. Pharetra et ultrices neque ornare aenean euismod elementum nisi quis. Luctus venenatis lectus magna fringilla urna porttitor. Eu feugiat pretium nibh ipsum consequat nisl vel pretium. Ornare suspendisse sed nisi lacus sed. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tellus elementum sagittis vitae et leo duis. Eu scelerisque felis imperdiet proin fermentum leo. Quisque non tellus orci ac. Tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada. Diam quam nulla porttitor massa id neque aliquam vestibulum. - -Consequat ac felis donec et odio pellentesque diam volutpat. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit. Nunc aliquet bibendum enim facilisis gravida neque convallis a. Pellentesque elit ullamcorper dignissim cras. Vulputate enim nulla aliquet porttitor lacus luctus accumsan tortor. Tristique senectus et netus et. Sed euismod nisi porta lorem mollis. Sit amet justo donec enim diam. Viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Placerat vestibulum lectus mauris ultrices eros in cursus turpis. Morbi tristique senectus et netus et malesuada fames ac. Turpis in eu mi bibendum neque egestas. Diam in arcu cursus euismod quis viverra nibh cras pulvinar. Pretium lectus quam id leo in vitae turpis massa. Massa ultricies mi quis hendrerit. Eget est lorem ipsum dolor sit. A erat nam at lectus. - -Hac habitasse platea dictumst quisque sagittis. Orci dapibus ultrices in iaculis nunc. Libero justo laoreet sit amet cursus sit amet. Aliquam malesuada bibendum arcu vitae elementum curabitur. Mi eget mauris pharetra et. Egestas pretium aenean pharetra magna. Nisl purus in mollis nunc sed id semper risus in. Feugiat in fermentum posuere urna nec tincidunt. Dictum fusce ut placerat orci nulla pellentesque dignissim enim. Quis imperdiet massa tincidunt nunc. Sit amet purus gravida quis. Dignissim diam quis enim lobortis. At risus viverra adipiscing at in tellus integer feugiat. Mollis nunc sed id semper. Cras semper auctor neque vitae tempus quam pellentesque nec nam. At risus viverra adipiscing at in tellus integer feugiat scelerisque. Mauris ultrices eros in cursus turpis massa. - -Mattis molestie a iaculis at erat pellentesque adipiscing. Enim lobortis scelerisque fermentum dui faucibus. Tincidunt vitae semper quis lectus nulla. Turpis cursus in hac habitasse platea dictumst quisque sagittis. Nulla facilisi cras fermentum odio eu feugiat pretium nibh ipsum. Lorem donec massa sapien faucibus et. Suspendisse interdum consectetur libero id faucibus. Sollicitudin aliquam ultrices sagittis orci a scelerisque purus. Dictum fusce ut placerat orci nulla. Blandit volutpat maecenas volutpat blandit aliquam. Dictum non consectetur a erat nam at lectus urna duis. - -Sem et tortor consequat id porta nibh. Tellus mauris a diam maecenas. Pulvinar elementum integer enim neque volutpat. Quisque non tellus orci ac auctor augue. Turpis tincidunt id aliquet risus feugiat in ante metus dictum. Auctor elit sed vulputate mi sit amet. Ipsum dolor sit amet consectetur. Amet nulla facilisi morbi tempus iaculis urna id. Aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices sagittis. Vitae purus faucibus ornare suspendisse sed nisi. - -Purus faucibus ornare suspendisse sed nisi lacus. Amet nisl purus in mollis nunc. Elit at imperdiet dui accumsan sit amet nulla facilisi morbi. Ac tortor dignissim convallis aenean et tortor at. Convallis a cras semper auctor neque vitae tempus quam. Netus et malesuada fames ac turpis. Nunc sed augue lacus viverra vitae. Ut etiam sit amet nisl purus in mollis. Iaculis nunc sed augue lacus viverra. A iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Turpis in eu mi bibendum neque egestas congue quisque egestas. Aliquet eget sit amet tellus cras adipiscing enim eu. Ut eu sem integer vitae justo eget magna. Varius morbi enim nunc faucibus a pellentesque sit. Tristique sollicitudin nibh sit amet. - -Nulla facilisi cras fermentum odio eu feugiat pretium. Auctor elit sed vulputate mi sit amet. Nunc pulvinar sapien et ligula ullamcorper. Vitae turpis massa sed elementum tempus egestas sed sed risus. Risus quis varius quam quisque id diam vel quam. Tempus egestas sed sed risus pretium quam vulputate dignissim. Libero volutpat sed cras ornare arcu. Pellentesque nec nam aliquam sem et tortor. Magna ac placerat vestibulum lectus mauris ultrices eros in cursus. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam. Et netus et malesuada fames ac turpis egestas integer. Sed ullamcorper morbi tincidunt ornare massa eget egestas purus viverra. Lacus suspendisse faucibus interdum posuere lorem ipsum dolor. Elit pellentesque habitant morbi tristique senectus et netus et malesuada. Massa sapien faucibus et molestie ac. Venenatis cras sed felis eget velit. Nisi porta lorem mollis aliquam ut porttitor leo a. Libero justo laoreet sit amet cursus sit amet. Quis auctor elit sed vulputate mi sit amet mauris commodo. - -Est ante in nibh mauris. Eu sem integer vitae justo eget magna fermentum iaculis. In dictum non consectetur a erat nam. Ultrices in iaculis nunc sed augue lacus viverra. Sit amet consectetur adipiscing elit ut aliquam purus. Ipsum faucibus vitae aliquet nec ullamcorper sit amet risus nullam. Volutpat consequat mauris nunc congue nisi vitae suscipit tellus mauris. Congue eu consequat ac felis donec et odio. Venenatis tellus in metus vulputate eu scelerisque felis imperdiet. Proin fermentum leo vel orci. Egestas integer eget aliquet nibh praesent. Ut pharetra sit amet aliquam id diam. Sit amet est placerat in egestas. Rutrum tellus pellentesque eu tincidunt. Rhoncus aenean vel elit scelerisque mauris. Non sodales neque sodales ut etiam sit amet nisl purus. Duis ut diam quam nulla. Amet dictum sit amet justo donec enim. Feugiat pretium nibh ipsum consequat nisl. Aliquet risus feugiat in ante metus. - -Elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Mauris rhoncus aenean vel elit scelerisque mauris. At volutpat diam ut venenatis tellus in. Tempus urna et pharetra pharetra massa. Eu turpis egestas pretium aenean. Blandit aliquam etiam erat velit scelerisque in dictum. A condimentum vitae sapien pellentesque habitant morbi. Proin fermentum leo vel orci porta non pulvinar. Amet mattis vulputate enim nulla aliquet porttitor. Lorem sed risus ultricies tristique nulla aliquet enim tortor. Lectus urna duis convallis convallis. Tempor commodo ullamcorper a lacus vestibulum sed. Morbi leo urna molestie at elementum eu facilisis. - -Pellentesque habitant morbi tristique senectus et netus. Enim praesent elementum facilisis leo vel fringilla est ullamcorper eget. Elementum facilisis leo vel fringilla est ullamcorper. Cras ornare arcu dui vivamus arcu. Sem viverra aliquet eget sit. Posuere morbi leo urna molestie at elementum eu facilisis. Tincidunt augue interdum velit euismod in. In ornare quam viverra orci sagittis eu volutpat. Fringilla urna porttitor rhoncus dolor purus. Senectus et netus et malesuada fames ac turpis. Vel risus commodo viverra maecenas accumsan. Neque vitae tempus quam pellentesque nec nam aliquam sem. Eget felis eget nunc lobortis mattis aliquam faucibus purus in. Amet tellus cras adipiscing enim. - -Facilisis volutpat est velit egestas dui. Sit amet mattis vulputate enim nulla aliquet. Cursus turpis massa tincidunt dui. Quisque id diam vel quam elementum pulvinar. A lacus vestibulum sed arcu non odio euismod. At volutpat diam ut venenatis tellus in metus vulputate. Non arcu risus quis varius. Ultrices sagittis orci a scelerisque purus semper eget. Massa eget egestas purus viverra accumsan. Neque laoreet suspendisse interdum consectetur libero id faucibus nisl. - -Nisi est sit amet facilisis magna etiam tempor orci eu. Et malesuada fames ac turpis. Mauris nunc congue nisi vitae suscipit tellus. At urna condimentum mattis pellentesque id. Purus non enim praesent elementum facilisis. Aliquam sem et tortor consequat id. Odio ut enim blandit volutpat maecenas volutpat. Ultrices in iaculis nunc sed augue lacus viverra vitae congue. At in tellus integer feugiat scelerisque varius. Nisi quis eleifend quam adipiscing vitae proin sagittis. Morbi non arcu risus quis varius quam quisque id diam. Purus in massa tempor nec feugiat nisl. Arcu dui vivamus arcu felis bibendum. Tristique senectus et netus et malesuada fames ac turpis egestas. Morbi enim nunc faucibus a pellentesque. - -Aliquam eleifend mi in nulla. Mi quis hendrerit dolor magna eget est lorem. Nisl pretium fusce id velit ut tortor pretium viverra suspendisse. Arcu cursus vitae congue mauris rhoncus aenean. Proin sed libero enim sed faucibus turpis in eu. Quis varius quam quisque id diam vel quam. Ac tortor dignissim convallis aenean et. Praesent semper feugiat nibh sed pulvinar proin gravida hendrerit lectus. Sagittis aliquam malesuada bibendum arcu vitae elementum curabitur vitae. Tellus in hac habitasse platea dictumst vestibulum. Nunc eget lorem dolor sed viverra ipsum. Id semper risus in hendrerit gravida rutrum quisque. Odio ut sem nulla pharetra diam. Nibh tellus molestie nunc non blandit. Elementum nibh tellus molestie nunc. - -Cursus metus aliquam eleifend mi in nulla. Commodo viverra maecenas accumsan lacus vel facilisis volutpat est velit. Duis tristique sollicitudin nibh sit amet commodo nulla facilisi. Eu ultrices vitae auctor eu augue ut. Elementum tempus egestas sed sed. Odio eu feugiat pretium nibh ipsum consequat nisl vel pretium. A lacus vestibulum sed arcu non odio euismod lacinia. Eu ultrices vitae auctor eu augue. Amet nisl suscipit adipiscing bibendum est ultricies integer. Tristique magna sit amet purus gravida quis. Enim neque volutpat ac tincidunt vitae semper. Penatibus et magnis dis parturient montes nascetur ridiculus mus. Elementum curabitur vitae nunc sed velit. Dolor purus non enim praesent. Gravida dictum fusce ut placerat orci nulla. Aliquam sem et tortor consequat id porta. Bibendum at varius vel pharetra vel turpis nunc eget lorem. Diam vulputate ut pharetra sit amet aliquam id. Vulputate odio ut enim blandit volutpat maecenas volutpat blandit. - -Risus nullam eget felis eget nunc. Gravida cum sociis natoque penatibus et magnis dis parturient. Ultrices dui sapien eget mi proin sed libero enim sed. Mattis aliquam faucibus purus in massa tempor nec feugiat nisl. Pulvinar pellentesque habitant morbi tristique senectus et netus. Nisi vitae suscipit tellus mauris a diam maecenas sed. In egestas erat imperdiet sed euismod nisi. Mattis nunc sed blandit libero volutpat sed. Adipiscing at in tellus integer feugiat scelerisque varius morbi enim. Aliquet sagittis id consectetur purus ut faucibus pulvinar elementum. Nisi scelerisque eu ultrices vitae auctor. Suscipit tellus mauris a diam maecenas sed enim ut sem. Ac feugiat sed lectus vestibulum mattis. Quis ipsum suspendisse ultrices gravida. Semper viverra nam libero justo laoreet. Ornare aenean euismod elementum nisi. Et egestas quis ipsum suspendisse. Gravida in fermentum et sollicitudin ac orci phasellus egestas. Pellentesque habitant morbi tristique senectus et netus et. At augue eget arcu dictum. - -Id porta nibh venenatis cras. Penatibus et magnis dis parturient montes nascetur. Velit scelerisque in dictum non consectetur a erat nam at. Tellus in metus vulputate eu scelerisque felis imperdiet proin. Suspendisse faucibus interdum posuere lorem ipsum. Viverra justo nec ultrices dui sapien. Tempor orci eu lobortis elementum nibh tellus molestie nunc non. Metus vulputate eu scelerisque felis imperdiet proin fermentum leo vel. Risus viverra adipiscing at in tellus integer feugiat scelerisque. A cras semper auctor neque. A pellentesque sit amet porttitor eget dolor morbi non arcu. Nunc consequat interdum varius sit amet mattis vulputate enim. Vulputate sapien nec sagittis aliquam malesuada. Iaculis nunc sed augue lacus viverra vitae congue eu. Enim nulla aliquet porttitor lacus luctus. Enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra. A condimentum vitae sapien pellentesque habitant morbi tristique senectus et. - -Ipsum nunc aliquet bibendum enim facilisis gravida neque convallis a. Congue quisque egestas diam in arcu. Quis ipsum suspendisse ultrices gravida dictum fusce ut placerat. Parturient montes nascetur ridiculus mus mauris vitae. Elit pellentesque habitant morbi tristique senectus. Et pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Purus gravida quis blandit turpis cursus in hac habitasse platea. Eu augue ut lectus arcu bibendum at varius vel. Semper eget duis at tellus at urna. Ut placerat orci nulla pellentesque dignissim enim sit amet venenatis. Lectus mauris ultrices eros in cursus turpis massa. Cursus euismod quis viverra nibh. Gravida in fermentum et sollicitudin ac orci phasellus egestas. Nisi quis eleifend quam adipiscing vitae proin. Velit euismod in pellentesque massa placerat duis ultricies. Mauris nunc congue nisi vitae suscipit tellus. - -Dui nunc mattis enim ut. Placerat orci nulla pellentesque dignissim enim sit amet venenatis urna. Ac tortor dignissim convallis aenean et tortor at. Quis vel eros donec ac odio tempor. Volutpat odio facilisis mauris sit amet. Sapien faucibus et molestie ac feugiat sed lectus. Dictum varius duis at consectetur lorem donec massa sapien. Donec adipiscing tristique risus nec feugiat in fermentum posuere urna. Amet volutpat consequat mauris nunc congue nisi vitae suscipit. Cursus vitae congue mauris rhoncus aenean vel. Eu volutpat odio facilisis mauris sit amet. Eu feugiat pretium nibh ipsum consequat nisl vel pretium. - -Lacus suspendisse faucibus interdum posuere. At elementum eu facilisis sed odio morbi. Et odio pellentesque diam volutpat commodo sed egestas. Molestie a iaculis at erat pellentesque adipiscing commodo elit. Nisi quis eleifend quam adipiscing vitae proin. Vel pretium lectus quam id leo in. Convallis tellus id interdum velit. Sed tempus urna et pharetra pharetra. Duis ut diam quam nulla porttitor massa id neque aliquam. Nisl purus in mollis nunc sed. Vulputate enim nulla aliquet porttitor lacus luctus accumsan. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Euismod elementum nisi quis eleifend. Sed sed risus pretium quam vulputate dignissim. Neque laoreet suspendisse interdum consectetur libero id. In massa tempor nec feugiat nisl pretium. Morbi tristique senectus et netus. - -Etiam dignissim diam quis enim lobortis scelerisque. Diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Ipsum dolor sit amet consectetur adipiscing. Vel pharetra vel turpis nunc. Sed nisi lacus sed viverra tellus in hac. Est placerat in egestas erat. Ut enim blandit volutpat maecenas volutpat. Non arcu risus quis varius quam quisque id. Nec ultrices dui sapien eget mi. Donec ac odio tempor orci dapibus. - -Consectetur libero id faucibus nisl. Nullam non nisi est sit amet facilisis magna etiam. Consequat interdum varius sit amet mattis vulputate. Aliquet sagittis id consectetur purus ut faucibus. Nulla malesuada pellentesque elit eget gravida cum sociis. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt. Nec feugiat in fermentum posuere. Est ullamcorper eget nulla facilisi etiam. Adipiscing commodo elit at imperdiet dui accumsan sit. Sit amet dictum sit amet justo donec. - -Condimentum lacinia quis vel eros donec ac. Elit duis tristique sollicitudin nibh sit. Tortor id aliquet lectus proin nibh nisl condimentum id venenatis. Vitae tempus quam pellentesque nec nam aliquam sem et. Non enim praesent elementum facilisis leo vel fringilla est ullamcorper. Metus aliquam eleifend mi in nulla posuere sollicitudin. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis. Tincidunt vitae semper quis lectus. Dictum fusce ut placerat orci nulla pellentesque dignissim. Ut sem nulla pharetra diam sit amet nisl suscipit adipiscing. Ipsum consequat nisl vel pretium lectus quam. - -Odio morbi quis commodo odio aenean sed adipiscing diam. Est velit egestas dui id ornare arcu odio ut sem. Ac tortor vitae purus faucibus ornare suspendisse sed. Hac habitasse platea dictumst quisque. Arcu odio ut sem nulla. Dignissim convallis aenean et tortor at risus viverra adipiscing. At volutpat diam ut venenatis. Consequat id porta nibh venenatis cras sed. Amet volutpat consequat mauris nunc. Aliquet nibh praesent tristique magna sit amet. - -Convallis convallis tellus id interdum velit. Cras adipiscing enim eu turpis egestas pretium aenean. Tempor commodo ullamcorper a lacus vestibulum. In massa tempor nec feugiat nisl pretium. Amet volutpat consequat mauris nunc congue nisi vitae suscipit tellus. Rhoncus aenean vel elit scelerisque mauris. Vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Mauris vitae ultricies leo integer malesuada. Turpis nunc eget lorem dolor sed viverra ipsum nunc. Morbi non arcu risus quis varius quam quisque id diam. Odio morbi quis commodo odio aenean. Blandit massa enim nec dui nunc mattis enim. Nullam non nisi est sit amet facilisis. Scelerisque in dictum non consectetur a erat nam at. Turpis in eu mi bibendum neque. Placerat orci nulla pellentesque dignissim enim. Lacus vestibulum sed arcu non. Nisi est sit amet facilisis magna etiam tempor orci eu. - -Scelerisque fermentum dui faucibus in ornare quam viverra. Varius duis at consectetur lorem donec massa sapien faucibus. Accumsan tortor posuere ac ut consequat semper viverra. Curabitur gravida arcu ac tortor dignissim convallis aenean. Scelerisque eu ultrices vitae auctor. Elit ut aliquam purus sit amet luctus venenatis lectus. Nulla pellentesque dignissim enim sit. Lacus viverra vitae congue eu. Enim eu turpis egestas pretium aenean pharetra magna ac placerat. Mi in nulla posuere sollicitudin aliquam ultrices sagittis. Erat nam at lectus urna duis convallis convallis. Et molestie ac feugiat sed lectus. Sagittis vitae et leo duis ut diam. Id diam maecenas ultricies mi. Tempus quam pellentesque nec nam. Sem et tortor consequat id porta nibh venenatis cras. Eu mi bibendum neque egestas congue quisque egestas. Scelerisque purus semper eget duis at tellus at urna condimentum. Orci a scelerisque purus semper eget duis at. - -Facilisi morbi tempus iaculis urna id volutpat lacus. Vitae tortor condimentum lacinia quis vel eros donec. Molestie nunc non blandit massa. Urna et pharetra pharetra massa massa ultricies mi. Netus et malesuada fames ac turpis egestas sed tempus. Pretium aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Nibh sed pulvinar proin gravida hendrerit lectus a. Nisl nunc mi ipsum faucibus vitae aliquet nec. Sit amet nisl suscipit adipiscing bibendum est. Maecenas volutpat blandit aliquam etiam erat velit scelerisque in. - -Habitant morbi tristique senectus et netus et malesuada fames. Mauris cursus mattis molestie a iaculis. Gravida quis blandit turpis cursus in hac habitasse. Velit egestas dui id ornare arcu. Egestas purus viverra accumsan in nisl nisi scelerisque. Eget gravida cum sociis natoque. Volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque. Vel facilisis volutpat est velit egestas dui id ornare arcu. Sed viverra tellus in hac habitasse platea dictumst vestibulum rhoncus. Semper viverra nam libero justo. Maecenas accumsan lacus vel facilisis volutpat est velit egestas dui. - -Fusce id velit ut tortor pretium viverra suspendisse potenti. Interdum consectetur libero id faucibus nisl. Odio euismod lacinia at quis risus. Amet purus gravida quis blandit turpis cursus in. Est velit egestas dui id ornare arcu odio ut sem. Egestas quis ipsum suspendisse ultrices gravida. Lectus mauris ultrices eros in cursus. Egestas diam in arcu cursus euismod. Ultrices vitae auctor eu augue ut lectus arcu bibendum at. Mattis pellentesque id nibh tortor. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget gravida. Urna nunc id cursus metus aliquam eleifend mi. Morbi quis commodo odio aenean. In egestas erat imperdiet sed. Porta lorem mollis aliquam ut porttitor leo. Nisl condimentum id venenatis a. Nulla facilisi cras fermentum odio eu feugiat pretium. Sed risus pretium quam vulputate dignissim suspendisse in est. Scelerisque varius morbi enim nunc faucibus. Ultricies mi eget mauris pharetra et ultrices neque ornare aenean. - -Vulputate mi sit amet mauris commodo. Pharetra pharetra massa massa ultricies mi quis hendrerit dolor. Et ligula ullamcorper malesuada proin libero nunc consequat interdum varius. Mi eget mauris pharetra et ultrices neque ornare. Aenean vel elit scelerisque mauris pellentesque pulvinar. Amet dictum sit amet justo donec enim. Massa tincidunt dui ut ornare lectus sit amet est placerat. Quis blandit turpis cursus in hac habitasse. Dignissim sodales ut eu sem integer vitae justo eget magna. Nunc sed velit dignissim sodales ut eu sem integer. Cursus eget nunc scelerisque viverra mauris in. Proin sed libero enim sed faucibus turpis in eu. Sit amet consectetur adipiscing elit duis. Lorem mollis aliquam ut porttitor leo a diam. Ut placerat orci nulla pellentesque dignissim. Tincidunt lobortis feugiat vivamus at augue. Sed cras ornare arcu dui vivamus arcu. Id aliquet lectus proin nibh nisl condimentum. At consectetur lorem donec massa sapien faucibus et molestie. Molestie a iaculis at erat. - -Vitae turpis massa sed elementum tempus egestas. Eget felis eget nunc lobortis. Orci ac auctor augue mauris. Sapien pellentesque habitant morbi tristique senectus et netus. Enim nulla aliquet porttitor lacus luctus accumsan. Enim lobortis scelerisque fermentum dui faucibus in. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Pulvinar sapien et ligula ullamcorper malesuada proin. Quis varius quam quisque id. Nullam vehicula ipsum a arcu cursus vitae congue mauris rhoncus. Ac ut consequat semper viverra nam libero justo laoreet sit. Metus dictum at tempor commodo ullamcorper a lacus vestibulum. Venenatis a condimentum vitae sapien pellentesque habitant morbi. Massa ultricies mi quis hendrerit dolor magna. Pharetra massa massa ultricies mi quis hendrerit dolor. Est lorem ipsum dolor sit. Vestibulum sed arcu non odio euismod lacinia at. Posuere sollicitudin aliquam ultrices sagittis orci a. - -Morbi quis commodo odio aenean sed adipiscing diam. Nisl rhoncus mattis rhoncus urna neque. Nunc congue nisi vitae suscipit tellus mauris a diam. Mattis nunc sed blandit libero volutpat sed cras. Dictum fusce ut placerat orci nulla pellentesque dignissim. Eu nisl nunc mi ipsum faucibus vitae. Etiam non quam lacus suspendisse faucibus interdum. Dictum non consectetur a erat nam at lectus urna duis. Nulla pellentesque dignissim enim sit amet venenatis urna cursus. Amet justo donec enim diam vulputate ut pharetra sit amet. Lacus suspendisse faucibus interdum posuere. Nulla facilisi morbi tempus iaculis. Mauris a diam maecenas sed enim ut sem viverra aliquet. Euismod elementum nisi quis eleifend quam adipiscing vitae. Consectetur libero id faucibus nisl tincidunt eget nullam. - -Integer quis auctor elit sed vulputate. Ipsum dolor sit amet consectetur adipiscing elit duis tristique sollicitudin. Tellus integer feugiat scelerisque varius morbi enim. Sed tempus urna et pharetra pharetra massa massa ultricies mi. Massa id neque aliquam vestibulum morbi. Enim ut tellus elementum sagittis vitae et leo duis ut. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Magna etiam tempor orci eu. Urna molestie at elementum eu facilisis sed odio morbi quis. Bibendum arcu vitae elementum curabitur vitae nunc sed. Sapien et ligula ullamcorper malesuada proin libero. Egestas diam in arcu cursus euismod quis viverra nibh. Quis risus sed vulputate odio ut enim blandit. Tristique senectus et netus et malesuada fames ac. Felis eget nunc lobortis mattis aliquam. Mi proin sed libero enim. Commodo nulla facilisi nullam vehicula. - -A cras semper auctor neque vitae. Urna duis convallis convallis tellus id interdum velit laoreet id. Adipiscing enim eu turpis egestas pretium. Tellus in hac habitasse platea. Odio facilisis mauris sit amet massa vitae tortor. Condimentum id venenatis a condimentum vitae. Etiam erat velit scelerisque in dictum non consectetur. Mollis nunc sed id semper risus in. Amet nisl suscipit adipiscing bibendum. Mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare. Sodales ut etiam sit amet nisl purus in mollis. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. At tempor commodo ullamcorper a. Amet nisl purus in mollis nunc sed id. Interdum velit laoreet id donec ultrices tincidunt arcu non. Placerat vestibulum lectus mauris ultrices. Non tellus orci ac auctor augue mauris augue. Aliquam ultrices sagittis orci a. - -Id velit ut tortor pretium viverra suspendisse potenti nullam ac. Nisi est sit amet facilisis magna etiam tempor. Varius duis at consectetur lorem donec massa sapien faucibus. Et odio pellentesque diam volutpat. Adipiscing enim eu turpis egestas pretium. Consectetur adipiscing elit ut aliquam purus. Pellentesque nec nam aliquam sem et tortor consequat id porta. Mattis vulputate enim nulla aliquet porttitor lacus luctus accumsan. Duis tristique sollicitudin nibh sit amet commodo nulla. Amet purus gravida quis blandit turpis cursus. Senectus et netus et malesuada fames ac turpis egestas. Feugiat nisl pretium fusce id velit ut. Consequat semper viverra nam libero. Pellentesque dignissim enim sit amet. Libero nunc consequat interdum varius sit amet. Est velit egestas dui id. - -Est placerat in egestas erat imperdiet sed. Neque vitae tempus quam pellentesque nec nam aliquam sem et. Mi tempus imperdiet nulla malesuada pellentesque. Et malesuada fames ac turpis egestas maecenas pharetra. Volutpat ac tincidunt vitae semper quis lectus nulla at. Aliquam sem et tortor consequat. Scelerisque purus semper eget duis at tellus at urna. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Eu nisl nunc mi ipsum faucibus vitae aliquet. Tristique senectus et netus et malesuada fames. Semper viverra nam libero justo. Fermentum posuere urna nec tincidunt praesent semper feugiat nibh. Enim ut sem viverra aliquet eget sit amet tellus. Auctor eu augue ut lectus arcu bibendum. Nunc pulvinar sapien et ligula ullamcorper malesuada proin libero. Lectus proin nibh nisl condimentum id venenatis a condimentum vitae. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Praesent tristique magna sit amet purus gravida. Laoreet suspendisse interdum consectetur libero id. Pellentesque nec nam aliquam sem. - -Nibh venenatis cras sed felis eget velit aliquet sagittis id. Enim facilisis gravida neque convallis a cras semper. Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula ullamcorper. Morbi quis commodo odio aenean. At urna condimentum mattis pellentesque id nibh tortor. Sed arcu non odio euismod. Nunc sed velit dignissim sodales ut eu sem integer. Euismod elementum nisi quis eleifend quam adipiscing vitae proin. Non sodales neque sodales ut etiam sit amet nisl. Feugiat in ante metus dictum at. Libero enim sed faucibus turpis in. Sagittis vitae et leo duis ut diam quam nulla porttitor. Ullamcorper eget nulla facilisi etiam dignissim diam. - -Posuere urna nec tincidunt praesent semper feugiat nibh. Justo laoreet sit amet cursus. Amet purus gravida quis blandit turpis cursus in hac. Mauris cursus mattis molestie a iaculis at erat. Justo nec ultrices dui sapien eget mi proin. Sit amet commodo nulla facilisi. A lacus vestibulum sed arcu non odio. Risus in hendrerit gravida rutrum quisque non. Eros donec ac odio tempor. Habitasse platea dictumst vestibulum rhoncus est pellentesque. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus. Praesent tristique magna sit amet purus gravida quis. Ut aliquam purus sit amet. Vitae semper quis lectus nulla at volutpat diam ut venenatis. Amet consectetur adipiscing elit ut. Blandit volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque. Id eu nisl nunc mi ipsum faucibus vitae aliquet. Aliquam etiam erat velit scelerisque in dictum non consectetur a. - -Venenatis lectus magna fringilla urna. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. Adipiscing tristique risus nec feugiat in fermentum posuere. Arcu dui vivamus arcu felis bibendum ut tristique et egestas. Sed viverra tellus in hac habitasse platea dictumst vestibulum. Quisque sagittis purus sit amet volutpat consequat mauris nunc. Neque gravida in fermentum et sollicitudin ac. Ac placerat vestibulum lectus mauris ultrices eros in. Risus ultricies tristique nulla aliquet enim tortor at. Posuere sollicitudin aliquam ultrices sagittis. Feugiat in ante metus dictum. At augue eget arcu dictum. Suspendisse sed nisi lacus sed. Nascetur ridiculus mus mauris vitae ultricies leo. Maecenas pharetra convallis posuere morbi leo urna. Sit amet est placerat in egestas erat imperdiet sed. Mi in nulla posuere sollicitudin aliquam ultrices sagittis orci a. In metus vulputate eu scelerisque. - -Bibendum ut tristique et egestas quis ipsum. Aenean sed adipiscing diam donec. In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Elementum sagittis vitae et leo duis. Egestas quis ipsum suspendisse ultrices. Risus at ultrices mi tempus imperdiet nulla malesuada. Massa tincidunt nunc pulvinar sapien et ligula. Ut etiam sit amet nisl purus in mollis nunc sed. Amet aliquam id diam maecenas ultricies mi. Dapibus ultrices in iaculis nunc sed augue lacus. Enim sit amet venenatis urna. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo nulla. Gravida quis blandit turpis cursus. Tempor commodo ullamcorper a lacus vestibulum. Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere. Scelerisque felis imperdiet proin fermentum leo vel orci. - -Auctor eu augue ut lectus arcu. Dui id ornare arcu odio ut sem nulla pharetra. Donec ultrices tincidunt arcu non sodales neque sodales ut etiam. Morbi tristique senectus et netus et malesuada fames ac. Justo nec ultrices dui sapien eget mi proin sed. Arcu cursus euismod quis viverra nibh cras pulvinar. Elementum pulvinar etiam non quam lacus suspendisse faucibus interdum posuere. Dictum non consectetur a erat nam. A erat nam at lectus urna duis convallis convallis tellus. Est placerat in egestas erat imperdiet sed euismod nisi. Enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra. Cursus metus aliquam eleifend mi in nulla posuere sollicitudin aliquam. Eget nunc scelerisque viverra mauris in aliquam sem fringilla ut. Velit scelerisque in dictum non consectetur. In metus vulputate eu scelerisque felis imperdiet proin fermentum leo. Proin libero nunc consequat interdum varius. Sit amet commodo nulla facilisi nullam vehicula ipsum a arcu. Orci a scelerisque purus semper eget duis. - -Sem viverra aliquet eget sit amet tellus cras adipiscing. Phasellus faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis. Id aliquet lectus proin nibh nisl. Integer vitae justo eget magna fermentum iaculis. Volutpat odio facilisis mauris sit amet massa. Convallis a cras semper auctor neque vitae tempus. Id interdum velit laoreet id. Odio eu feugiat pretium nibh ipsum consequat nisl vel. Enim nunc faucibus a pellentesque. At urna condimentum mattis pellentesque id. Maecenas pharetra convallis posuere morbi leo urna. Enim sed faucibus turpis in eu. Enim tortor at auctor urna nunc id cursus metus. Eget nunc scelerisque viverra mauris in. Pulvinar proin gravida hendrerit lectus. Mi sit amet mauris commodo. Viverra nam libero justo laoreet. - -Id venenatis a condimentum vitae sapien pellentesque habitant. Nibh sed pulvinar proin gravida hendrerit lectus. Duis at consectetur lorem donec massa sapien faucibus et molestie. Volutpat ac tincidunt vitae semper quis lectus nulla. Eget mi proin sed libero enim sed faucibus. Faucibus et molestie ac feugiat. Velit dignissim sodales ut eu sem. Mollis aliquam ut porttitor leo a diam sollicitudin. Gravida quis blandit turpis cursus. Nullam eget felis eget nunc lobortis mattis aliquam faucibus. Tincidunt tortor aliquam nulla facilisi cras fermentum odio. Non diam phasellus vestibulum lorem sed risus. Sodales neque sodales ut etiam sit amet nisl. Duis at tellus at urna condimentum mattis pellentesque id. Gravida quis blandit turpis cursus in hac habitasse platea. - -Ligula ullamcorper malesuada proin libero nunc consequat interdum varius. At quis risus sed vulputate odio ut enim. Congue mauris rhoncus aenean vel elit scelerisque. Laoreet suspendisse interdum consectetur libero id faucibus nisl. Ultricies mi eget mauris pharetra et ultrices. At tellus at urna condimentum mattis pellentesque id. Dui accumsan sit amet nulla facilisi. Ultrices in iaculis nunc sed augue. Massa id neque aliquam vestibulum morbi. Ipsum dolor sit amet consectetur adipiscing elit ut. Faucibus turpis in eu mi bibendum neque egestas. - -Leo vel fringilla est ullamcorper. Platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Et ultrices neque ornare aenean euismod. Convallis convallis tellus id interdum velit laoreet id donec. Odio tempor orci dapibus ultrices. Pretium quam vulputate dignissim suspendisse in est ante. Pellentesque eu tincidunt tortor aliquam nulla facilisi. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Adipiscing commodo elit at imperdiet dui accumsan sit amet nulla. Dui ut ornare lectus sit amet est placerat in. Convallis posuere morbi leo urna molestie at elementum eu facilisis. Tincidunt eget nullam non nisi est. - -Posuere morbi leo urna molestie at elementum eu. Duis at tellus at urna condimentum mattis pellentesque id. Velit dignissim sodales ut eu sem. Id venenatis a condimentum vitae sapien pellentesque habitant morbi. Maecenas sed enim ut sem viverra. Ut sem nulla pharetra diam sit amet. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Pretium nibh ipsum consequat nisl vel pretium. Hac habitasse platea dictumst vestibulum rhoncus. Vitae et leo duis ut diam quam nulla porttitor massa. Sociis natoque penatibus et magnis dis parturient montes nascetur. Vitae tortor condimentum lacinia quis vel eros. Id ornare arcu odio ut sem. Consectetur adipiscing elit duis tristique. Aliquet enim tortor at auctor urna nunc id cursus. Tincidunt dui ut ornare lectus. Eget nunc lobortis mattis aliquam faucibus purus in. Tristique magna sit amet purus gravida quis blandit turpis. - -Amet tellus cras adipiscing enim eu turpis egestas pretium aenean. Vestibulum sed arcu non odio euismod. Ipsum dolor sit amet consectetur adipiscing elit. Ut eu sem integer vitae justo eget magna fermentum. Lectus arcu bibendum at varius vel. Egestas erat imperdiet sed euismod nisi porta lorem. Nulla facilisi morbi tempus iaculis urna id volutpat lacus laoreet. Volutpat ac tincidunt vitae semper quis lectus nulla at. Dictum varius duis at consectetur. Porta non pulvinar neque laoreet. Duis ut diam quam nulla. Eget arcu dictum varius duis. Tellus integer feugiat scelerisque varius morbi enim nunc. Consectetur libero id faucibus nisl tincidunt eget nullam. Mus mauris vitae ultricies leo. Amet mattis vulputate enim nulla. Eget duis at tellus at urna condimentum. Cursus eget nunc scelerisque viverra mauris in. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar. - -Nulla porttitor massa id neque. In hendrerit gravida rutrum quisque non tellus orci ac. Mi sit amet mauris commodo. Pellentesque habitant morbi tristique senectus et netus et. Enim ut tellus elementum sagittis. Ut ornare lectus sit amet est placerat in. Lectus proin nibh nisl condimentum id venenatis a condimentum. Vel fringilla est ullamcorper eget nulla. Augue interdum velit euismod in. Volutpat ac tincidunt vitae semper. Lobortis elementum nibh tellus molestie nunc. Montes nascetur ridiculus mus mauris vitae ultricies. Urna porttitor rhoncus dolor purus non. Quis blandit turpis cursus in hac habitasse. Fermentum leo vel orci porta non pulvinar neque. Augue interdum velit euismod in. Fames ac turpis egestas sed tempus. - -Sociis natoque penatibus et magnis dis parturient. Dis parturient montes nascetur ridiculus mus mauris. A iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Adipiscing tristique risus nec feugiat in. In hac habitasse platea dictumst quisque sagittis purus sit. Non diam phasellus vestibulum lorem sed risus ultricies tristique. Egestas dui id ornare arcu. Tincidunt tortor aliquam nulla facilisi cras. Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere ac. Mattis aliquam faucibus purus in massa tempor. Viverra maecenas accumsan lacus vel facilisis. Semper feugiat nibh sed pulvinar proin gravida. Nunc aliquet bibendum enim facilisis gravida neque. Aliquam etiam erat velit scelerisque in. Ac placerat vestibulum lectus mauris ultrices eros in cursus. - -Ac placerat vestibulum lectus mauris ultrices eros in. Proin sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing. Convallis convallis tellus id interdum. Purus sit amet volutpat consequat. Faucibus nisl tincidunt eget nullam non nisi est sit. Est ullamcorper eget nulla facilisi etiam dignissim diam. Maecenas accumsan lacus vel facilisis volutpat est velit. Mollis aliquam ut porttitor leo. Et netus et malesuada fames ac turpis egestas. Id nibh tortor id aliquet lectus proin nibh. Ornare suspendisse sed nisi lacus. Adipiscing vitae proin sagittis nisl rhoncus mattis. Ipsum dolor sit amet consectetur adipiscing. Porta nibh venenatis cras sed felis eget velit aliquet sagittis. - -Sagittis aliquam malesuada bibendum arcu. Ut tristique et egestas quis ipsum suspendisse ultrices. Ut aliquam purus sit amet luctus venenatis lectus magna fringilla. A condimentum vitae sapien pellentesque habitant morbi tristique senectus. Neque laoreet suspendisse interdum consectetur libero id faucibus nisl tincidunt. Morbi tristique senectus et netus et malesuada fames ac. Ullamcorper sit amet risus nullam eget felis eget. Sed risus ultricies tristique nulla aliquet. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Massa vitae tortor condimentum lacinia quis vel eros donec. Eu mi bibendum neque egestas congue quisque. Arcu odio ut sem nulla. Cursus turpis massa tincidunt dui. - -Egestas fringilla phasellus faucibus scelerisque eleifend. Aliquet nibh praesent tristique magna sit amet. Et ultrices neque ornare aenean euismod elementum nisi quis eleifend. In ornare quam viverra orci. Aenean vel elit scelerisque mauris pellentesque pulvinar. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Lacus sed turpis tincidunt id aliquet. Convallis posuere morbi leo urna. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. At in tellus integer feugiat scelerisque varius. Ipsum faucibus vitae aliquet nec ullamcorper sit amet. Ullamcorper morbi tincidunt ornare massa eget. Faucibus purus in massa tempor. - -Habitant morbi tristique senectus et netus et malesuada fames ac. Tristique senectus et netus et. Sit amet mauris commodo quis imperdiet massa. Nulla malesuada pellentesque elit eget gravida cum sociis natoque. Volutpat blandit aliquam etiam erat velit scelerisque in. Tellus id interdum velit laoreet id donec. Adipiscing commodo elit at imperdiet dui accumsan sit amet. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Dignissim sodales ut eu sem integer vitae justo eget magna. Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus. Libero volutpat sed cras ornare arcu dui. - -Adipiscing at in tellus integer feugiat. Tincidunt vitae semper quis lectus nulla at volutpat. Sit amet nisl purus in mollis nunc sed id semper. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget. Dui nunc mattis enim ut tellus elementum sagittis vitae et. Hac habitasse platea dictumst quisque. Arcu dictum varius duis at. Eu scelerisque felis imperdiet proin. Faucibus et molestie ac feugiat sed. Duis ultricies lacus sed turpis. - -Aliquam etiam erat velit scelerisque in dictum non. Neque convallis a cras semper auctor neque vitae tempus. Integer eget aliquet nibh praesent. Orci sagittis eu volutpat odio facilisis. Risus at ultrices mi tempus imperdiet nulla. Adipiscing enim eu turpis egestas. Nullam vehicula ipsum a arcu. Vulputate sapien nec sagittis aliquam. Ultrices neque ornare aenean euismod elementum nisi quis. Mauris a diam maecenas sed enim. Faucibus vitae aliquet nec ullamcorper sit amet risus nullam. - -Amet cursus sit amet dictum. Etiam sit amet nisl purus in mollis nunc sed id. Sit amet mauris commodo quis imperdiet massa tincidunt nunc. Dapibus ultrices in iaculis nunc sed augue lacus. Quam nulla porttitor massa id neque aliquam vestibulum. Eget sit amet tellus cras. Velit scelerisque in dictum non consectetur. Sed euismod nisi porta lorem mollis aliquam ut porttitor. Nam libero justo laoreet sit. In aliquam sem fringilla ut morbi. Facilisis volutpat est velit egestas dui. Libero volutpat sed cras ornare arcu dui vivamus. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. - -Praesent semper feugiat nibh sed pulvinar proin gravida. Enim nec dui nunc mattis enim ut. Ut porttitor leo a diam sollicitudin tempor id eu. Eget aliquet nibh praesent tristique. Curabitur vitae nunc sed velit dignissim sodales. Tempor commodo ullamcorper a lacus. Odio facilisis mauris sit amet massa. Dui faucibus in ornare quam viverra orci sagittis eu. Tellus at urna condimentum mattis pellentesque id nibh. Lacus vel facilisis volutpat est velit. Sed viverra tellus in hac. At volutpat diam ut venenatis tellus in metus vulputate. Molestie a iaculis at erat pellentesque adipiscing. - -Amet aliquam id diam maecenas ultricies mi eget mauris pharetra. Pharetra pharetra massa massa ultricies mi quis hendrerit. Felis bibendum ut tristique et egestas quis. Sed arcu non odio euismod lacinia at quis risus sed. At varius vel pharetra vel turpis nunc eget. Interdum varius sit amet mattis vulputate enim nulla. Cras sed felis eget velit aliquet sagittis. Ultricies integer quis auctor elit sed vulputate mi. Facilisis volutpat est velit egestas dui id. At erat pellentesque adipiscing commodo elit at imperdiet dui accumsan. - -Dictumst quisque sagittis purus sit amet volutpat consequat mauris. Dui sapien eget mi proin sed libero. Viverra ipsum nunc aliquet bibendum. Eget arcu dictum varius duis at consectetur lorem donec massa. Diam in arcu cursus euismod quis viverra nibh cras pulvinar. Commodo odio aenean sed adipiscing. Quam lacus suspendisse faucibus interdum posuere lorem ipsum dolor sit. Donec enim diam vulputate ut pharetra sit. Quis auctor elit sed vulputate mi sit amet mauris commodo. Vel pretium lectus quam id leo in vitae turpis. Risus at ultrices mi tempus. Quisque egestas diam in arcu. Mauris augue neque gravida in fermentum et sollicitudin ac orci. Sed enim ut sem viverra. Venenatis lectus magna fringilla urna porttitor rhoncus dolor purus non. Dolor morbi non arcu risus quis varius quam quisque id. Donec ultrices tincidunt arcu non sodales neque. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat. - -Velit sed ullamcorper morbi tincidunt ornare massa eget egestas. Volutpat blandit aliquam etiam erat velit scelerisque in dictum non. Sed adipiscing diam donec adipiscing tristique risus nec. Velit laoreet id donec ultrices tincidunt arcu non. Gravida in fermentum et sollicitudin ac. Ac tortor vitae purus faucibus. Vestibulum morbi blandit cursus risus at. Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin. Vitae elementum curabitur vitae nunc sed velit. Lectus magna fringilla urna porttitor. Sodales ut eu sem integer. Aliquam id diam maecenas ultricies mi eget mauris pharetra et. Dignissim suspendisse in est ante in nibh. Pellentesque habitant morbi tristique senectus et netus et. - -Cras ornare arcu dui vivamus arcu felis bibendum ut tristique. Arcu cursus euismod quis viverra nibh cras. Tellus molestie nunc non blandit massa enim nec dui. Tellus rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Rutrum tellus pellentesque eu tincidunt tortor. Auctor urna nunc id cursus metus aliquam. Nulla malesuada pellentesque elit eget gravida cum sociis natoque. Nec feugiat in fermentum posuere urna nec. Feugiat in fermentum posuere urna. Aliquet sagittis id consectetur purus ut faucibus pulvinar elementum. - -Duis at tellus at urna condimentum mattis pellentesque id. Et ligula ullamcorper malesuada proin libero. Mattis enim ut tellus elementum sagittis. Mattis pellentesque id nibh tortor id aliquet lectus. Duis at consectetur lorem donec massa sapien faucibus. Volutpat ac tincidunt vitae semper quis. Adipiscing vitae proin sagittis nisl rhoncus. At elementum eu facilisis sed odio. Facilisis gravida neque convallis a cras. Mi eget mauris pharetra et ultrices. Montes nascetur ridiculus mus mauris. Egestas purus viverra accumsan in. Arcu cursus euismod quis viverra nibh. Quam elementum pulvinar etiam non quam. Ac placerat vestibulum lectus mauris ultrices eros. Morbi tristique senectus et netus et malesuada. Quisque id diam vel quam elementum pulvinar etiam non quam. Quis lectus nulla at volutpat diam ut. Lectus arcu bibendum at varius vel pharetra vel turpis. Ultrices dui sapien eget mi. - -Nullam ac tortor vitae purus faucibus ornare suspendisse. Eu turpis egestas pretium aenean pharetra. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin. Tristique et egestas quis ipsum suspendisse ultrices gravida. Sit amet purus gravida quis blandit turpis cursus. Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus urna neque. Risus sed vulputate odio ut enim blandit volutpat maecenas volutpat. Ut eu sem integer vitae justo eget. Est placerat in egestas erat imperdiet sed euismod. Habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Tristique sollicitudin nibh sit amet commodo. Dolor magna eget est lorem ipsum. Elementum nibh tellus molestie nunc non blandit massa enim nec. Donec massa sapien faucibus et. Est lorem ipsum dolor sit amet consectetur. - -Imperdiet massa tincidunt nunc pulvinar sapien et. Viverra adipiscing at in tellus integer feugiat scelerisque varius. Augue neque gravida in fermentum et sollicitudin ac orci. Ac felis donec et odio pellentesque diam volutpat. Mattis rhoncus urna neque viverra. Felis eget velit aliquet sagittis id consectetur. Eget nullam non nisi est. Pharetra convallis posuere morbi leo urna molestie at elementum eu. Pellentesque massa placerat duis ultricies lacus sed turpis. Vivamus at augue eget arcu dictum varius duis at consectetur. - -In egestas erat imperdiet sed euismod nisi. Ut tellus elementum sagittis vitae et leo. Vel pharetra vel turpis nunc eget. Interdum posuere lorem ipsum dolor. Non odio euismod lacinia at quis risus sed. Leo a diam sollicitudin tempor id eu nisl nunc. Amet mauris commodo quis imperdiet massa tincidunt nunc. At tempor commodo ullamcorper a lacus vestibulum. Non sodales neque sodales ut etiam sit amet nisl purus. Faucibus interdum posuere lorem ipsum dolor sit. Sed tempus urna et pharetra pharetra massa massa. Et netus et malesuada fames ac turpis egestas. Cursus risus at ultrices mi tempus imperdiet nulla malesuada. Tellus rutrum tellus pellentesque eu. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim. Dolor sit amet consectetur adipiscing elit. Blandit libero volutpat sed cras. Cras ornare arcu dui vivamus arcu felis bibendum. Ac turpis egestas integer eget aliquet. Suscipit adipiscing bibendum est ultricies. - -Tellus elementum sagittis vitae et. Volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque in. Mi sit amet mauris commodo quis imperdiet massa tincidunt. Mi quis hendrerit dolor magna eget est lorem ipsum dolor. Mi in nulla posuere sollicitudin aliquam ultrices. Suspendisse sed nisi lacus sed. Imperdiet dui accumsan sit amet nulla facilisi. Quis eleifend quam adipiscing vitae proin sagittis nisl. Vitae ultricies leo integer malesuada nunc vel risus. Volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque in. Tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin libero. Et malesuada fames ac turpis. Sem fringilla ut morbi tincidunt. - -Nulla aliquet porttitor lacus luctus accumsan. Eleifend donec pretium vulputate sapien nec sagittis. Nulla facilisi morbi tempus iaculis urna id volutpat lacus. Posuere urna nec tincidunt praesent semper feugiat nibh. Scelerisque viverra mauris in aliquam sem. Ut sem nulla pharetra diam sit amet nisl suscipit. Montes nascetur ridiculus mus mauris vitae. Vivamus at augue eget arcu. Sem et tortor consequat id porta nibh venenatis. Viverra aliquet eget sit amet. Luctus venenatis lectus magna fringilla. Sed felis eget velit aliquet sagittis id consectetur purus ut. Cursus eget nunc scelerisque viverra mauris in aliquam. Facilisi cras fermentum odio eu. Ac tincidunt vitae semper quis lectus nulla at volutpat diam. Nec sagittis aliquam malesuada bibendum arcu vitae. Sed odio morbi quis commodo odio aenean. - -Gravida cum sociis natoque penatibus et magnis. Massa tempor nec feugiat nisl pretium fusce. Accumsan lacus vel facilisis volutpat. Risus nullam eget felis eget nunc lobortis mattis aliquam faucibus. Mus mauris vitae ultricies leo integer malesuada nunc. Ut aliquam purus sit amet luctus venenatis. Tellus mauris a diam maecenas sed enim. Pulvinar pellentesque habitant morbi tristique senectus et netus et. Non enim praesent elementum facilisis. Id diam vel quam elementum pulvinar etiam non. Ultricies mi eget mauris pharetra et ultrices neque ornare aenean. Nulla aliquet enim tortor at auctor urna nunc id cursus. Libero enim sed faucibus turpis. Consequat interdum varius sit amet mattis vulputate. At volutpat diam ut venenatis tellus in metus vulputate. Arcu dui vivamus arcu felis. Ac turpis egestas sed tempus urna. Nascetur ridiculus mus mauris vitae ultricies leo. Eget sit amet tellus cras adipiscing enim eu turpis egestas. - -Imperdiet nulla malesuada pellentesque elit eget. Ultricies lacus sed turpis tincidunt id aliquet risus. Tincidunt ornare massa eget egestas. Et ligula ullamcorper malesuada proin. Sit amet volutpat consequat mauris nunc congue nisi vitae. Neque sodales ut etiam sit amet nisl purus in. Luctus accumsan tortor posuere ac. Imperdiet massa tincidunt nunc pulvinar sapien. Dictum at tempor commodo ullamcorper a lacus vestibulum. Odio morbi quis commodo odio aenean sed adipiscing diam. Sed lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt. Pellentesque nec nam aliquam sem et tortor consequat id. At in tellus integer feugiat scelerisque varius morbi. Tellus id interdum velit laoreet id donec ultrices tincidunt arcu. Sit amet mattis vulputate enim nulla aliquet. Volutpat consequat mauris nunc congue nisi vitae suscipit. - -Netus et malesuada fames ac turpis egestas maecenas pharetra convallis. Enim sit amet venenatis urna cursus eget. Nunc mattis enim ut tellus elementum sagittis vitae et. A iaculis at erat pellentesque adipiscing commodo elit at. Vitae purus faucibus ornare suspendisse. Nisl vel pretium lectus quam id leo in. Bibendum est ultricies integer quis auctor. Convallis tellus id interdum velit laoreet id donec ultrices tincidunt. Eros in cursus turpis massa tincidunt dui ut ornare lectus. Varius vel pharetra vel turpis nunc eget. Phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Auctor eu augue ut lectus arcu bibendum at varius vel. - -Sed euismod nisi porta lorem mollis aliquam ut. Varius sit amet mattis vulputate enim nulla aliquet porttitor. Viverra tellus in hac habitasse platea dictumst vestibulum rhoncus. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Eget duis at tellus at urna condimentum mattis pellentesque. Quis ipsum suspendisse ultrices gravida dictum. Consectetur adipiscing elit ut aliquam purus. Placerat in egestas erat imperdiet sed euismod nisi. Aliquet nec ullamcorper sit amet risus. Pulvinar neque laoreet suspendisse interdum consectetur libero id faucibus nisl. Nisi lacus sed viverra tellus in. Mollis nunc sed id semper risus in hendrerit gravida. Eget velit aliquet sagittis id consectetur purus. Nisi est sit amet facilisis. Et tortor at risus viverra adipiscing at in tellus integer. - -Neque sodales ut etiam sit amet nisl. Ipsum suspendisse ultrices gravida dictum. Enim nec dui nunc mattis enim. Tortor aliquam nulla facilisi cras fermentum odio eu feugiat pretium. Phasellus egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam. Amet justo donec enim diam. Tincidunt dui ut ornare lectus sit amet. Lectus quam id leo in. Maecenas ultricies mi eget mauris pharetra et ultrices neque. Nec dui nunc mattis enim ut. A cras semper auctor neque. Mi tempus imperdiet nulla malesuada pellentesque elit eget gravida cum. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Nibh sit amet commodo nulla facilisi. Convallis aenean et tortor at risus viverra adipiscing. Bibendum at varius vel pharetra vel turpis. Blandit cursus risus at ultrices mi tempus imperdiet nulla malesuada. Aenean euismod elementum nisi quis. - -Sit amet mauris commodo quis. Quis ipsum suspendisse ultrices gravida dictum fusce ut placerat. Congue mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Dolor magna eget est lorem ipsum. Dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Nunc sed augue lacus viverra vitae. Iaculis urna id volutpat lacus laoreet non curabitur. Sed risus ultricies tristique nulla aliquet enim tortor at auctor. Malesuada bibendum arcu vitae elementum curabitur vitae. Id semper risus in hendrerit gravida. Tellus cras adipiscing enim eu turpis egestas. Est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Tempor orci dapibus ultrices in iaculis. Viverra justo nec ultrices dui sapien eget mi. Lorem donec massa sapien faucibus et molestie ac feugiat. Quis lectus nulla at volutpat diam ut. Amet consectetur adipiscing elit duis. Viverra orci sagittis eu volutpat odio facilisis. - -Mauris commodo quis imperdiet massa tincidunt nunc. Diam in arcu cursus euismod quis viverra nibh cras pulvinar. Amet commodo nulla facilisi nullam vehicula ipsum a arcu cursus. Eget felis eget nunc lobortis. Aliquam malesuada bibendum arcu vitae elementum curabitur vitae nunc sed. Pharetra et ultrices neque ornare aenean euismod elementum. Amet commodo nulla facilisi nullam. Diam sit amet nisl suscipit. Auctor urna nunc id cursus metus aliquam eleifend mi in. Eget est lorem ipsum dolor sit amet. Aliquet eget sit amet tellus cras adipiscing enim eu. Congue quisque egestas diam in arcu. - -Morbi tempus iaculis urna id. Et odio pellentesque diam volutpat commodo. Porttitor lacus luctus accumsan tortor. Risus ultricies tristique nulla aliquet. Imperdiet dui accumsan sit amet nulla. Turpis egestas maecenas pharetra convallis posuere morbi leo. At elementum eu facilisis sed odio morbi. Tincidunt vitae semper quis lectus nulla. Enim blandit volutpat maecenas volutpat. Lacus vestibulum sed arcu non odio euismod lacinia at. Volutpat maecenas volutpat blandit aliquam etiam erat. Molestie a iaculis at erat pellentesque adipiscing. Pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus et. Quis varius quam quisque id diam vel quam. - -Felis eget velit aliquet sagittis id consectetur purus ut. Eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Risus in hendrerit gravida rutrum quisque non tellus orci. Sit amet nisl suscipit adipiscing bibendum est ultricies integer quis. Ullamcorper sit amet risus nullam eget felis eget nunc lobortis. Mauris commodo quis imperdiet massa tincidunt nunc. Vel orci porta non pulvinar neque laoreet. Ullamcorper sit amet risus nullam eget felis eget. Facilisi etiam dignissim diam quis enim. Sed faucibus turpis in eu mi. Sed odio morbi quis commodo odio aenean sed adipiscing. Facilisis sed odio morbi quis commodo odio aenean. Euismod quis viverra nibh cras. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Nulla facilisi etiam dignissim diam. - -Pretium fusce id velit ut tortor pretium viverra suspendisse. Tincidunt id aliquet risus feugiat in ante metus dictum. Maecenas pharetra convallis posuere morbi leo urna molestie at elementum. Habitant morbi tristique senectus et netus et malesuada. Sapien et ligula ullamcorper malesuada proin libero nunc consequat. Vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Aliquam sem fringilla ut morbi tincidunt augue interdum. Volutpat lacus laoreet non curabitur gravida. Elementum facilisis leo vel fringilla est ullamcorper eget nulla facilisi. Semper auctor neque vitae tempus quam pellentesque nec. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Tempor orci eu lobortis elementum nibh tellus molestie nunc non. In eu mi bibendum neque egestas congue quisque egestas diam. - -Adipiscing enim eu turpis egestas pretium aenean pharetra. Vitae suscipit tellus mauris a diam maecenas sed enim. Enim ut tellus elementum sagittis vitae et leo duis. Cursus eget nunc scelerisque viverra mauris in aliquam sem. Vel fringilla est ullamcorper eget. Tellus elementum sagittis vitae et leo. Auctor augue mauris augue neque gravida in. Id faucibus nisl tincidunt eget nullam non nisi est. Venenatis tellus in metus vulputate eu scelerisque felis. Donec pretium vulputate sapien nec sagittis. Urna molestie at elementum eu facilisis sed odio morbi quis. Quisque sagittis purus sit amet. Habitasse platea dictumst quisque sagittis purus sit amet. Ultricies leo integer malesuada nunc vel risus. Egestas dui id ornare arcu odio ut sem. - -Proin sagittis nisl rhoncus mattis rhoncus. Et ultrices neque ornare aenean. Purus viverra accumsan in nisl nisi. Laoreet non curabitur gravida arcu ac tortor. Vitae sapien pellentesque habitant morbi tristique senectus et netus. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Cursus mattis molestie a iaculis. Mi quis hendrerit dolor magna eget est. Elementum nisi quis eleifend quam adipiscing vitae proin sagittis nisl. Risus commodo viverra maecenas accumsan lacus vel facilisis volutpat. Maecenas pharetra convallis posuere morbi leo. Hendrerit dolor magna eget est lorem ipsum dolor sit amet. Morbi tristique senectus et netus et malesuada. Dictum varius duis at consectetur lorem donec massa. Dignissim suspendisse in est ante in nibh mauris cursus mattis. Consequat mauris nunc congue nisi vitae suscipit tellus mauris a. Ac orci phasellus egestas tellus rutrum tellus pellentesque eu. Interdum velit euismod in pellentesque. Leo vel fringilla est ullamcorper eget nulla facilisi. - -Orci dapibus ultrices in iaculis nunc sed augue lacus. Ut tristique et egestas quis ipsum suspendisse. Vitae elementum curabitur vitae nunc sed. Mauris pharetra et ultrices neque ornare aenean euismod elementum nisi. Laoreet sit amet cursus sit amet. Fusce ut placerat orci nulla pellentesque. Accumsan tortor posuere ac ut consequat semper viverra nam libero. Pretium aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Fringilla est ullamcorper eget nulla facilisi. Morbi tristique senectus et netus et malesuada. - -Amet volutpat consequat mauris nunc congue nisi vitae suscipit. Senectus et netus et malesuada fames ac turpis. Praesent tristique magna sit amet purus gravida quis blandit turpis. Blandit aliquam etiam erat velit scelerisque in dictum. Urna id volutpat lacus laoreet non. Tellus elementum sagittis vitae et leo duis. Tempor orci dapibus ultrices in iaculis nunc sed. Lacus sed viverra tellus in. Sed augue lacus viverra vitae. Lobortis feugiat vivamus at augue. Lacinia quis vel eros donec ac odio tempor orci dapibus. Tellus cras adipiscing enim eu. Dui ut ornare lectus sit amet est. - -Et magnis dis parturient montes nascetur ridiculus mus mauris. Nisi scelerisque eu ultrices vitae auctor eu augue ut lectus. Lectus magna fringilla urna porttitor rhoncus dolor. In cursus turpis massa tincidunt dui ut ornare. Sit amet risus nullam eget. Duis ultricies lacus sed turpis tincidunt id. Ipsum dolor sit amet consectetur adipiscing. In vitae turpis massa sed elementum tempus egestas. Sit amet dictum sit amet justo donec enim diam vulputate. Purus viverra accumsan in nisl nisi scelerisque eu ultrices vitae. Fusce ut placerat orci nulla pellentesque dignissim enim. Ultrices tincidunt arcu non sodales neque sodales. Platea dictumst quisque sagittis purus sit amet volutpat consequat. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Mauris commodo quis imperdiet massa tincidunt nunc. Lectus nulla at volutpat diam ut venenatis tellus. Platea dictumst vestibulum rhoncus est pellentesque elit. Ac ut consequat semper viverra nam libero justo laoreet. Risus quis varius quam quisque id. - -Varius vel pharetra vel turpis nunc eget lorem dolor. Convallis posuere morbi leo urna molestie at elementum. Amet luctus venenatis lectus magna fringilla urna porttitor rhoncus. Ac tincidunt vitae semper quis. Erat imperdiet sed euismod nisi porta. Dui ut ornare lectus sit. Ut etiam sit amet nisl purus in mollis. Et molestie ac feugiat sed lectus. Sit amet mauris commodo quis imperdiet. Vel turpis nunc eget lorem dolor sed viverra ipsum nunc. Nullam vehicula ipsum a arcu cursus vitae congue mauris rhoncus. - -Mauris augue neque gravida in fermentum et sollicitudin. Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus semper. Fames ac turpis egestas integer eget aliquet nibh. Scelerisque in dictum non consectetur a erat nam at lectus. Nulla pellentesque dignissim enim sit amet venenatis urna cursus. Id nibh tortor id aliquet lectus proin nibh. Dui faucibus in ornare quam viverra orci sagittis eu volutpat. Cursus turpis massa tincidunt dui ut ornare lectus. Velit ut tortor pretium viverra. Et tortor consequat id porta. Erat imperdiet sed euismod nisi porta lorem mollis aliquam. Dictumst vestibulum rhoncus est pellentesque elit. At lectus urna duis convallis convallis tellus id interdum velit. Est ultricies integer quis auctor elit sed vulputate. Mi ipsum faucibus vitae aliquet nec ullamcorper. Vulputate ut pharetra sit amet aliquam. Volutpat sed cras ornare arcu dui vivamus arcu felis. Quam vulputate dignissim suspendisse in est ante in nibh. Fermentum et sollicitudin ac orci phasellus egestas tellus. - -Risus nullam eget felis eget nunc. Nec sagittis aliquam malesuada bibendum arcu vitae. Quisque non tellus orci ac. Amet nulla facilisi morbi tempus. Lobortis mattis aliquam faucibus purus. Sed faucibus turpis in eu mi bibendum neque. Nibh mauris cursus mattis molestie. Vel turpis nunc eget lorem dolor. Dolor sit amet consectetur adipiscing elit duis tristique. Ultricies lacus sed turpis tincidunt id aliquet. Eleifend mi in nulla posuere sollicitudin aliquam. Semper eget duis at tellus at urna. Neque sodales ut etiam sit amet nisl. Feugiat in ante metus dictum at. Nullam non nisi est sit amet facilisis. - -Elit scelerisque mauris pellentesque pulvinar pellentesque habitant. Id semper risus in hendrerit gravida rutrum quisque non tellus. Faucibus ornare suspendisse sed nisi lacus sed viverra tellus. Morbi leo urna molestie at elementum eu. Potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed. Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc consequat. Etiam sit amet nisl purus in mollis nunc sed. Dignissim sodales ut eu sem integer vitae justo. Euismod quis viverra nibh cras. Elementum facilisis leo vel fringilla est ullamcorper. Quis risus sed vulputate odio ut enim. In nisl nisi scelerisque eu ultrices vitae. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. Neque sodales ut etiam sit amet nisl purus. Erat nam at lectus urna duis convallis convallis tellus. Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. Congue quisque egestas diam in arcu cursus euismod. Magna ac placerat vestibulum lectus mauris. In est ante in nibh mauris cursus mattis. - -Faucibus pulvinar elementum integer enim neque volutpat ac. Sodales neque sodales ut etiam sit amet nisl. Elit scelerisque mauris pellentesque pulvinar pellentesque. Fringilla phasellus faucibus scelerisque eleifend. Cum sociis natoque penatibus et magnis. Enim blandit volutpat maecenas volutpat blandit aliquam. Adipiscing elit ut aliquam purus sit amet luctus venenatis lectus. Scelerisque purus semper eget duis at. Ut placerat orci nulla pellentesque dignissim. Nunc lobortis mattis aliquam faucibus purus in massa tempor. Scelerisque fermentum dui faucibus in ornare quam. Fermentum iaculis eu non diam phasellus vestibulum lorem sed. Odio euismod lacinia at quis risus sed vulputate odio. Morbi tristique senectus et netus. Dui nunc mattis enim ut tellus elementum. Arcu vitae elementum curabitur vitae nunc. - -Velit scelerisque in dictum non consectetur a. Sed felis eget velit aliquet sagittis id consectetur. Ullamcorper sit amet risus nullam eget felis eget nunc lobortis. Aliquet enim tortor at auctor urna nunc id cursus metus. Suspendisse interdum consectetur libero id. Ipsum dolor sit amet consectetur. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Ante metus dictum at tempor commodo. Et molestie ac feugiat sed. Eu facilisis sed odio morbi quis commodo odio aenean sed. - -Magnis dis parturient montes nascetur. Aliquet bibendum enim facilisis gravida neque convallis a cras. Enim blandit volutpat maecenas volutpat blandit aliquam etiam. In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Imperdiet massa tincidunt nunc pulvinar sapien. Ac feugiat sed lectus vestibulum mattis ullamcorper velit sed. Tempus egestas sed sed risus pretium. Tortor aliquam nulla facilisi cras fermentum. Integer quis auctor elit sed. Scelerisque eu ultrices vitae auctor eu. Faucibus nisl tincidunt eget nullam non nisi est sit. Id interdum velit laoreet id donec ultrices tincidunt. Amet venenatis urna cursus eget nunc scelerisque viverra mauris. Ornare arcu dui vivamus arcu felis bibendum ut. Dolor magna eget est lorem ipsum dolor. - -Aliquam faucibus purus in massa tempor nec feugiat nisl. Sed vulputate mi sit amet mauris commodo quis imperdiet. Augue interdum velit euismod in pellentesque massa placerat duis ultricies. Massa tincidunt nunc pulvinar sapien et. Nulla porttitor massa id neque aliquam. Tincidunt arcu non sodales neque sodales ut. Quam elementum pulvinar etiam non quam lacus. Quis enim lobortis scelerisque fermentum dui faucibus in. Arcu risus quis varius quam. Morbi tincidunt augue interdum velit euismod. Cursus sit amet dictum sit amet justo donec enim. Risus in hendrerit gravida rutrum quisque. Amet nisl suscipit adipiscing bibendum. Lacus vestibulum sed arcu non odio. Diam vel quam elementum pulvinar etiam non quam. Curabitur gravida arcu ac tortor dignissim convallis aenean et. - -Aliquet bibendum enim facilisis gravida neque convallis. Facilisis gravida neque convallis a cras semper auctor neque vitae. Nunc mi ipsum faucibus vitae. Leo vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Fringilla phasellus faucibus scelerisque eleifend. Suscipit tellus mauris a diam maecenas sed enim. Mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Nisi quis eleifend quam adipiscing vitae proin sagittis. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus mattis. Pretium nibh ipsum consequat nisl vel pretium. Eget mauris pharetra et ultrices neque. Augue interdum velit euismod in pellentesque massa placerat. Nibh mauris cursus mattis molestie a iaculis at erat. - -Imperdiet massa tincidunt nunc pulvinar sapien et. Quis hendrerit dolor magna eget est lorem ipsum dolor sit. Aliquam sem et tortor consequat id. Quisque egestas diam in arcu. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. Ultrices neque ornare aenean euismod elementum nisi. Nibh venenatis cras sed felis eget velit aliquet sagittis. Posuere urna nec tincidunt praesent. Lectus proin nibh nisl condimentum id venenatis a condimentum. Sit amet consectetur adipiscing elit pellentesque habitant morbi tristique. - -Et malesuada fames ac turpis egestas sed tempus urna. Morbi non arcu risus quis varius. Maecenas pharetra convallis posuere morbi leo urna. Eget dolor morbi non arcu risus quis varius. Sit amet consectetur adipiscing elit ut aliquam purus. Morbi non arcu risus quis varius. Amet nisl suscipit adipiscing bibendum est ultricies integer quis. Id faucibus nisl tincidunt eget nullam non nisi. Blandit turpis cursus in hac habitasse platea dictumst quisque sagittis. Sed turpis tincidunt id aliquet. Egestas diam in arcu cursus euismod. Orci ac auctor augue mauris. Fermentum leo vel orci porta non pulvinar. Eu non diam phasellus vestibulum lorem sed risus. Viverra mauris in aliquam sem fringilla ut morbi tincidunt augue. Velit aliquet sagittis id consectetur purus. - -Aliquam ultrices sagittis orci a scelerisque purus semper. Ac odio tempor orci dapibus ultrices in iaculis nunc sed. Justo eget magna fermentum iaculis. Ornare suspendisse sed nisi lacus. Auctor augue mauris augue neque. Habitasse platea dictumst quisque sagittis purus sit amet. Adipiscing enim eu turpis egestas. Risus nullam eget felis eget nunc. Lectus magna fringilla urna porttitor rhoncus. Odio ut sem nulla pharetra diam sit amet nisl. - -Nibh tortor id aliquet lectus proin nibh nisl. Malesuada fames ac turpis egestas integer eget aliquet nibh praesent. Turpis cursus in hac habitasse platea dictumst quisque sagittis purus. Non sodales neque sodales ut etiam sit. Viverra accumsan in nisl nisi scelerisque eu. Tempus imperdiet nulla malesuada pellentesque elit eget. Facilisi etiam dignissim diam quis enim lobortis. Duis ultricies lacus sed turpis. Egestas quis ipsum suspendisse ultrices gravida. Aliquet enim tortor at auctor urna nunc id cursus. - -Turpis massa tincidunt dui ut ornare lectus sit. Risus viverra adipiscing at in tellus. Et malesuada fames ac turpis egestas maecenas. Cursus mattis molestie a iaculis at. Dui vivamus arcu felis bibendum ut. Ut eu sem integer vitae justo eget magna fermentum. Aliquam sem fringilla ut morbi tincidunt augue interdum velit euismod. Semper eget duis at tellus at. Eros donec ac odio tempor orci. Nulla at volutpat diam ut venenatis tellus. Consectetur adipiscing elit ut aliquam purus. Posuere lorem ipsum dolor sit amet consectetur adipiscing elit. Scelerisque purus semper eget duis at tellus. Massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin. Faucibus pulvinar elementum integer enim neque volutpat ac. Nisi est sit amet facilisis magna etiam tempor orci eu. Natoque penatibus et magnis dis parturient montes nascetur ridiculus. Eu ultrices vitae auctor eu. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam quis. - -Non nisi est sit amet facilisis magna etiam tempor orci. Elit at imperdiet dui accumsan sit amet nulla facilisi morbi. Viverra accumsan in nisl nisi scelerisque eu ultrices. Eu augue ut lectus arcu bibendum at varius. Mus mauris vitae ultricies leo integer malesuada nunc vel. Amet cursus sit amet dictum sit. Dolor purus non enim praesent elementum facilisis leo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Donec enim diam vulputate ut. Facilisis leo vel fringilla est ullamcorper eget. Tortor at risus viverra adipiscing at. Amet aliquam id diam maecenas ultricies mi eget mauris pharetra. Pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. Egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Ut tellus elementum sagittis vitae et leo. Eu augue ut lectus arcu bibendum at varius vel pharetra. Iaculis urna id volutpat lacus laoreet non curabitur. Nec tincidunt praesent semper feugiat nibh. Vitae tempus quam pellentesque nec. Lectus proin nibh nisl condimentum id. - -Viverra accumsan in nisl nisi scelerisque. Consequat nisl vel pretium lectus quam id leo in vitae. Arcu dictum varius duis at consectetur lorem donec. Quisque sagittis purus sit amet volutpat. Amet dictum sit amet justo donec enim diam vulputate ut. Tellus orci ac auctor augue mauris augue neque. Tempor nec feugiat nisl pretium fusce id velit ut. Pellentesque diam volutpat commodo sed. Aliquam sem fringilla ut morbi tincidunt augue interdum velit. Odio tempor orci dapibus ultrices. Risus viverra adipiscing at in tellus. Pulvinar mattis nunc sed blandit. Velit euismod in pellentesque massa placerat duis ultricies lacus. Velit laoreet id donec ultrices tincidunt arcu. Sed pulvinar proin gravida hendrerit lectus. - -Morbi tristique senectus et netus et malesuada fames ac. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. Convallis a cras semper auctor neque vitae tempus. Vulputate eu scelerisque felis imperdiet. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. At auctor urna nunc id cursus metus aliquam. A cras semper auctor neque vitae tempus quam pellentesque. Et tortor consequat id porta nibh. Eget egestas purus viverra accumsan in nisl. At imperdiet dui accumsan sit amet nulla facilisi morbi tempus. Eget egestas purus viverra accumsan in. Nunc congue nisi vitae suscipit tellus mauris a. Viverra vitae congue eu consequat ac felis donec et odio. Orci porta non pulvinar neque laoreet suspendisse interdum. Aliquam etiam erat velit scelerisque in dictum non. - -Malesuada bibendum arcu vitae elementum. Blandit aliquam etiam erat velit scelerisque in dictum non consectetur. Eget nullam non nisi est sit amet facilisis magna. Vel pretium lectus quam id leo in vitae turpis massa. Volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque. At volutpat diam ut venenatis tellus in metus vulputate eu. Adipiscing elit ut aliquam purus sit amet luctus venenatis. Morbi tempus iaculis urna id volutpat lacus. Elit duis tristique sollicitudin nibh sit amet commodo nulla. Pellentesque sit amet porttitor eget. Arcu bibendum at varius vel pharetra. Sit amet massa vitae tortor condimentum lacinia quis. Sit amet facilisis magna etiam tempor orci eu. Convallis convallis tellus id interdum velit. - -Aliquam vestibulum morbi blandit cursus risus. Nibh cras pulvinar mattis nunc sed blandit libero volutpat sed. Vitae purus faucibus ornare suspendisse sed. Amet mauris commodo quis imperdiet massa tincidunt nunc. Id eu nisl nunc mi ipsum faucibus vitae aliquet nec. Libero nunc consequat interdum varius sit. Laoreet id donec ultrices tincidunt arcu non sodales neque. In pellentesque massa placerat duis ultricies lacus sed. Ipsum consequat nisl vel pretium. Nunc sed velit dignissim sodales. Venenatis lectus magna fringilla urna porttitor rhoncus. Enim praesent elementum facilisis leo vel. Ullamcorper eget nulla facilisi etiam. Consectetur adipiscing elit ut aliquam purus. Diam quam nulla porttitor massa. Orci dapibus ultrices in iaculis nunc sed augue lacus. Non nisi est sit amet facilisis magna etiam tempor orci. Vel pharetra vel turpis nunc eget lorem dolor sed. - -Semper viverra nam libero justo laoreet. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Accumsan tortor posuere ac ut consequat semper viverra. Massa massa ultricies mi quis hendrerit dolor magna eget est. Turpis cursus in hac habitasse platea dictumst quisque sagittis. Dui vivamus arcu felis bibendum. Condimentum id venenatis a condimentum vitae sapien pellentesque. Ultrices vitae auctor eu augue ut lectus arcu bibendum. Semper feugiat nibh sed pulvinar proin gravida. Tellus cras adipiscing enim eu turpis egestas pretium aenean pharetra. - -Suspendisse in est ante in nibh mauris cursus mattis. Volutpat lacus laoreet non curabitur gravida arcu ac. Est sit amet facilisis magna etiam tempor. Quam vulputate dignissim suspendisse in est ante in. Hac habitasse platea dictumst vestibulum rhoncus est. Sem fringilla ut morbi tincidunt. Turpis in eu mi bibendum. Viverra nam libero justo laoreet sit amet cursus sit amet. Vel risus commodo viverra maecenas accumsan. Vitae turpis massa sed elementum tempus egestas sed sed. Cursus sit amet dictum sit amet justo donec enim diam. Cras sed felis eget velit. Feugiat scelerisque varius morbi enim nunc faucibus. Duis at tellus at urna condimentum. At risus viverra adipiscing at in. Pulvinar pellentesque habitant morbi tristique senectus et. Sapien pellentesque habitant morbi tristique senectus et. - -Fringilla urna porttitor rhoncus dolor purus. Mi eget mauris pharetra et ultrices. Faucibus purus in massa tempor nec feugiat nisl pretium. At erat pellentesque adipiscing commodo elit at imperdiet dui accumsan. Orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Nunc scelerisque viverra mauris in. Posuere sollicitudin aliquam ultrices sagittis. Risus quis varius quam quisque id diam vel quam elementum. Etiam sit amet nisl purus in mollis. Id donec ultrices tincidunt arcu non. Nulla posuere sollicitudin aliquam ultrices sagittis orci. Laoreet sit amet cursus sit amet. Fermentum et sollicitudin ac orci phasellus egestas. Leo integer malesuada nunc vel risus commodo viverra maecenas accumsan. Dignissim sodales ut eu sem integer. Non enim praesent elementum facilisis leo vel. - -Tempus imperdiet nulla malesuada pellentesque. Nisi est sit amet facilisis magna. Mi sit amet mauris commodo quis imperdiet massa tincidunt. Pellentesque adipiscing commodo elit at imperdiet. Massa eget egestas purus viverra. Nec feugiat in fermentum posuere urna nec tincidunt. Pellentesque nec nam aliquam sem et tortor consequat id. Morbi quis commodo odio aenean sed adipiscing. Sapien et ligula ullamcorper malesuada proin. Justo nec ultrices dui sapien eget. Scelerisque eu ultrices vitae auctor eu augue ut lectus. Tellus at urna condimentum mattis pellentesque id nibh tortor. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit. Adipiscing elit ut aliquam purus sit. Vitae tortor condimentum lacinia quis vel eros donec ac odio. Non sodales neque sodales ut. - -Semper viverra nam libero justo laoreet sit amet cursus sit. Velit laoreet id donec ultrices tincidunt arcu non sodales neque. Semper eget duis at tellus. Dolor magna eget est lorem ipsum dolor sit amet consectetur. Vel quam elementum pulvinar etiam non. Maecenas ultricies mi eget mauris pharetra et ultrices neque ornare. Ultrices gravida dictum fusce ut placerat orci nulla pellentesque dignissim. Turpis cursus in hac habitasse platea dictumst quisque sagittis purus. Adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. In pellentesque massa placerat duis ultricies. Malesuada fames ac turpis egestas sed tempus urna et. Consequat nisl vel pretium lectus. Mattis vulputate enim nulla aliquet porttitor. Odio morbi quis commodo odio aenean sed. Adipiscing elit pellentesque habitant morbi tristique. Amet porttitor eget dolor morbi non. Vel fringilla est ullamcorper eget nulla facilisi etiam dignissim. Integer enim neque volutpat ac tincidunt. Ultrices tincidunt arcu non sodales neque sodales ut. Interdum posuere lorem ipsum dolor sit amet. - -Vestibulum lorem sed risus ultricies tristique nulla aliquet. Non arcu risus quis varius quam. Lectus arcu bibendum at varius vel pharetra. Condimentum id venenatis a condimentum. Nulla porttitor massa id neque aliquam vestibulum morbi blandit cursus. Orci dapibus ultrices in iaculis nunc sed augue lacus viverra. Risus nullam eget felis eget nunc lobortis. Pharetra vel turpis nunc eget lorem dolor sed viverra. Egestas dui id ornare arcu odio ut. Sagittis id consectetur purus ut. Tincidunt tortor aliquam nulla facilisi. Lacus laoreet non curabitur gravida arcu. Curabitur gravida arcu ac tortor dignissim convallis aenean. Eget aliquet nibh praesent tristique. Adipiscing bibendum est ultricies integer quis auctor elit sed. Habitasse platea dictumst vestibulum rhoncus est. Sed cras ornare arcu dui. Id porta nibh venenatis cras sed. Imperdiet dui accumsan sit amet nulla facilisi. - -Id aliquet lectus proin nibh. Commodo ullamcorper a lacus vestibulum. Imperdiet proin fermentum leo vel orci porta non pulvinar neque. Blandit libero volutpat sed cras. Nibh sed pulvinar proin gravida. Lacus suspendisse faucibus interdum posuere. Mattis nunc sed blandit libero. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus. Dignissim enim sit amet venenatis urna cursus eget nunc. Amet justo donec enim diam vulputate. Id neque aliquam vestibulum morbi blandit cursus. Sed libero enim sed faucibus turpis in eu. Montes nascetur ridiculus mus mauris vitae ultricies. Quam vulputate dignissim suspendisse in est ante in nibh mauris. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant morbi. Diam in arcu cursus euismod. Phasellus egestas tellus rutrum tellus. Vel pretium lectus quam id leo. - -Nunc non blandit massa enim nec dui nunc mattis. Volutpat lacus laoreet non curabitur. Sem nulla pharetra diam sit amet. Pulvinar mattis nunc sed blandit libero volutpat sed. Dui accumsan sit amet nulla facilisi morbi tempus iaculis. Mus mauris vitae ultricies leo. Proin nibh nisl condimentum id venenatis. Dignissim enim sit amet venenatis urna cursus eget nunc. In hac habitasse platea dictumst vestibulum. Felis imperdiet proin fermentum leo vel. Mattis vulputate enim nulla aliquet porttitor lacus luctus. Tortor consequat id porta nibh venenatis cras sed felis. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. Lorem donec massa sapien faucibus et molestie ac feugiat sed. Mattis rhoncus urna neque viverra justo nec ultrices dui sapien. Risus in hendrerit gravida rutrum quisque non tellus orci ac. Justo laoreet sit amet cursus sit amet dictum. Sed libero enim sed faucibus turpis in eu mi bibendum. - -Nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Tortor posuere ac ut consequat semper viverra nam libero. Nec dui nunc mattis enim. Nunc mattis enim ut tellus elementum sagittis. Gravida rutrum quisque non tellus orci ac auctor. Donec adipiscing tristique risus nec feugiat in fermentum posuere urna. Viverra maecenas accumsan lacus vel facilisis volutpat est velit egestas. Bibendum arcu vitae elementum curabitur vitae nunc sed. Ac turpis egestas integer eget aliquet nibh. In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Massa massa ultricies mi quis. Sagittis eu volutpat odio facilisis mauris. Eget magna fermentum iaculis eu non diam phasellus vestibulum. Nulla aliquet enim tortor at. Lobortis scelerisque fermentum dui faucibus. Ante metus dictum at tempor commodo ullamcorper. - -Augue neque gravida in fermentum et sollicitudin ac orci. Elit pellentesque habitant morbi tristique senectus. Arcu cursus vitae congue mauris rhoncus. Sit amet purus gravida quis blandit. Cras fermentum odio eu feugiat pretium nibh ipsum consequat. Leo in vitae turpis massa sed elementum tempus. Nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. Non sodales neque sodales ut etiam sit amet. Facilisi morbi tempus iaculis urna id volutpat. Non blandit massa enim nec. Etiam erat velit scelerisque in dictum non consectetur a erat. Fermentum posuere urna nec tincidunt praesent semper feugiat. Justo donec enim diam vulputate ut pharetra sit amet. Egestas sed tempus urna et pharetra pharetra. Sed ullamcorper morbi tincidunt ornare massa. - -Posuere urna nec tincidunt praesent semper feugiat nibh sed pulvinar. Sit amet porttitor eget dolor morbi. Auctor elit sed vulputate mi sit amet mauris commodo quis. Nullam non nisi est sit amet facilisis magna etiam. Amet luctus venenatis lectus magna fringilla urna. Consectetur adipiscing elit duis tristique sollicitudin nibh sit. Dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Pellentesque diam volutpat commodo sed egestas. Lectus mauris ultrices eros in. Elementum eu facilisis sed odio morbi quis commodo. Diam vel quam elementum pulvinar etiam non quam. Ac placerat vestibulum lectus mauris ultrices eros in cursus turpis. Leo duis ut diam quam nulla porttitor massa id. Metus dictum at tempor commodo ullamcorper a lacus. Varius vel pharetra vel turpis nunc eget lorem dolor. - -Tristique sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Risus ultricies tristique nulla aliquet enim tortor at auctor urna. Ut eu sem integer vitae justo eget magna fermentum. Risus nec feugiat in fermentum posuere urna nec. Quisque non tellus orci ac auctor. Egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. Purus sit amet luctus venenatis lectus magna fringilla urna porttitor. Velit euismod in pellentesque massa placerat duis ultricies. Congue nisi vitae suscipit tellus mauris a diam. Sem et tortor consequat id porta. Platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Penatibus et magnis dis parturient. A erat nam at lectus urna. Commodo viverra maecenas accumsan lacus vel facilisis volutpat est velit. In iaculis nunc sed augue lacus viverra vitae. Tempus urna et pharetra pharetra massa massa ultricies mi quis. Fermentum iaculis eu non diam. Donec ac odio tempor orci dapibus ultrices in iaculis. Purus in massa tempor nec feugiat. - -Nisl tincidunt eget nullam non nisi est. Donec et odio pellentesque diam volutpat. Tristique senectus et netus et. Amet facilisis magna etiam tempor. Eget sit amet tellus cras adipiscing. Blandit volutpat maecenas volutpat blandit aliquam etiam erat velit. Tincidunt ornare massa eget egestas purus viverra accumsan in. Accumsan tortor posuere ac ut consequat. Gravida in fermentum et sollicitudin ac orci phasellus. Id diam vel quam elementum pulvinar etiam non quam. Sit amet nisl purus in mollis nunc sed. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget. Ultricies tristique nulla aliquet enim tortor at. Platea dictumst quisque sagittis purus. Eros donec ac odio tempor. Vitae elementum curabitur vitae nunc. Nibh cras pulvinar mattis nunc. - -At risus viverra adipiscing at in. Vitae suscipit tellus mauris a diam maecenas sed enim ut. Tellus integer feugiat scelerisque varius morbi enim nunc faucibus a. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis. Ac tincidunt vitae semper quis lectus nulla at volutpat. Facilisi morbi tempus iaculis urna id volutpat lacus laoreet non. Consequat semper viverra nam libero justo laoreet sit amet cursus. Duis ultricies lacus sed turpis tincidunt id. Pretium nibh ipsum consequat nisl vel pretium lectus quam id. Vel eros donec ac odio. Nulla posuere sollicitudin aliquam ultrices. Bibendum at varius vel pharetra vel. - -Eleifend donec pretium vulputate sapien nec. Nisl suscipit adipiscing bibendum est ultricies integer. Sit amet porttitor eget dolor morbi non arcu risus. Diam quam nulla porttitor massa id neque. Facilisis volutpat est velit egestas. Est ultricies integer quis auctor elit sed vulputate mi. Aliquam sem et tortor consequat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Ornare lectus sit amet est. Imperdiet sed euismod nisi porta lorem mollis aliquam ut. - -Justo nec ultrices dui sapien eget mi. Fermentum odio eu feugiat pretium. Dui id ornare arcu odio ut sem nulla. Quis varius quam quisque id diam vel. Aliquam purus sit amet luctus venenatis. Blandit turpis cursus in hac habitasse. Turpis tincidunt id aliquet risus. Euismod quis viverra nibh cras pulvinar mattis nunc sed blandit. Ultricies tristique nulla aliquet enim tortor at auctor urna. Fames ac turpis egestas maecenas pharetra convallis posuere morbi. - -Nibh praesent tristique magna sit. Iaculis at erat pellentesque adipiscing. Sed vulputate mi sit amet mauris commodo quis. Vestibulum lorem sed risus ultricies. Arcu non sodales neque sodales ut etiam sit. Diam quam nulla porttitor massa id. Adipiscing tristique risus nec feugiat in fermentum posuere. Faucibus nisl tincidunt eget nullam non nisi. Magna etiam tempor orci eu lobortis elementum. Consequat mauris nunc congue nisi vitae suscipit tellus mauris. Posuere urna nec tincidunt praesent semper. Nunc vel risus commodo viverra maecenas accumsan lacus vel. - -Sed turpis tincidunt id aliquet risus. Mauris commodo quis imperdiet massa tincidunt. Convallis convallis tellus id interdum velit laoreet id donec. Lorem ipsum dolor sit amet consectetur adipiscing. Vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Auctor augue mauris augue neque gravida in fermentum et. Feugiat in fermentum posuere urna nec tincidunt praesent. Sed lectus vestibulum mattis ullamcorper velit. Tellus orci ac auctor augue mauris augue neque gravida in. Massa sapien faucibus et molestie ac feugiat sed lectus vestibulum. Integer quis auctor elit sed vulputate mi sit. Imperdiet proin fermentum leo vel. Posuere sollicitudin aliquam ultrices sagittis orci. - -Velit sed ullamcorper morbi tincidunt. Mattis nunc sed blandit libero volutpat sed. Sit amet est placerat in egestas. Enim praesent elementum facilisis leo vel fringilla est. Donec ultrices tincidunt arcu non sodales neque sodales. Lacus laoreet non curabitur gravida. Enim sed faucibus turpis in eu mi. Tortor aliquam nulla facilisi cras fermentum odio. Mollis nunc sed id semper. Aenean et tortor at risus viverra adipiscing at in. Rhoncus mattis rhoncus urna neque viverra justo nec ultrices. Scelerisque mauris pellentesque pulvinar pellentesque. Morbi enim nunc faucibus a pellentesque sit amet porttitor eget. - -Vitae tortor condimentum lacinia quis. Pretium viverra suspendisse potenti nullam. Non tellus orci ac auctor augue mauris augue neque gravida. Tempus quam pellentesque nec nam aliquam sem et. Arcu non odio euismod lacinia at quis risus. Donec enim diam vulputate ut pharetra sit amet. Augue neque gravida in fermentum. Egestas maecenas pharetra convallis posuere morbi. Tempor commodo ullamcorper a lacus. Scelerisque purus semper eget duis at tellus at urna. Netus et malesuada fames ac turpis egestas. Blandit cursus risus at ultrices mi. Diam quis enim lobortis scelerisque fermentum. Sem integer vitae justo eget magna fermentum. Porttitor rhoncus dolor purus non enim. Nam at lectus urna duis convallis convallis tellus id interdum. Elit eget gravida cum sociis natoque penatibus et. Eros in cursus turpis massa tincidunt dui ut. Massa tincidunt nunc pulvinar sapien. Ipsum suspendisse ultrices gravida dictum fusce ut placerat orci nulla. - -In ornare quam viverra orci sagittis eu volutpat odio facilisis. Velit laoreet id donec ultrices tincidunt arcu non sodales neque. Eget nullam non nisi est. Posuere morbi leo urna molestie at elementum eu facilisis. Amet consectetur adipiscing elit duis. Risus feugiat in ante metus. Proin sed libero enim sed faucibus. Eget gravida cum sociis natoque penatibus et magnis. Semper feugiat nibh sed pulvinar proin. Ullamcorper malesuada proin libero nunc consequat. Felis eget nunc lobortis mattis aliquam faucibus purus in. Etiam sit amet nisl purus in mollis nunc. Sed euismod nisi porta lorem mollis. Purus sit amet luctus venenatis lectus magna fringilla. Est ante in nibh mauris. In dictum non consectetur a erat nam at lectus urna. - -Sit amet tellus cras adipiscing enim eu turpis. Eu feugiat pretium nibh ipsum consequat nisl vel pretium. Ultricies mi eget mauris pharetra et ultrices neque. Fames ac turpis egestas integer eget. Interdum velit laoreet id donec ultrices tincidunt. Et netus et malesuada fames. Auctor eu augue ut lectus. Netus et malesuada fames ac. Amet nisl suscipit adipiscing bibendum. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Quisque egestas diam in arcu cursus euismod quis viverra. Facilisi cras fermentum odio eu feugiat pretium. Integer enim neque volutpat ac tincidunt vitae semper quis. Hendrerit gravida rutrum quisque non tellus orci ac. Nibh praesent tristique magna sit. Sed odio morbi quis commodo odio. Mauris pharetra et ultrices neque ornare aenean euismod. At in tellus integer feugiat scelerisque. Mi quis hendrerit dolor magna eget est lorem ipsum dolor. Massa sapien faucibus et molestie. - -Eget duis at tellus at urna. At risus viverra adipiscing at in. Fermentum odio eu feugiat pretium nibh. Egestas integer eget aliquet nibh praesent tristique. Massa placerat duis ultricies lacus sed. Tortor dignissim convallis aenean et tortor at. Aliquet risus feugiat in ante metus dictum at. Sodales neque sodales ut etiam sit amet nisl purus in. Et netus et malesuada fames ac turpis egestas. Sed faucibus turpis in eu mi bibendum. Ultrices neque ornare aenean euismod. Non blandit massa enim nec dui nunc mattis. Nulla facilisi etiam dignissim diam quis. Enim sed faucibus turpis in eu. Odio aenean sed adipiscing diam donec adipiscing tristique. Vel quam elementum pulvinar etiam non quam lacus suspendisse. Scelerisque felis imperdiet proin fermentum leo vel. Ullamcorper a lacus vestibulum sed arcu non odio. Cursus risus at ultrices mi tempus. Viverra ipsum nunc aliquet bibendum enim. - -Maecenas sed enim ut sem viverra aliquet eget. Maecenas sed enim ut sem viverra aliquet eget sit. Maecenas accumsan lacus vel facilisis volutpat est velit. Varius sit amet mattis vulputate. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit. In eu mi bibendum neque egestas congue quisque egestas. Tortor at risus viverra adipiscing at in tellus integer feugiat. Eu scelerisque felis imperdiet proin fermentum leo. Risus sed vulputate odio ut enim. Massa sapien faucibus et molestie ac feugiat sed. Nascetur ridiculus mus mauris vitae ultricies leo. Ut tortor pretium viverra suspendisse potenti. - -Porttitor eget dolor morbi non arcu risus quis. Sem nulla pharetra diam sit amet nisl suscipit adipiscing bibendum. Diam maecenas sed enim ut sem viverra aliquet. Diam sollicitudin tempor id eu nisl. In fermentum et sollicitudin ac orci phasellus egestas tellus rutrum. Cras ornare arcu dui vivamus arcu felis bibendum ut tristique. Elementum pulvinar etiam non quam lacus. Enim sit amet venenatis urna cursus. Odio eu feugiat pretium nibh ipsum consequat nisl vel. Ornare massa eget egestas purus viverra accumsan. Diam donec adipiscing tristique risus nec. Nunc aliquet bibendum enim facilisis gravida neque convallis a. Rhoncus urna neque viverra justo nec ultrices. Turpis egestas sed tempus urna et pharetra pharetra massa. Et tortor at risus viverra. Tincidunt eget nullam non nisi est sit amet. Tincidunt vitae semper quis lectus nulla at volutpat diam. Egestas diam in arcu cursus euismod quis. - -Vitae sapien pellentesque habitant morbi tristique senectus et. Lorem ipsum dolor sit amet consectetur adipiscing elit. Id velit ut tortor pretium viverra suspendisse. Tortor id aliquet lectus proin. Pellentesque massa placerat duis ultricies. Neque aliquam vestibulum morbi blandit cursus risus at ultrices. Rhoncus urna neque viverra justo nec ultrices dui. Placerat duis ultricies lacus sed turpis tincidunt id aliquet risus. Risus feugiat in ante metus dictum at tempor commodo ullamcorper. Dolor sit amet consectetur adipiscing. Gravida neque convallis a cras semper auctor neque. Risus quis varius quam quisque id diam. Sit amet venenatis urna cursus eget nunc. Sit amet luctus venenatis lectus magna. In metus vulputate eu scelerisque felis imperdiet proin fermentum leo. Est sit amet facilisis magna etiam. Eu feugiat pretium nibh ipsum consequat nisl vel. Pellentesque pulvinar pellentesque habitant morbi. Urna et pharetra pharetra massa massa ultricies mi. Proin nibh nisl condimentum id venenatis a condimentum vitae. - -Id donec ultrices tincidunt arcu non. Nunc congue nisi vitae suscipit tellus mauris a diam maecenas. Sit amet nisl suscipit adipiscing bibendum est ultricies integer quis. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan. Enim sed faucibus turpis in. Lorem ipsum dolor sit amet consectetur adipiscing. Neque aliquam vestibulum morbi blandit cursus. Sed ullamcorper morbi tincidunt ornare massa eget. Duis tristique sollicitudin nibh sit amet commodo nulla facilisi nullam. Elit sed vulputate mi sit amet mauris commodo quis imperdiet. Erat velit scelerisque in dictum non consectetur a. Auctor neque vitae tempus quam pellentesque nec nam aliquam sem. Volutpat ac tincidunt vitae semper. Vestibulum rhoncus est pellentesque elit. Aliquam ultrices sagittis orci a scelerisque purus. Velit egestas dui id ornare. Pharetra et ultrices neque ornare aenean euismod elementum nisi. - -Id neque aliquam vestibulum morbi blandit cursus risus at ultrices. Lobortis mattis aliquam faucibus purus in. Id consectetur purus ut faucibus. Volutpat est velit egestas dui id. Elementum nibh tellus molestie nunc non blandit. Vitae aliquet nec ullamcorper sit. Pharetra vel turpis nunc eget lorem dolor sed. Viverra maecenas accumsan lacus vel facilisis volutpat. Neque viverra justo nec ultrices dui sapien eget mi. Condimentum vitae sapien pellentesque habitant morbi tristique senectus et. Ac felis donec et odio pellentesque diam volutpat. - -Orci eu lobortis elementum nibh tellus molestie. Suscipit tellus mauris a diam maecenas sed enim. Imperdiet massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada. Tellus molestie nunc non blandit massa enim nec dui. Integer enim neque volutpat ac tincidunt vitae semper quis lectus. Consectetur libero id faucibus nisl. Neque sodales ut etiam sit amet nisl. Lorem donec massa sapien faucibus et molestie ac feugiat. Convallis aenean et tortor at risus viverra adipiscing. Arcu felis bibendum ut tristique et egestas. Egestas purus viverra accumsan in. Faucibus turpis in eu mi bibendum. Auctor urna nunc id cursus metus aliquam eleifend mi. Sed libero enim sed faucibus turpis. Fames ac turpis egestas integer eget aliquet nibh. Suspendisse in est ante in nibh. Egestas congue quisque egestas diam in arcu cursus euismod. Consectetur adipiscing elit duis tristique. At in tellus integer feugiat scelerisque varius morbi. Rhoncus urna neque viverra justo nec. - -Eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Tempor orci dapibus ultrices in iaculis nunc sed augue. Faucibus nisl tincidunt eget nullam non nisi. Amet est placerat in egestas erat imperdiet. Mus mauris vitae ultricies leo integer malesuada nunc. Et sollicitudin ac orci phasellus. Dui accumsan sit amet nulla facilisi morbi tempus iaculis. Turpis massa tincidunt dui ut ornare lectus sit amet est. Facilisi morbi tempus iaculis urna id. Netus et malesuada fames ac turpis egestas integer. Est placerat in egestas erat imperdiet sed euismod. Ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. Nisi porta lorem mollis aliquam ut. - -Id semper risus in hendrerit gravida rutrum. Pulvinar neque laoreet suspendisse interdum consectetur. Velit euismod in pellentesque massa placerat. Molestie ac feugiat sed lectus. Proin sed libero enim sed faucibus turpis. At lectus urna duis convallis convallis tellus id interdum velit. Neque egestas congue quisque egestas diam. A diam sollicitudin tempor id. Ac tincidunt vitae semper quis lectus nulla at volutpat diam. Mi sit amet mauris commodo quis imperdiet massa. Amet est placerat in egestas erat imperdiet. Convallis convallis tellus id interdum velit. Egestas quis ipsum suspendisse ultrices gravida. - -Venenatis tellus in metus vulputate eu. Sit amet facilisis magna etiam tempor orci eu lobortis. Ut sem viverra aliquet eget sit amet. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing. Nec tincidunt praesent semper feugiat nibh sed. Malesuada fames ac turpis egestas maecenas. Nunc eget lorem dolor sed viverra ipsum nunc aliquet bibendum. Tincidunt arcu non sodales neque sodales ut etiam. Faucibus vitae aliquet nec ullamcorper sit amet risus nullam eget. Dictumst quisque sagittis purus sit amet volutpat. Turpis egestas maecenas pharetra convallis posuere morbi. Turpis cursus in hac habitasse platea dictumst quisque sagittis. Sed faucibus turpis in eu mi bibendum neque egestas congue. Commodo nulla facilisi nullam vehicula ipsum a arcu cursus. Urna nec tincidunt praesent semper feugiat. Semper viverra nam libero justo laoreet sit amet cursus. Non consectetur a erat nam at lectus urna. Arcu ac tortor dignissim convallis aenean et. - -Blandit aliquam etiam erat velit. Elementum nibh tellus molestie nunc non blandit. Posuere sollicitudin aliquam ultrices sagittis orci a. Lectus urna duis convallis convallis tellus id interdum. Rhoncus est pellentesque elit ullamcorper dignissim cras tincidunt lobortis feugiat. Facilisis mauris sit amet massa vitae tortor condimentum. Aliquet nec ullamcorper sit amet risus nullam. At imperdiet dui accumsan sit amet. Arcu dictum varius duis at consectetur lorem donec massa. Lacus sed turpis tincidunt id aliquet. Tellus elementum sagittis vitae et leo duis ut diam quam. Nulla pellentesque dignissim enim sit amet. A lacus vestibulum sed arcu non odio. Id faucibus nisl tincidunt eget nullam non nisi est. - -Dui sapien eget mi proin. Sem et tortor consequat id porta nibh venenatis. Cursus risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Egestas purus viverra accumsan in nisl nisi scelerisque. Malesuada fames ac turpis egestas. Amet venenatis urna cursus eget nunc. Potenti nullam ac tortor vitae purus faucibus ornare suspendisse sed. Arcu non odio euismod lacinia at quis risus. Vitae congue eu consequat ac felis donec. Id aliquet risus feugiat in ante. Quis auctor elit sed vulputate mi sit amet mauris. Sagittis vitae et leo duis ut diam quam. Gravida rutrum quisque non tellus. Arcu bibendum at varius vel pharetra vel turpis. Elementum pulvinar etiam non quam lacus suspendisse faucibus. Tellus in metus vulputate eu. - -Donec enim diam vulputate ut pharetra sit amet. Commodo ullamcorper a lacus vestibulum. Aliquam id diam maecenas ultricies mi eget mauris pharetra et. Nulla facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum. Ut faucibus pulvinar elementum integer enim neque volutpat ac tincidunt. Bibendum ut tristique et egestas quis ipsum suspendisse ultrices gravida. Cum sociis natoque penatibus et magnis dis. Imperdiet massa tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada. Ipsum faucibus vitae aliquet nec ullamcorper sit amet risus. Felis bibendum ut tristique et egestas quis. Vitae congue eu consequat ac felis donec. Accumsan lacus vel facilisis volutpat est velit egestas dui. Et egestas quis ipsum suspendisse ultrices gravida. Eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Facilisis magna etiam tempor orci. Nec ultrices dui sapien eget mi proin sed libero enim. Et leo duis ut diam quam nulla porttitor massa id. Pharetra convallis posuere morbi leo urna molestie at. Porta lorem mollis aliquam ut porttitor leo a diam. - -In ante metus dictum at tempor commodo ullamcorper a. Varius duis at consectetur lorem donec massa sapien faucibus et. Suspendisse ultrices gravida dictum fusce ut placerat. Quis hendrerit dolor magna eget est lorem ipsum dolor. Nullam eget felis eget nunc lobortis mattis aliquam faucibus purus. Laoreet id donec ultrices tincidunt. Vel pretium lectus quam id leo. Orci phasellus egestas tellus rutrum. Enim neque volutpat ac tincidunt vitae semper quis lectus nulla. Tortor at risus viverra adipiscing at in. - -Curabitur gravida arcu ac tortor dignissim convallis aenean et. Lectus magna fringilla urna porttitor. Quis ipsum suspendisse ultrices gravida dictum fusce. Ac feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Arcu vitae elementum curabitur vitae nunc sed. Mi bibendum neque egestas congue quisque egestas diam. Eu nisl nunc mi ipsum faucibus. Viverra tellus in hac habitasse platea dictumst vestibulum rhoncus est. Nunc aliquet bibendum enim facilisis. Eget velit aliquet sagittis id consectetur purus ut. Et tortor at risus viverra adipiscing. - -Placerat orci nulla pellentesque dignissim enim. Congue mauris rhoncus aenean vel elit scelerisque. Pharetra massa massa ultricies mi. Cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum. Pellentesque habitant morbi tristique senectus et netus. Mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Ac turpis egestas integer eget. Amet risus nullam eget felis eget nunc lobortis. Ornare aenean euismod elementum nisi quis eleifend. Pharetra massa massa ultricies mi quis. Condimentum lacinia quis vel eros donec ac. Tristique risus nec feugiat in fermentum. Egestas fringilla phasellus faucibus scelerisque eleifend. Semper risus in hendrerit gravida rutrum quisque non tellus. Augue mauris augue neque gravida in fermentum et sollicitudin. Ipsum faucibus vitae aliquet nec ullamcorper sit amet. Turpis cursus in hac habitasse platea. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Quis hendrerit dolor magna eget est lorem ipsum dolor. - -Tortor at auctor urna nunc id cursus. Tellus integer feugiat scelerisque varius morbi enim nunc. Purus semper eget duis at tellus at urna condimentum mattis. Sem fringilla ut morbi tincidunt augue interdum velit. Quam vulputate dignissim suspendisse in est ante in nibh. Pellentesque dignissim enim sit amet venenatis urna cursus. Phasellus faucibus scelerisque eleifend donec. Pellentesque diam volutpat commodo sed egestas. Faucibus ornare suspendisse sed nisi lacus sed. Donec pretium vulputate sapien nec. Aliquam etiam erat velit scelerisque in dictum. Ante metus dictum at tempor commodo. Viverra maecenas accumsan lacus vel. Ornare quam viverra orci sagittis eu. Turpis egestas maecenas pharetra convallis posuere morbi leo. Mauris pharetra et ultrices neque ornare aenean euismod elementum. Amet venenatis urna cursus eget nunc scelerisque viverra. Eu tincidunt tortor aliquam nulla. Ut lectus arcu bibendum at varius vel. - -Donec massa sapien faucibus et molestie ac feugiat sed. Amet luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. Laoreet suspendisse interdum consectetur libero id faucibus nisl tincidunt eget. Diam sollicitudin tempor id eu nisl. Velit aliquet sagittis id consectetur purus. Amet nisl purus in mollis nunc sed id semper. Porttitor lacus luctus accumsan tortor posuere. Non odio euismod lacinia at quis risus. Aenean et tortor at risus viverra adipiscing at in tellus. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Neque vitae tempus quam pellentesque nec nam aliquam sem. Adipiscing at in tellus integer. Ut tristique et egestas quis ipsum suspendisse ultrices. Pharetra convallis posuere morbi leo urna molestie at elementum eu. Neque egestas congue quisque egestas diam in arcu cursus euismod. Duis at tellus at urna. Vulputate sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum. Morbi enim nunc faucibus a pellentesque. Cursus eget nunc scelerisque viverra mauris in aliquam. Pulvinar etiam non quam lacus suspendisse faucibus. - -Mauris augue neque gravida in. Donec ac odio tempor orci dapibus ultrices in. Neque laoreet suspendisse interdum consectetur. Cursus in hac habitasse platea. Vel risus commodo viverra maecenas accumsan lacus vel facilisis. Id diam maecenas ultricies mi eget mauris pharetra et. At tempor commodo ullamcorper a lacus. Ipsum faucibus vitae aliquet nec ullamcorper sit. Posuere urna nec tincidunt praesent semper feugiat nibh. Tristique senectus et netus et malesuada. In nisl nisi scelerisque eu ultrices vitae auctor eu. Dignissim sodales ut eu sem integer vitae justo eget magna. Mauris cursus mattis molestie a iaculis at erat. Arcu ac tortor dignissim convallis. Vitae auctor eu augue ut lectus. - -Enim ut sem viverra aliquet eget sit. Eget mi proin sed libero enim sed faucibus. Sit amet mattis vulputate enim nulla aliquet porttitor lacus. Vitae tempus quam pellentesque nec. Sit amet consectetur adipiscing elit ut aliquam purus sit. Pulvinar pellentesque habitant morbi tristique senectus et netus. Et malesuada fames ac turpis egestas maecenas pharetra convallis posuere. Cursus mattis molestie a iaculis. Fermentum et sollicitudin ac orci phasellus egestas. Vel pharetra vel turpis nunc eget lorem. In arcu cursus euismod quis. Risus pretium quam vulputate dignissim suspendisse in est ante in. Adipiscing bibendum est ultricies integer quis auctor elit. Nunc aliquet bibendum enim facilisis gravida. Enim nunc faucibus a pellentesque sit amet porttitor. - -Pellentesque id nibh tortor id aliquet lectus proin nibh. Pretium quam vulputate dignissim suspendisse in est ante. Odio eu feugiat pretium nibh ipsum consequat nisl. Orci nulla pellentesque dignissim enim sit amet venenatis urna cursus. Dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Bibendum neque egestas congue quisque egestas diam in arcu cursus. Tortor id aliquet lectus proin nibh nisl condimentum id venenatis. Sem et tortor consequat id porta. Ac tortor dignissim convallis aenean. Tellus elementum sagittis vitae et leo duis ut diam quam. Quam quisque id diam vel. Nulla porttitor massa id neque aliquam vestibulum. Posuere lorem ipsum dolor sit. Turpis nunc eget lorem dolor. Ut lectus arcu bibendum at varius vel pharetra vel turpis. Pharetra vel turpis nunc eget lorem. Amet consectetur adipiscing elit pellentesque habitant morbi tristique senectus. - -Et tortor consequat id porta nibh venenatis cras. Odio facilisis mauris sit amet massa. Tincidunt arcu non sodales neque sodales ut. A scelerisque purus semper eget duis at tellus at urna. Varius sit amet mattis vulputate enim nulla aliquet porttitor lacus. Porta lorem mollis aliquam ut. Ipsum dolor sit amet consectetur adipiscing. Ut sem nulla pharetra diam sit. Tristique senectus et netus et malesuada fames. Nulla facilisi nullam vehicula ipsum a arcu cursus. - -Est pellentesque elit ullamcorper dignissim cras tincidunt. Tortor pretium viverra suspendisse potenti nullam. Lacus luctus accumsan tortor posuere. Tellus in hac habitasse platea dictumst vestibulum rhoncus. Molestie nunc non blandit massa enim nec dui nunc. Massa ultricies mi quis hendrerit dolor magna eget est lorem. Viverra mauris in aliquam sem fringilla. Neque aliquam vestibulum morbi blandit cursus risus at ultrices mi. Porta non pulvinar neque laoreet suspendisse interdum consectetur libero. In eu mi bibendum neque. Ultrices tincidunt arcu non sodales neque. Ut sem viverra aliquet eget sit amet tellus. Facilisis volutpat est velit egestas dui id. - -Varius vel pharetra vel turpis nunc eget lorem dolor sed. Mauris vitae ultricies leo integer malesuada nunc. Proin sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Dolor sit amet consectetur adipiscing. Quam elementum pulvinar etiam non quam. Eleifend mi in nulla posuere sollicitudin aliquam ultrices sagittis. Eu feugiat pretium nibh ipsum consequat nisl vel. Tellus elementum sagittis vitae et leo. Dolor magna eget est lorem ipsum. Ac feugiat sed lectus vestibulum mattis ullamcorper velit sed. Amet nisl purus in mollis nunc sed id semper risus. Dignissim convallis aenean et tortor at risus viverra adipiscing. Eget mauris pharetra et ultrices. Parturient montes nascetur ridiculus mus mauris. Faucibus nisl tincidunt eget nullam non nisi est. Senectus et netus et malesuada fames. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere lorem. Convallis convallis tellus id interdum velit laoreet id. Tellus mauris a diam maecenas sed enim ut. - -Nunc pulvinar sapien et ligula ullamcorper malesuada. Eu volutpat odio facilisis mauris sit. Sem et tortor consequat id porta. Dui sapien eget mi proin sed. Ultrices dui sapien eget mi proin. Vitae ultricies leo integer malesuada nunc vel. Cursus sit amet dictum sit amet justo donec enim. Cursus vitae congue mauris rhoncus aenean vel elit scelerisque mauris. Ut lectus arcu bibendum at. Cras pulvinar mattis nunc sed. Mattis pellentesque id nibh tortor id aliquet lectus. Odio facilisis mauris sit amet massa. Enim nunc faucibus a pellentesque sit amet porttitor eget dolor. Mauris nunc congue nisi vitae suscipit. Tortor id aliquet lectus proin nibh nisl condimentum. Ullamcorper velit sed ullamcorper morbi tincidunt. Vitae auctor eu augue ut lectus arcu bibendum at. Sapien et ligula ullamcorper malesuada proin libero. Enim blandit volutpat maecenas volutpat blandit aliquam. - -Sit amet mauris commodo quis imperdiet massa tincidunt. Vitae aliquet nec ullamcorper sit. Amet tellus cras adipiscing enim eu. Lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt. Vitae justo eget magna fermentum iaculis eu non diam. In egestas erat imperdiet sed euismod nisi. Nunc eget lorem dolor sed viverra ipsum nunc aliquet. Eu turpis egestas pretium aenean pharetra magna. Dolor sit amet consectetur adipiscing elit duis tristique. Nulla aliquet porttitor lacus luctus. Gravida arcu ac tortor dignissim convallis aenean. Blandit massa enim nec dui nunc mattis enim ut. Elementum sagittis vitae et leo duis ut diam. Rhoncus aenean vel elit scelerisque mauris pellentesque. Tempor orci dapibus ultrices in iaculis nunc. Nisl nisi scelerisque eu ultrices vitae auctor eu. - -Pellentesque sit amet porttitor eget dolor. Mattis molestie a iaculis at erat pellentesque adipiscing commodo. Ipsum consequat nisl vel pretium lectus quam id. Id aliquet lectus proin nibh nisl condimentum id venenatis. Vel pretium lectus quam id leo in vitae turpis massa. Urna nec tincidunt praesent semper feugiat. Volutpat blandit aliquam etiam erat velit. Vulputate enim nulla aliquet porttitor lacus luctus accumsan tortor posuere. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. Scelerisque mauris pellentesque pulvinar pellentesque. Id venenatis a condimentum vitae sapien. Pellentesque id nibh tortor id aliquet. Id donec ultrices tincidunt arcu non. Sagittis purus sit amet volutpat consequat. Arcu cursus vitae congue mauris rhoncus aenean vel elit. Diam sollicitudin tempor id eu. Volutpat maecenas volutpat blandit aliquam etiam erat velit. - -Vestibulum sed arcu non odio euismod lacinia at quis risus. Sit amet facilisis magna etiam tempor orci. Pretium nibh ipsum consequat nisl vel pretium lectus. At imperdiet dui accumsan sit amet nulla facilisi morbi tempus. Nec ultrices dui sapien eget mi proin sed libero enim. Elementum curabitur vitae nunc sed velit. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Nunc mi ipsum faucibus vitae. Quis vel eros donec ac odio tempor. Neque viverra justo nec ultrices dui. Egestas diam in arcu cursus euismod quis viverra nibh. Pellentesque nec nam aliquam sem et tortor consequat. Eu feugiat pretium nibh ipsum consequat. - -Ac auctor augue mauris augue. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing vitae. Et sollicitudin ac orci phasellus egestas. Nunc aliquet bibendum enim facilisis gravida. Commodo odio aenean sed adipiscing diam donec. Lectus mauris ultrices eros in cursus turpis massa. Justo laoreet sit amet cursus sit amet dictum. Amet est placerat in egestas erat imperdiet sed euismod nisi. Id leo in vitae turpis massa sed elementum tempus egestas. Morbi tristique senectus et netus. Orci dapibus ultrices in iaculis. Amet facilisis magna etiam tempor orci eu lobortis elementum. Hac habitasse platea dictumst quisque sagittis purus sit. Diam ut venenatis tellus in metus vulputate eu. Nibh tellus molestie nunc non. Volutpat lacus laoreet non curabitur gravida. Lectus proin nibh nisl condimentum id venenatis a. Enim facilisis gravida neque convallis a cras. Est velit egestas dui id ornare arcu odio ut sem. - -Morbi tristique senectus et netus. Penatibus et magnis dis parturient. Ut venenatis tellus in metus vulputate. Quis blandit turpis cursus in hac habitasse. Mauris vitae ultricies leo integer malesuada. Sed id semper risus in hendrerit gravida rutrum. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. Ac turpis egestas integer eget aliquet. Dapibus ultrices in iaculis nunc sed augue. Adipiscing tristique risus nec feugiat in fermentum posuere urna nec. Eu augue ut lectus arcu bibendum at. Malesuada fames ac turpis egestas sed tempus. In pellentesque massa placerat duis ultricies lacus sed turpis. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum. Bibendum arcu vitae elementum curabitur vitae nunc sed velit. Posuere urna nec tincidunt praesent semper feugiat. - -At lectus urna duis convallis convallis tellus id. Urna porttitor rhoncus dolor purus non. Laoreet suspendisse interdum consectetur libero. In hac habitasse platea dictumst vestibulum rhoncus est pellentesque. Integer vitae justo eget magna fermentum iaculis eu. Id consectetur purus ut faucibus pulvinar elementum integer. Vitae suscipit tellus mauris a diam. Ac turpis egestas maecenas pharetra convallis posuere morbi leo. Imperdiet massa tincidunt nunc pulvinar. Pretium aenean pharetra magna ac placerat. Placerat orci nulla pellentesque dignissim enim. - -Ultricies mi eget mauris pharetra et. Eu scelerisque felis imperdiet proin fermentum leo. Tincidunt eget nullam non nisi est sit amet facilisis. Leo vel orci porta non pulvinar neque laoreet suspendisse interdum. Lorem ipsum dolor sit amet consectetur adipiscing elit duis. Sapien nec sagittis aliquam malesuada bibendum. Rhoncus aenean vel elit scelerisque mauris. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Dignissim cras tincidunt lobortis feugiat. Risus at ultrices mi tempus imperdiet. Lobortis elementum nibh tellus molestie nunc non. Faucibus turpis in eu mi bibendum neque egestas congue. Risus at ultrices mi tempus imperdiet. Quisque egestas diam in arcu. Quis lectus nulla at volutpat diam ut venenatis. Nulla facilisi cras fermentum odio eu feugiat pretium. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices eros. - -Consectetur libero id faucibus nisl tincidunt eget nullam. Id diam vel quam elementum pulvinar. Arcu vitae elementum curabitur vitae nunc sed velit. Urna et pharetra pharetra massa massa ultricies. Cursus turpis massa tincidunt dui. Ut morbi tincidunt augue interdum velit euismod in. Blandit volutpat maecenas volutpat blandit. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Risus commodo viverra maecenas accumsan lacus vel facilisis volutpat. Lacus laoreet non curabitur gravida arcu ac tortor. Arcu ac tortor dignissim convallis aenean et tortor at risus. Adipiscing bibendum est ultricies integer quis. Sed odio morbi quis commodo odio aenean sed adipiscing. Ut aliquam purus sit amet luctus. - -Vitae congue eu consequat ac. Leo integer malesuada nunc vel risus commodo viverra maecenas. Luctus accumsan tortor posuere ac ut. Eu volutpat odio facilisis mauris sit amet massa. Adipiscing elit duis tristique sollicitudin nibh sit amet. Aliquam vestibulum morbi blandit cursus risus. Arcu cursus euismod quis viverra nibh cras pulvinar mattis. Aliquam vestibulum morbi blandit cursus risus. Aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Venenatis tellus in metus vulputate eu scelerisque. Vitae suscipit tellus mauris a. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Convallis a cras semper auctor neque vitae tempus quam. - -In arcu cursus euismod quis viverra nibh cras pulvinar mattis. Nunc non blandit massa enim nec. Ut etiam sit amet nisl purus. Est lorem ipsum dolor sit amet consectetur adipiscing. Id leo in vitae turpis massa sed elementum tempus. Libero enim sed faucibus turpis. Viverra aliquet eget sit amet tellus. Erat imperdiet sed euismod nisi porta lorem mollis aliquam ut. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. Pulvinar pellentesque habitant morbi tristique senectus et netus et. Auctor elit sed vulputate mi sit. Eleifend mi in nulla posuere sollicitudin. Pulvinar sapien et ligula ullamcorper malesuada proin. Malesuada proin libero nunc consequat interdum. Elementum sagittis vitae et leo duis ut diam quam. Ultricies leo integer malesuada nunc vel risus commodo viverra. Diam ut venenatis tellus in metus vulputate eu scelerisque felis. - -Phasellus egestas tellus rutrum tellus pellentesque. Pellentesque habitant morbi tristique senectus et netus. Morbi non arcu risus quis varius quam quisque id diam. Amet nisl suscipit adipiscing bibendum. Est ullamcorper eget nulla facilisi. Neque convallis a cras semper auctor neque. Aliquet porttitor lacus luctus accumsan tortor posuere. Nunc sed blandit libero volutpat sed. Venenatis urna cursus eget nunc scelerisque. Tortor dignissim convallis aenean et tortor at. Eget arcu dictum varius duis at consectetur. Feugiat sed lectus vestibulum mattis ullamcorper velit. Nisi vitae suscipit tellus mauris a diam maecenas sed enim. Sed augue lacus viverra vitae. Porttitor lacus luctus accumsan tortor posuere ac ut. Odio aenean sed adipiscing diam donec adipiscing tristique risus nec. Egestas erat imperdiet sed euismod. - -Viverra maecenas accumsan lacus vel. Nunc mattis enim ut tellus elementum sagittis vitae et leo. Pulvinar proin gravida hendrerit lectus a. Facilisi cras fermentum odio eu feugiat. Tempor orci dapibus ultrices in iaculis nunc. Turpis massa tincidunt dui ut. Neque volutpat ac tincidunt vitae. Facilisi etiam dignissim diam quis enim lobortis. Tincidunt dui ut ornare lectus. Mauris augue neque gravida in fermentum et. Enim ut sem viverra aliquet eget sit amet tellus cras. Ac auctor augue mauris augue neque gravida in. Sem et tortor consequat id porta nibh. Ullamcorper morbi tincidunt ornare massa. Nec feugiat nisl pretium fusce id velit ut tortor pretium. Semper viverra nam libero justo laoreet sit amet. Libero id faucibus nisl tincidunt eget nullam non. Est sit amet facilisis magna etiam tempor orci eu. Integer malesuada nunc vel risus commodo. - -Mattis ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. Fames ac turpis egestas sed. Elementum sagittis vitae et leo duis ut diam quam. Cursus in hac habitasse platea dictumst. Id semper risus in hendrerit gravida rutrum quisque non. Diam vel quam elementum pulvinar etiam non quam lacus. Egestas congue quisque egestas diam in arcu. Turpis egestas maecenas pharetra convallis posuere morbi. Nibh ipsum consequat nisl vel. Sit amet porttitor eget dolor morbi non arcu risus quis. Eros in cursus turpis massa tincidunt dui ut ornare. Tempus iaculis urna id volutpat lacus laoreet non curabitur gravida. Risus nec feugiat in fermentum. Sed arcu non odio euismod lacinia at quis. Suspendisse interdum consectetur libero id faucibus nisl tincidunt eget. Adipiscing at in tellus integer feugiat scelerisque varius morbi. Nunc mi ipsum faucibus vitae aliquet nec. Est velit egestas dui id ornare arcu odio ut sem. Facilisis gravida neque convallis a cras semper auctor neque. Nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque purus. - -A arcu cursus vitae congue mauris rhoncus aenean vel. Duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Sit amet volutpat consequat mauris nunc congue nisi. Mauris cursus mattis molestie a. Vehicula ipsum a arcu cursus vitae. Pellentesque pulvinar pellentesque habitant morbi. Eget mauris pharetra et ultrices neque ornare. Sed elementum tempus egestas sed sed risus pretium. Id nibh tortor id aliquet. At lectus urna duis convallis convallis tellus id. Amet dictum sit amet justo donec enim diam. Duis tristique sollicitudin nibh sit amet commodo nulla facilisi. Orci sagittis eu volutpat odio facilisis mauris. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Eget mi proin sed libero enim sed faucibus turpis in. Vulputate enim nulla aliquet porttitor lacus luctus accumsan tortor. Dolor purus non enim praesent elementum. Integer malesuada nunc vel risus. - -Pellentesque diam volutpat commodo sed egestas egestas. Dapibus ultrices in iaculis nunc sed. Maecenas pharetra convallis posuere morbi leo. Pellentesque habitant morbi tristique senectus et netus et malesuada. Mauris nunc congue nisi vitae suscipit tellus mauris a diam. Vel quam elementum pulvinar etiam non. Elit at imperdiet dui accumsan sit amet nulla. Ipsum faucibus vitae aliquet nec ullamcorper sit amet risus nullam. Nisl vel pretium lectus quam id leo in vitae. Est ullamcorper eget nulla facilisi etiam dignissim diam. - -Nulla aliquet porttitor lacus luctus accumsan tortor posuere ac ut. Blandit massa enim nec dui nunc mattis enim ut. Interdum posuere lorem ipsum dolor. Cras ornare arcu dui vivamus arcu felis bibendum. Scelerisque eu ultrices vitae auctor eu augue ut lectus. Pretium fusce id velit ut tortor pretium viverra suspendisse potenti. Vehicula ipsum a arcu cursus vitae congue mauris. Consectetur purus ut faucibus pulvinar elementum integer enim neque volutpat. Blandit libero volutpat sed cras ornare arcu. Vel quam elementum pulvinar etiam non. Vitae semper quis lectus nulla at volutpat diam ut. - -Elit scelerisque mauris pellentesque pulvinar. Ut venenatis tellus in metus vulputate eu scelerisque felis imperdiet. Mus mauris vitae ultricies leo integer malesuada. Viverra maecenas accumsan lacus vel facilisis volutpat est. Id semper risus in hendrerit gravida. Facilisis magna etiam tempor orci eu. Odio morbi quis commodo odio aenean sed adipiscing. Proin libero nunc consequat interdum varius. Scelerisque in dictum non consectetur a. Varius duis at consectetur lorem donec massa sapien faucibus. Et ultrices neque ornare aenean euismod elementum nisi. Quis imperdiet massa tincidunt nunc pulvinar sapien. Nam aliquam sem et tortor. Donec ultrices tincidunt arcu non sodales neque sodales. - -Id eu nisl nunc mi ipsum. Sit amet justo donec enim diam vulputate ut. At volutpat diam ut venenatis tellus in metus vulputate. In iaculis nunc sed augue lacus viverra. Sit amet consectetur adipiscing elit duis. Consectetur adipiscing elit ut aliquam purus sit amet. Convallis posuere morbi leo urna molestie at elementum eu. A condimentum vitae sapien pellentesque habitant morbi tristique senectus et. Adipiscing enim eu turpis egestas pretium. Elementum nisi quis eleifend quam adipiscing. Elit at imperdiet dui accumsan sit. Pharetra massa massa ultricies mi. - -Nullam vehicula ipsum a arcu. Felis donec et odio pellentesque diam volutpat commodo sed egestas. Elementum eu facilisis sed odio morbi quis. Ullamcorper velit sed ullamcorper morbi tincidunt. Nec ullamcorper sit amet risus. At consectetur lorem donec massa sapien. Eu facilisis sed odio morbi quis. Quis enim lobortis scelerisque fermentum. Cursus mattis molestie a iaculis at erat. Cursus turpis massa tincidunt dui ut ornare. Sed viverra ipsum nunc aliquet bibendum enim facilisis. Neque convallis a cras semper auctor neque. Metus aliquam eleifend mi in nulla. Turpis massa tincidunt dui ut ornare lectus sit. Tempus imperdiet nulla malesuada pellentesque elit eget gravida. - -Adipiscing diam donec adipiscing tristique risus nec. Non diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Libero enim sed faucibus turpis. Sit amet consectetur adipiscing elit ut aliquam purus sit. Pretium lectus quam id leo in. Senectus et netus et malesuada fames ac turpis egestas. Diam quam nulla porttitor massa id neque aliquam vestibulum morbi. Senectus et netus et malesuada fames ac turpis. Adipiscing elit pellentesque habitant morbi. Tellus elementum sagittis vitae et. Commodo odio aenean sed adipiscing diam donec adipiscing. Ac placerat vestibulum lectus mauris ultrices eros in cursus turpis. Vel eros donec ac odio tempor orci dapibus. Mattis rhoncus urna neque viverra justo nec. Justo laoreet sit amet cursus sit. Elit scelerisque mauris pellentesque pulvinar. Tristique senectus et netus et malesuada fames ac. - -Lorem ipsum dolor sit amet consectetur adipiscing elit ut aliquam. Non odio euismod lacinia at quis risus sed vulputate odio. Justo donec enim diam vulputate. Non arcu risus quis varius quam. Mauris commodo quis imperdiet massa. Sagittis purus sit amet volutpat consequat mauris. Blandit volutpat maecenas volutpat blandit aliquam. Eget arcu dictum varius duis at consectetur lorem donec. Auctor eu augue ut lectus arcu. A scelerisque purus semper eget duis at tellus at. - -Morbi leo urna molestie at elementum eu facilisis sed. Cursus turpis massa tincidunt dui ut. Eleifend mi in nulla posuere sollicitudin aliquam. Mauris augue neque gravida in fermentum et sollicitudin ac. Malesuada pellentesque elit eget gravida cum sociis natoque. Sit amet est placerat in egestas erat imperdiet sed euismod. Sed id semper risus in hendrerit gravida. A arcu cursus vitae congue mauris rhoncus aenean vel elit. Sit amet commodo nulla facilisi nullam vehicula. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Libero justo laoreet sit amet cursus. Rhoncus urna neque viverra justo nec ultrices dui sapien eget. Nunc aliquet bibendum enim facilisis gravida neque. Urna neque viverra justo nec ultrices dui sapien eget mi. - -Vestibulum mattis ullamcorper velit sed. Nisl nisi scelerisque eu ultrices vitae auctor eu augue. Faucibus a pellentesque sit amet porttitor eget dolor. Mi quis hendrerit dolor magna eget est. Aliquet lectus proin nibh nisl condimentum id venenatis. Maecenas pharetra convallis posuere morbi leo urna molestie at elementum. Mauris ultrices eros in cursus turpis massa tincidunt dui. At consectetur lorem donec massa sapien faucibus et. Placerat in egestas erat imperdiet sed euismod nisi porta. Ipsum consequat nisl vel pretium lectus quam id leo. - -A scelerisque purus semper eget. Odio eu feugiat pretium nibh ipsum consequat nisl. Non odio euismod lacinia at quis risus sed vulputate odio. Eget felis eget nunc lobortis mattis aliquam faucibus. Amet cursus sit amet dictum sit amet justo. Aliquet nibh praesent tristique magna sit. Mauris pellentesque pulvinar pellentesque habitant morbi tristique senectus et. Cursus vitae congue mauris rhoncus aenean vel. Pharetra et ultrices neque ornare aenean euismod elementum. Faucibus ornare suspendisse sed nisi lacus sed viverra tellus in. Ut venenatis tellus in metus vulputate eu scelerisque. Vitae et leo duis ut diam. Ut venenatis tellus in metus vulputate eu. Ut sem nulla pharetra diam sit amet nisl suscipit adipiscing. Risus viverra adipiscing at in tellus. Nibh cras pulvinar mattis nunc sed blandit libero volutpat. Massa tempor nec feugiat nisl pretium fusce id velit ut. Odio morbi quis commodo odio. Tortor dignissim convallis aenean et tortor at risus viverra adipiscing. - -Lacus sed turpis tincidunt id aliquet risus feugiat in ante. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus. Congue quisque egestas diam in arcu cursus. Congue eu consequat ac felis donec et odio pellentesque diam. Tempor orci eu lobortis elementum nibh tellus. Id consectetur purus ut faucibus pulvinar elementum. Vitae proin sagittis nisl rhoncus mattis. Velit ut tortor pretium viverra suspendisse potenti nullam ac tortor. Rutrum quisque non tellus orci ac auctor. Ultricies lacus sed turpis tincidunt id. Turpis egestas maecenas pharetra convallis posuere morbi leo. Eget sit amet tellus cras. Nunc vel risus commodo viverra maecenas accumsan lacus vel. Sed id semper risus in hendrerit. Sed id semper risus in hendrerit. Urna et pharetra pharetra massa massa. Purus gravida quis blandit turpis cursus in hac. - -Velit aliquet sagittis id consectetur purus ut faucibus pulvinar elementum. Commodo sed egestas egestas fringilla phasellus faucibus. Aliquam purus sit amet luctus venenatis lectus magna fringilla urna. Varius quam quisque id diam vel quam elementum. Eu turpis egestas pretium aenean. Amet risus nullam eget felis eget nunc lobortis mattis aliquam. Donec massa sapien faucibus et molestie ac feugiat sed lectus. Tincidunt eget nullam non nisi est. Ornare quam viverra orci sagittis eu volutpat odio. At consectetur lorem donec massa sapien faucibus et molestie. - -Massa placerat duis ultricies lacus sed turpis tincidunt id. Integer vitae justo eget magna fermentum. Sed viverra tellus in hac. Purus ut faucibus pulvinar elementum integer enim neque volutpat ac. Lacus sed viverra tellus in hac habitasse platea dictumst vestibulum. Pretium nibh ipsum consequat nisl vel pretium lectus. Natoque penatibus et magnis dis parturient montes nascetur ridiculus mus. Non blandit massa enim nec dui. Consequat id porta nibh venenatis cras sed felis. Sed libero enim sed faucibus turpis in. Libero volutpat sed cras ornare arcu dui. Dictum at tempor commodo ullamcorper a lacus. Ipsum a arcu cursus vitae congue mauris rhoncus. Commodo viverra maecenas accumsan lacus. - -Risus quis varius quam quisque id. Gravida in fermentum et sollicitudin ac orci phasellus egestas. Tellus id interdum velit laoreet id donec ultrices tincidunt. Amet risus nullam eget felis eget nunc. Viverra aliquet eget sit amet tellus cras. Aliquet eget sit amet tellus cras adipiscing enim. Non consectetur a erat nam at lectus. Morbi tristique senectus et netus. Ipsum faucibus vitae aliquet nec ullamcorper. Sagittis id consectetur purus ut faucibus pulvinar. - -Nunc mattis enim ut tellus elementum sagittis vitae et leo. Id neque aliquam vestibulum morbi blandit cursus risus at ultrices. Feugiat scelerisque varius morbi enim nunc. Ac odio tempor orci dapibus ultrices. Urna id volutpat lacus laoreet non curabitur gravida arcu ac. Donec et odio pellentesque diam volutpat commodo. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus. Id aliquet risus feugiat in ante metus dictum at tempor. Ut eu sem integer vitae justo eget. Blandit aliquam etiam erat velit scelerisque in dictum. Duis convallis convallis tellus id interdum. Nibh praesent tristique magna sit amet purus gravida quis blandit. Dui sapien eget mi proin sed libero enim sed. Diam phasellus vestibulum lorem sed risus. Orci nulla pellentesque dignissim enim sit amet venenatis urna. Pellentesque dignissim enim sit amet venenatis. Nisi quis eleifend quam adipiscing vitae proin. Sit amet facilisis magna etiam tempor orci eu. Purus in mollis nunc sed id semper risus in. - -Tortor vitae purus faucibus ornare suspendisse sed nisi. Lobortis elementum nibh tellus molestie nunc. Auctor urna nunc id cursus metus aliquam eleifend mi. Sit amet justo donec enim diam vulputate ut pharetra sit. Arcu ac tortor dignissim convallis aenean et tortor. Est placerat in egestas erat. Mi quis hendrerit dolor magna eget est. Tellus in metus vulputate eu scelerisque felis imperdiet proin. Amet consectetur adipiscing elit duis tristique. Nunc sed augue lacus viverra vitae. Viverra nibh cras pulvinar mattis nunc sed blandit libero. - -Nunc pulvinar sapien et ligula. Ut eu sem integer vitae justo eget. Eu nisl nunc mi ipsum faucibus vitae. Id eu nisl nunc mi ipsum faucibus. Ut faucibus pulvinar elementum integer enim. Porttitor lacus luctus accumsan tortor posuere. Massa tincidunt dui ut ornare lectus sit amet est. Tincidunt augue interdum velit euismod in pellentesque massa placerat. Nibh tortor id aliquet lectus proin nibh. Urna condimentum mattis pellentesque id nibh tortor id. Blandit turpis cursus in hac habitasse. Placerat vestibulum lectus mauris ultrices eros in cursus turpis massa. Lacus viverra vitae congue eu. Viverra nibh cras pulvinar mattis. Amet consectetur adipiscing elit pellentesque. Lacinia at quis risus sed vulputate odio ut enim blandit. Turpis egestas integer eget aliquet nibh praesent tristique magna sit. - -Nisi porta lorem mollis aliquam ut porttitor leo a diam. Cras ornare arcu dui vivamus. Amet consectetur adipiscing elit pellentesque habitant. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus. Lacinia quis vel eros donec ac. Adipiscing tristique risus nec feugiat in fermentum posuere urna. Velit dignissim sodales ut eu sem integer vitae. Vel risus commodo viverra maecenas accumsan lacus vel facilisis. Urna condimentum mattis pellentesque id nibh tortor id aliquet. Sapien eget mi proin sed libero enim sed. Id ornare arcu odio ut sem nulla pharetra diam sit. Id porta nibh venenatis cras sed felis. Tincidunt vitae semper quis lectus. Accumsan tortor posuere ac ut consequat semper viverra nam. Massa enim nec dui nunc. Scelerisque felis imperdiet proin fermentum leo vel orci. Turpis in eu mi bibendum neque. Consequat interdum varius sit amet mattis vulputate enim. Eu tincidunt tortor aliquam nulla facilisi cras. Sit amet nisl suscipit adipiscing bibendum est ultricies integer. - -Ac turpis egestas integer eget aliquet nibh praesent tristique. Magna fermentum iaculis eu non diam phasellus vestibulum lorem. Risus nullam eget felis eget nunc lobortis. Viverra vitae congue eu consequat ac. Convallis convallis tellus id interdum velit laoreet id donec ultrices. Lectus urna duis convallis convallis tellus. Pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Consequat mauris nunc congue nisi vitae suscipit. Nibh praesent tristique magna sit amet purus gravida. Amet luctus venenatis lectus magna fringilla urna. Vulputate ut pharetra sit amet aliquam id. - -Egestas diam in arcu cursus euismod quis. Nulla facilisi nullam vehicula ipsum a. Metus dictum at tempor commodo ullamcorper a lacus vestibulum. Non diam phasellus vestibulum lorem sed risus. Placerat in egestas erat imperdiet sed euismod nisi porta lorem. Diam vulputate ut pharetra sit amet aliquam. Id venenatis a condimentum vitae. Tristique magna sit amet purus. Egestas purus viverra accumsan in. Tortor id aliquet lectus proin nibh. Eu turpis egestas pretium aenean pharetra magna ac placerat vestibulum. Egestas sed sed risus pretium quam vulputate dignissim suspendisse. In pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. - -Ut sem nulla pharetra diam sit amet. Gravida cum sociis natoque penatibus et magnis dis parturient. Faucibus interdum posuere lorem ipsum dolor sit. Suspendisse faucibus interdum posuere lorem ipsum dolor sit amet consectetur. Vulputate mi sit amet mauris. Nisl condimentum id venenatis a condimentum vitae sapien. Arcu non sodales neque sodales ut etiam sit amet nisl. Posuere sollicitudin aliquam ultrices sagittis. Dapibus ultrices in iaculis nunc sed augue lacus viverra vitae. Quam viverra orci sagittis eu volutpat odio facilisis. Suscipit tellus mauris a diam maecenas sed enim ut sem. Cursus sit amet dictum sit amet justo donec enim diam. Nunc eget lorem dolor sed viverra. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Et malesuada fames ac turpis. Faucibus scelerisque eleifend donec pretium vulputate sapien. - -Enim ut tellus elementum sagittis vitae et leo duis. Viverra nam libero justo laoreet sit amet cursus. Pellentesque sit amet porttitor eget. Turpis nunc eget lorem dolor sed viverra ipsum nunc. Diam quam nulla porttitor massa id neque. Phasellus vestibulum lorem sed risus ultricies tristique. Integer vitae justo eget magna fermentum iaculis eu non. Scelerisque felis imperdiet proin fermentum leo vel orci porta non. Aliquam purus sit amet luctus venenatis. Et odio pellentesque diam volutpat commodo sed egestas. Pellentesque eu tincidunt tortor aliquam nulla. Scelerisque viverra mauris in aliquam sem fringilla ut morbi tincidunt. Dolor sit amet consectetur adipiscing. In ante metus dictum at tempor commodo ullamcorper a lacus. - -Turpis in eu mi bibendum neque egestas. Senectus et netus et malesuada fames ac. Egestas erat imperdiet sed euismod nisi porta. Vitae sapien pellentesque habitant morbi. Adipiscing elit pellentesque habitant morbi tristique. Et ligula ullamcorper malesuada proin libero. Eu augue ut lectus arcu bibendum at varius vel. Ut etiam sit amet nisl purus in mollis. Sed turpis tincidunt id aliquet risus feugiat in. Adipiscing at in tellus integer feugiat scelerisque varius morbi. Netus et malesuada fames ac turpis. Amet consectetur adipiscing elit ut aliquam. Non enim praesent elementum facilisis leo vel fringilla est. Egestas dui id ornare arcu. Imperdiet proin fermentum leo vel. - -Neque vitae tempus quam pellentesque nec nam aliquam sem et. Cursus in hac habitasse platea. Sit amet mauris commodo quis imperdiet. At in tellus integer feugiat scelerisque varius morbi enim. Malesuada nunc vel risus commodo viverra. Facilisis volutpat est velit egestas dui id. Magna fringilla urna porttitor rhoncus dolor purus non enim. Lorem dolor sed viverra ipsum nunc aliquet bibendum enim. Ipsum a arcu cursus vitae congue mauris rhoncus. Vivamus at augue eget arcu dictum varius. Habitant morbi tristique senectus et netus et. - -Mattis rhoncus urna neque viverra. Ipsum consequat nisl vel pretium. Pretium aenean pharetra magna ac placerat vestibulum. Nulla facilisi nullam vehicula ipsum a arcu cursus vitae. Curabitur gravida arcu ac tortor. Cras fermentum odio eu feugiat pretium nibh ipsum consequat. Fames ac turpis egestas integer eget aliquet nibh. Odio eu feugiat pretium nibh ipsum consequat nisl vel pretium. Velit euismod in pellentesque massa placerat duis ultricies lacus. Sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. At quis risus sed vulputate odio. - -Diam sollicitudin tempor id eu nisl nunc. Id interdum velit laoreet id donec ultrices tincidunt arcu. Adipiscing at in tellus integer feugiat scelerisque varius morbi. Massa placerat duis ultricies lacus sed turpis tincidunt id. Lorem ipsum dolor sit amet consectetur. Sapien eget mi proin sed libero enim sed. Sit amet justo donec enim diam vulputate ut. Nunc congue nisi vitae suscipit tellus mauris a diam maecenas. Odio facilisis mauris sit amet massa vitae tortor condimentum. Lectus quam id leo in vitae turpis massa sed elementum. Quam nulla porttitor massa id neque aliquam vestibulum. Faucibus pulvinar elementum integer enim neque. Sapien faucibus et molestie ac feugiat sed lectus vestibulum. Dui nunc mattis enim ut tellus elementum sagittis. Et tortor at risus viverra adipiscing at in tellus integer. Luctus accumsan tortor posuere ac. - -Mi sit amet mauris commodo quis imperdiet. Euismod lacinia at quis risus sed vulputate odio ut. Pellentesque dignissim enim sit amet venenatis urna cursus eget nunc. Scelerisque purus semper eget duis at. Vestibulum sed arcu non odio euismod lacinia. Tortor aliquam nulla facilisi cras fermentum odio eu feugiat. Iaculis eu non diam phasellus vestibulum lorem sed risus ultricies. Lacus sed turpis tincidunt id aliquet. Mauris in aliquam sem fringilla ut. Sollicitudin aliquam ultrices sagittis orci a scelerisque. Dolor magna eget est lorem ipsum dolor sit amet. Ornare lectus sit amet est. - -Malesuada bibendum arcu vitae elementum curabitur vitae nunc sed velit. Velit egestas dui id ornare arcu odio ut sem nulla. Lectus proin nibh nisl condimentum id venenatis a condimentum vitae. Non nisi est sit amet facilisis magna etiam tempor. Ultrices mi tempus imperdiet nulla malesuada pellentesque elit. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam ultrices. Tincidunt tortor aliquam nulla facilisi cras. Facilisis magna etiam tempor orci eu lobortis elementum nibh tellus. Scelerisque fermentum dui faucibus in. Duis ultricies lacus sed turpis tincidunt id aliquet risus feugiat. Cursus metus aliquam eleifend mi in nulla. Adipiscing elit ut aliquam purus. Elementum eu facilisis sed odio morbi quis. - -Dignissim cras tincidunt lobortis feugiat vivamus at augue. Purus in massa tempor nec feugiat nisl pretium. At lectus urna duis convallis convallis tellus id interdum velit. Aenean et tortor at risus viverra adipiscing at in tellus. Nulla aliquet enim tortor at. Ullamcorper morbi tincidunt ornare massa eget egestas purus viverra. Neque gravida in fermentum et sollicitudin ac orci phasellus egestas. Diam phasellus vestibulum lorem sed risus ultricies tristique. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Nunc mattis enim ut tellus. Orci dapibus ultrices in iaculis nunc sed augue lacus viverra. - -Nunc sed id semper risus in hendrerit gravida rutrum quisque. Tortor vitae purus faucibus ornare suspendisse. Eget felis eget nunc lobortis mattis aliquam faucibus purus. Semper quis lectus nulla at volutpat diam ut venenatis. Tellus cras adipiscing enim eu turpis egestas. Ultricies leo integer malesuada nunc vel risus commodo. Ullamcorper a lacus vestibulum sed arcu non odio. Ultrices vitae auctor eu augue ut lectus arcu bibendum at. Blandit cursus risus at ultrices mi. Arcu cursus vitae congue mauris rhoncus. Elit scelerisque mauris pellentesque pulvinar pellentesque. Cras semper auctor neque vitae tempus quam pellentesque nec. - -In fermentum et sollicitudin ac. Cras tincidunt lobortis feugiat vivamus at augue eget arcu dictum. Facilisis gravida neque convallis a cras semper auctor. Nibh mauris cursus mattis molestie a iaculis at erat. Auctor elit sed vulputate mi sit amet mauris commodo. Dignissim enim sit amet venenatis urna. Tincidunt ornare massa eget egestas. Et tortor at risus viverra adipiscing at in tellus. Pulvinar sapien et ligula ullamcorper malesuada proin libero nunc consequat. Amet nisl suscipit adipiscing bibendum est ultricies integer. Habitasse platea dictumst quisque sagittis purus sit amet. Aliquet porttitor lacus luctus accumsan tortor posuere. - -Eget nulla facilisi etiam dignissim diam. Semper feugiat nibh sed pulvinar. Sapien pellentesque habitant morbi tristique senectus et netus et malesuada. Semper auctor neque vitae tempus quam. Tellus id interdum velit laoreet id donec. At varius vel pharetra vel. Senectus et netus et malesuada fames ac turpis egestas. Proin nibh nisl condimentum id venenatis a condimentum vitae. Vestibulum lectus mauris ultrices eros in cursus turpis massa. Nisl suscipit adipiscing bibendum est. - -Cras ornare arcu dui vivamus arcu. Aliquam purus sit amet luctus venenatis lectus. In egestas erat imperdiet sed euismod. Massa enim nec dui nunc mattis enim ut tellus elementum. Velit dignissim sodales ut eu. Venenatis a condimentum vitae sapien pellentesque habitant. Convallis aenean et tortor at risus viverra adipiscing at in. Diam vulputate ut pharetra sit amet aliquam id diam. Consectetur adipiscing elit pellentesque habitant morbi tristique senectus et netus. Scelerisque eu ultrices vitae auctor eu augue. Volutpat est velit egestas dui id ornare arcu. Pretium vulputate sapien nec sagittis. Integer quis auctor elit sed vulputate. Morbi tristique senectus et netus et malesuada fames. Quam viverra orci sagittis eu volutpat odio facilisis mauris sit. - -Ullamcorper velit sed ullamcorper morbi. Cras fermentum odio eu feugiat. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Odio aenean sed adipiscing diam donec adipiscing. Morbi non arcu risus quis varius quam quisque id diam. Bibendum at varius vel pharetra vel. Faucibus a pellentesque sit amet porttitor eget dolor. Viverra maecenas accumsan lacus vel. Scelerisque varius morbi enim nunc faucibus a. Ultricies tristique nulla aliquet enim tortor at auctor. Leo in vitae turpis massa sed elementum tempus. Laoreet sit amet cursus sit amet dictum sit amet. Non arcu risus quis varius quam quisque id. Quam nulla porttitor massa id neque aliquam vestibulum morbi blandit. Vestibulum sed arcu non odio euismod lacinia. Ultrices vitae auctor eu augue ut lectus arcu bibendum at. Eleifend mi in nulla posuere sollicitudin. Vitae aliquet nec ullamcorper sit amet risus. - -Euismod lacinia at quis risus sed. Vitae justo eget magna fermentum iaculis eu non diam. Curabitur gravida arcu ac tortor. Quis lectus nulla at volutpat diam ut venenatis tellus. Rhoncus est pellentesque elit ullamcorper dignissim cras. Dolor sit amet consectetur adipiscing elit ut aliquam. Tortor at auctor urna nunc id cursus. A diam maecenas sed enim. Nibh cras pulvinar mattis nunc sed blandit libero. Magna sit amet purus gravida quis blandit turpis. Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula ipsum. Lobortis feugiat vivamus at augue eget. Suscipit tellus mauris a diam maecenas sed enim ut. Lacus luctus accumsan tortor posuere ac. Pellentesque elit eget gravida cum sociis. Condimentum id venenatis a condimentum. Vitae elementum curabitur vitae nunc sed velit dignissim sodales ut. Sit amet mauris commodo quis imperdiet massa tincidunt nunc. Ac auctor augue mauris augue neque gravida in fermentum. - -Tellus id interdum velit laoreet id donec ultrices tincidunt arcu. Eget aliquet nibh praesent tristique magna sit amet purus gravida. At erat pellentesque adipiscing commodo elit at. Magna etiam tempor orci eu lobortis elementum nibh tellus molestie. Cras ornare arcu dui vivamus. Magna fringilla urna porttitor rhoncus dolor purus. Aliquet lectus proin nibh nisl condimentum id. Sagittis vitae et leo duis. Ornare quam viverra orci sagittis. Consequat nisl vel pretium lectus quam id leo. Eget nulla facilisi etiam dignissim diam. Pretium quam vulputate dignissim suspendisse. Pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. In nulla posuere sollicitudin aliquam ultrices sagittis orci a. Tincidunt augue interdum velit euismod in pellentesque massa placerat. Duis ultricies lacus sed turpis tincidunt id aliquet risus. Condimentum vitae sapien pellentesque habitant morbi tristique senectus et netus. Sagittis vitae et leo duis ut. Fusce id velit ut tortor pretium. - -Gravida arcu ac tortor dignissim convallis aenean et tortor at. Massa tempor nec feugiat nisl pretium. Vestibulum mattis ullamcorper velit sed. Consequat nisl vel pretium lectus. Vel facilisis volutpat est velit egestas. Tortor condimentum lacinia quis vel eros donec ac odio tempor. Euismod in pellentesque massa placerat duis ultricies. Ac orci phasellus egestas tellus. Nisl condimentum id venenatis a condimentum vitae sapien pellentesque habitant. Cursus sit amet dictum sit amet justo donec enim diam. Quis commodo odio aenean sed adipiscing diam donec adipiscing tristique. Aliquam id diam maecenas ultricies mi eget. Risus at ultrices mi tempus. Habitasse platea dictumst vestibulum rhoncus est. Magna etiam tempor orci eu lobortis. - -Nec feugiat nisl pretium fusce. Gravida dictum fusce ut placerat orci nulla pellentesque dignissim. Id leo in vitae turpis massa sed elementum. Enim lobortis scelerisque fermentum dui faucibus in ornare. Habitant morbi tristique senectus et netus et malesuada. Lectus mauris ultrices eros in cursus turpis. Molestie nunc non blandit massa enim nec. Aliquam vestibulum morbi blandit cursus risus at ultrices. Eget nullam non nisi est sit amet facilisis. Lacus vel facilisis volutpat est velit egestas dui id. Cursus sit amet dictum sit amet justo donec enim. Justo eget magna fermentum iaculis eu non diam. Adipiscing elit duis tristique sollicitudin nibh sit amet commodo. - -Elementum nibh tellus molestie nunc non blandit massa enim. Diam donec adipiscing tristique risus nec feugiat in fermentum. Pretium quam vulputate dignissim suspendisse in est ante. Lorem ipsum dolor sit amet. Hendrerit dolor magna eget est lorem. Ut diam quam nulla porttitor massa id. Mauris nunc congue nisi vitae suscipit tellus mauris a diam. Condimentum id venenatis a condimentum vitae. Scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Pellentesque id nibh tortor id. Et molestie ac feugiat sed. - -Mauris in aliquam sem fringilla ut morbi tincidunt. Quam nulla porttitor massa id neque aliquam vestibulum. Orci phasellus egestas tellus rutrum tellus. Faucibus turpis in eu mi. A arcu cursus vitae congue mauris rhoncus aenean vel. Volutpat commodo sed egestas egestas. Sed turpis tincidunt id aliquet risus feugiat in ante metus. Fames ac turpis egestas integer eget aliquet nibh praesent tristique. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies leo. Enim nulla aliquet porttitor lacus luctus accumsan. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. - -Scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Malesuada nunc vel risus commodo viverra maecenas accumsan. Ut faucibus pulvinar elementum integer. Erat velit scelerisque in dictum non consectetur a erat. Odio ut enim blandit volutpat maecenas volutpat blandit. Purus sit amet volutpat consequat mauris. Non tellus orci ac auctor augue mauris augue. Dignissim cras tincidunt lobortis feugiat vivamus at. Sed tempus urna et pharetra pharetra massa. Quis blandit turpis cursus in hac. Rutrum quisque non tellus orci ac auctor augue mauris augue. Mauris vitae ultricies leo integer malesuada nunc vel. - -Viverra adipiscing at in tellus. Ac feugiat sed lectus vestibulum. Ipsum faucibus vitae aliquet nec ullamcorper sit. Sit amet est placerat in egestas erat imperdiet sed euismod. Nulla facilisi cras fermentum odio eu feugiat pretium. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Fermentum dui faucibus in ornare. Vitae aliquet nec ullamcorper sit amet risus. Arcu risus quis varius quam quisque id diam vel. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Praesent semper feugiat nibh sed pulvinar proin gravida hendrerit. Enim facilisis gravida neque convallis a cras semper auctor neque. Id cursus metus aliquam eleifend mi in. Est placerat in egestas erat imperdiet sed euismod. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. Purus sit amet volutpat consequat. Mi bibendum neque egestas congue quisque egestas diam in arcu. Aliquam nulla facilisi cras fermentum odio eu feugiat. - -Tortor at auctor urna nunc id cursus metus. Lectus arcu bibendum at varius. Commodo nulla facilisi nullam vehicula ipsum a arcu cursus vitae. Diam maecenas ultricies mi eget mauris pharetra. Sodales ut eu sem integer vitae justo. Egestas purus viverra accumsan in nisl nisi scelerisque eu. Felis eget nunc lobortis mattis aliquam faucibus purus in. Hac habitasse platea dictumst quisque sagittis. Pulvinar etiam non quam lacus suspendisse. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Nunc sed blandit libero volutpat sed cras ornare. Ut eu sem integer vitae justo. Vivamus at augue eget arcu dictum varius. Aenean sed adipiscing diam donec adipiscing tristique risus nec. Mus mauris vitae ultricies leo integer malesuada nunc vel risus. - -In mollis nunc sed id semper risus. Magna fermentum iaculis eu non diam phasellus vestibulum. Egestas maecenas pharetra convallis posuere morbi leo urna molestie. Adipiscing vitae proin sagittis nisl. Enim nec dui nunc mattis enim ut. Tellus id interdum velit laoreet id donec ultrices tincidunt. Sagittis orci a scelerisque purus semper eget duis. Faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper. Condimentum id venenatis a condimentum. Egestas congue quisque egestas diam in arcu cursus. Imperdiet dui accumsan sit amet. Elit ut aliquam purus sit amet luctus. Vitae semper quis lectus nulla at. Sed euismod nisi porta lorem mollis. Amet cursus sit amet dictum. Odio eu feugiat pretium nibh ipsum consequat. - -Laoreet non curabitur gravida arcu ac. Tempor commodo ullamcorper a lacus vestibulum. Et netus et malesuada fames. Sapien pellentesque habitant morbi tristique senectus et. Amet nisl purus in mollis nunc sed. Gravida in fermentum et sollicitudin ac orci phasellus. Ut tellus elementum sagittis vitae et. Viverra ipsum nunc aliquet bibendum enim facilisis gravida. Duis at consectetur lorem donec massa sapien faucibus et. Massa tempor nec feugiat nisl pretium fusce id velit. Senectus et netus et malesuada. Pellentesque nec nam aliquam sem et tortor consequat id porta. Nec feugiat in fermentum posuere urna nec tincidunt praesent semper. In nisl nisi scelerisque eu. Dolor sed viverra ipsum nunc. - -Est pellentesque elit ullamcorper dignissim. Sed faucibus turpis in eu mi. Mauris pharetra et ultrices neque ornare aenean euismod elementum nisi. Eu feugiat pretium nibh ipsum consequat nisl. Elit duis tristique sollicitudin nibh sit amet commodo. Vitae semper quis lectus nulla at volutpat diam. Proin fermentum leo vel orci. Cursus risus at ultrices mi tempus imperdiet nulla malesuada. Eros donec ac odio tempor. Orci porta non pulvinar neque laoreet suspendisse interdum. Facilisis leo vel fringilla est. Tincidunt dui ut ornare lectus sit amet est placerat. Faucibus a pellentesque sit amet porttitor. At risus viverra adipiscing at in tellus. Lacus sed turpis tincidunt id aliquet risus. Mattis pellentesque id nibh tortor id aliquet lectus proin nibh. - -Mauris pharetra et ultrices neque. Feugiat vivamus at augue eget. Risus nec feugiat in fermentum posuere urna nec tincidunt praesent. Leo a diam sollicitudin tempor id eu nisl. Volutpat diam ut venenatis tellus in metus vulputate eu. Tristique magna sit amet purus gravida quis blandit turpis. Maecenas pharetra convallis posuere morbi leo urna. Commodo nulla facilisi nullam vehicula ipsum. Nunc faucibus a pellentesque sit amet porttitor eget dolor morbi. Elit ut aliquam purus sit amet. Luctus accumsan tortor posuere ac ut consequat. Fermentum iaculis eu non diam phasellus vestibulum. Sit amet porttitor eget dolor morbi. Justo nec ultrices dui sapien eget mi proin. Viverra adipiscing at in tellus integer feugiat scelerisque. At volutpat diam ut venenatis tellus in metus vulputate. Pretium aenean pharetra magna ac placerat vestibulum lectus mauris. - -Elit ullamcorper dignissim cras tincidunt lobortis feugiat vivamus. Porttitor leo a diam sollicitudin tempor id. In nisl nisi scelerisque eu ultrices vitae. Sem nulla pharetra diam sit amet nisl. Viverra adipiscing at in tellus integer feugiat scelerisque. Leo in vitae turpis massa sed elementum. Arcu non sodales neque sodales ut etiam sit amet. Pretium fusce id velit ut tortor pretium viverra suspendisse. Purus in mollis nunc sed id semper risus. Interdum varius sit amet mattis vulputate enim nulla aliquet. Mauris pharetra et ultrices neque ornare. Congue eu consequat ac felis. Eget arcu dictum varius duis at consectetur lorem donec massa. Sapien nec sagittis aliquam malesuada bibendum arcu vitae. Pretium aenean pharetra magna ac. Elementum sagittis vitae et leo duis ut diam quam nulla. Proin sed libero enim sed faucibus turpis in. Maecenas ultricies mi eget mauris. Sed turpis tincidunt id aliquet risus feugiat in ante metus. - -Nec nam aliquam sem et tortor consequat id porta. Sed ullamcorper morbi tincidunt ornare massa. Facilisis sed odio morbi quis commodo odio aenean sed. Pharetra sit amet aliquam id. Aenean pharetra magna ac placerat vestibulum. Nunc sed velit dignissim sodales. Ut consequat semper viverra nam. Quam lacus suspendisse faucibus interdum. Tincidunt tortor aliquam nulla facilisi cras fermentum odio. Pretium aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Sit amet tellus cras adipiscing enim eu. Morbi tincidunt augue interdum velit euismod in pellentesque. Lobortis mattis aliquam faucibus purus in massa tempor. Non quam lacus suspendisse faucibus interdum. Mauris a diam maecenas sed enim ut. Orci a scelerisque purus semper eget duis at tellus. Leo in vitae turpis massa sed elementum tempus egestas. Netus et malesuada fames ac turpis egestas maecenas pharetra. Enim nec dui nunc mattis enim ut tellus elementum sagittis. - -Integer vitae justo eget magna. Luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. Dolor magna eget est lorem. Interdum consectetur libero id faucibus nisl tincidunt eget nullam non. Risus quis varius quam quisque id diam vel. Cursus turpis massa tincidunt dui ut ornare lectus. Ut ornare lectus sit amet est. Aliquet nec ullamcorper sit amet risus nullam. Dolor sit amet consectetur adipiscing elit pellentesque habitant. Purus ut faucibus pulvinar elementum integer enim neque volutpat ac. In nisl nisi scelerisque eu ultrices vitae. Imperdiet sed euismod nisi porta lorem mollis aliquam ut. Imperdiet sed euismod nisi porta lorem mollis aliquam. Mauris sit amet massa vitae tortor condimentum. Ornare arcu dui vivamus arcu felis. Id faucibus nisl tincidunt eget nullam. Senectus et netus et malesuada. Viverra ipsum nunc aliquet bibendum enim facilisis. Eu sem integer vitae justo eget magna fermentum iaculis. Natoque penatibus et magnis dis parturient montes nascetur ridiculus. - -Sit amet tellus cras adipiscing. Elit pellentesque habitant morbi tristique senectus et. Tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius. Ut tortor pretium viverra suspendisse potenti nullam ac tortor vitae. Sit amet facilisis magna etiam tempor. Justo donec enim diam vulputate ut pharetra. Nec feugiat in fermentum posuere urna nec. Luctus venenatis lectus magna fringilla. Interdum velit euismod in pellentesque massa. Nisl purus in mollis nunc sed id semper risus in. Vel quam elementum pulvinar etiam non. Aliquet nec ullamcorper sit amet risus nullam eget felis. Nibh venenatis cras sed felis. Id consectetur purus ut faucibus pulvinar elementum integer enim. Integer eget aliquet nibh praesent tristique magna. Consectetur adipiscing elit duis tristique sollicitudin. - -Volutpat est velit egestas dui id. Pharetra vel turpis nunc eget lorem dolor sed. Nulla malesuada pellentesque elit eget. Ullamcorper morbi tincidunt ornare massa. Orci sagittis eu volutpat odio facilisis mauris sit. Nec feugiat in fermentum posuere urna. Turpis massa tincidunt dui ut. Scelerisque eu ultrices vitae auctor eu augue ut. Nulla facilisi morbi tempus iaculis urna. Egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate. Sed risus pretium quam vulputate dignissim suspendisse in. Quam vulputate dignissim suspendisse in est ante in nibh mauris. Est ultricies integer quis auctor elit sed vulputate mi sit. Ultrices sagittis orci a scelerisque purus semper eget duis at. Egestas sed tempus urna et. Magna eget est lorem ipsum dolor sit amet. Lacus sed turpis tincidunt id. - -Amet luctus venenatis lectus magna fringilla urna porttitor. Et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit. Mi tempus imperdiet nulla malesuada pellentesque elit eget gravida cum. Vivamus arcu felis bibendum ut tristique et egestas quis ipsum. Vitae purus faucibus ornare suspendisse. Tempor id eu nisl nunc. Sit amet justo donec enim. Lorem ipsum dolor sit amet consectetur. Quisque egestas diam in arcu cursus euismod quis viverra nibh. Diam maecenas ultricies mi eget mauris pharetra. Semper auctor neque vitae tempus quam. Integer quis auctor elit sed vulputate mi sit. - -Elementum curabitur vitae nunc sed. Felis eget velit aliquet sagittis id consectetur. Rhoncus urna neque viverra justo nec ultrices dui sapien. Consequat id porta nibh venenatis. Nisl rhoncus mattis rhoncus urna. Malesuada proin libero nunc consequat interdum varius. Sed vulputate mi sit amet. Aliquam id diam maecenas ultricies mi. Quisque egestas diam in arcu cursus euismod quis. Suscipit tellus mauris a diam maecenas sed. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Sapien nec sagittis aliquam malesuada bibendum. Elementum nisi quis eleifend quam adipiscing vitae proin sagittis nisl. At imperdiet dui accumsan sit amet nulla facilisi morbi tempus. Mi bibendum neque egestas congue. Pellentesque elit ullamcorper dignissim cras tincidunt. Id semper risus in hendrerit gravida rutrum. Risus nec feugiat in fermentum posuere urna nec. - -Lacus vestibulum sed arcu non odio euismod lacinia at. Tristique senectus et netus et malesuada fames ac. Rutrum quisque non tellus orci ac auctor. Venenatis cras sed felis eget velit aliquet sagittis id. Nulla facilisi etiam dignissim diam quis enim. Suspendisse ultrices gravida dictum fusce ut placerat orci. Risus at ultrices mi tempus imperdiet nulla. Cras adipiscing enim eu turpis. Varius duis at consectetur lorem donec massa. Interdum velit euismod in pellentesque massa placerat duis ultricies. Enim ut tellus elementum sagittis vitae et leo duis. Pulvinar sapien et ligula ullamcorper malesuada. Rhoncus urna neque viverra justo nec ultrices dui. Nibh tortor id aliquet lectus proin nibh nisl condimentum. Odio euismod lacinia at quis risus sed vulputate odio ut. - -Id cursus metus aliquam eleifend mi in nulla posuere sollicitudin. Pretium viverra suspendisse potenti nullam. Volutpat blandit aliquam etiam erat velit scelerisque in dictum. Placerat duis ultricies lacus sed turpis. Enim facilisis gravida neque convallis a cras semper auctor. Ac turpis egestas maecenas pharetra convallis posuere. Elit duis tristique sollicitudin nibh. Vulputate eu scelerisque felis imperdiet proin fermentum. Pulvinar etiam non quam lacus suspendisse faucibus. Semper viverra nam libero justo laoreet. Id consectetur purus ut faucibus pulvinar elementum integer. Justo nec ultrices dui sapien eget. Sed cras ornare arcu dui vivamus arcu felis bibendum ut. Lobortis scelerisque fermentum dui faucibus in ornare quam viverra. Ac felis donec et odio pellentesque diam. Arcu odio ut sem nulla. A lacus vestibulum sed arcu. Cras fermentum odio eu feugiat pretium nibh. Nulla facilisi nullam vehicula ipsum a arcu cursus. Massa eget egestas purus viverra accumsan in nisl. - -Vitae congue mauris rhoncus aenean vel elit scelerisque. Amet nulla facilisi morbi tempus. Neque convallis a cras semper auctor neque vitae tempus. Facilisi etiam dignissim diam quis enim lobortis scelerisque. Elit ut aliquam purus sit. Urna porttitor rhoncus dolor purus non enim praesent. Id donec ultrices tincidunt arcu non sodales neque. Nibh sit amet commodo nulla facilisi nullam vehicula ipsum a. Non pulvinar neque laoreet suspendisse. Quam elementum pulvinar etiam non quam lacus suspendisse. Sagittis purus sit amet volutpat consequat mauris. Id aliquet lectus proin nibh nisl. Id venenatis a condimentum vitae sapien. Morbi tristique senectus et netus et malesuada fames ac turpis. Mattis rhoncus urna neque viverra. Hac habitasse platea dictumst vestibulum. Aliquam sem fringilla ut morbi tincidunt augue interdum velit euismod. Consectetur adipiscing elit pellentesque habitant morbi tristique senectus. Pellentesque elit eget gravida cum sociis. - -Nec dui nunc mattis enim ut tellus elementum sagittis vitae. Morbi tristique senectus et netus et. Nisl nisi scelerisque eu ultrices vitae auctor eu augue ut. Nisl condimentum id venenatis a condimentum vitae. Tellus in hac habitasse platea dictumst vestibulum rhoncus est. Mollis aliquam ut porttitor leo. Felis eget nunc lobortis mattis aliquam. Aliquet enim tortor at auctor urna nunc. Eget mauris pharetra et ultrices neque ornare aenean. Eget mi proin sed libero enim sed faucibus. In cursus turpis massa tincidunt dui ut. Augue eget arcu dictum varius. Elementum facilisis leo vel fringilla. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Vitae nunc sed velit dignissim sodales. Odio pellentesque diam volutpat commodo. Suscipit tellus mauris a diam. Dui id ornare arcu odio ut sem nulla pharetra. - -Viverra suspendisse potenti nullam ac tortor. Senectus et netus et malesuada fames ac turpis egestas integer. Faucibus vitae aliquet nec ullamcorper. Tristique sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula. Ut faucibus pulvinar elementum integer enim neque volutpat. Nec dui nunc mattis enim. Quam quisque id diam vel quam elementum pulvinar. Habitant morbi tristique senectus et netus. Sit amet luctus venenatis lectus magna fringilla urna. Sed augue lacus viverra vitae congue eu consequat. Libero volutpat sed cras ornare. - -Aliquam sem fringilla ut morbi. Morbi enim nunc faucibus a pellentesque. Ac turpis egestas sed tempus urna et pharetra pharetra massa. Quis risus sed vulputate odio ut enim blandit volutpat maecenas. Congue eu consequat ac felis donec et odio pellentesque. Justo eget magna fermentum iaculis eu non diam phasellus. In iaculis nunc sed augue lacus viverra. Ut faucibus pulvinar elementum integer enim neque. Vitae sapien pellentesque habitant morbi tristique. Lorem sed risus ultricies tristique nulla aliquet enim tortor at. Erat velit scelerisque in dictum non consectetur a. Ligula ullamcorper malesuada proin libero nunc consequat interdum. Volutpat ac tincidunt vitae semper quis lectus nulla at. Vulputate enim nulla aliquet porttitor lacus luctus accumsan tortor posuere. Non diam phasellus vestibulum lorem sed risus ultricies. Massa enim nec dui nunc mattis enim. Ipsum a arcu cursus vitae congue. - -Aliquam sem et tortor consequat id porta. Metus aliquam eleifend mi in nulla posuere. Nisl vel pretium lectus quam id leo in vitae. Donec ac odio tempor orci dapibus ultrices in. Blandit volutpat maecenas volutpat blandit aliquam etiam erat. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices. Cras pulvinar mattis nunc sed blandit libero volutpat. Consequat interdum varius sit amet. Amet consectetur adipiscing elit pellentesque habitant. Mi proin sed libero enim sed faucibus turpis. Cursus turpis massa tincidunt dui. - -Eu non diam phasellus vestibulum lorem sed. Vitae auctor eu augue ut. Non nisi est sit amet facilisis magna etiam. Sapien nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Sagittis eu volutpat odio facilisis mauris sit. Quam viverra orci sagittis eu volutpat odio facilisis mauris. At ultrices mi tempus imperdiet nulla malesuada. Et malesuada fames ac turpis egestas. Pharetra vel turpis nunc eget. Quam id leo in vitae turpis massa sed elementum tempus. - -Vulputate dignissim suspendisse in est. Mauris in aliquam sem fringilla ut morbi tincidunt. Ut tortor pretium viverra suspendisse potenti nullam. Viverra aliquet eget sit amet. Orci a scelerisque purus semper eget duis. Iaculis urna id volutpat lacus laoreet non curabitur. Amet est placerat in egestas erat imperdiet. Dolor magna eget est lorem ipsum. Blandit volutpat maecenas volutpat blandit. Amet porttitor eget dolor morbi. Neque sodales ut etiam sit. Ante in nibh mauris cursus mattis molestie a iaculis at. Tristique senectus et netus et malesuada fames ac turpis egestas. Tortor pretium viverra suspendisse potenti. Pellentesque eu tincidunt tortor aliquam nulla facilisi. Tortor pretium viverra suspendisse potenti nullam ac tortor vitae purus. Id interdum velit laoreet id. Tristique senectus et netus et malesuada fames. Vulputate odio ut enim blandit. - -Augue lacus viverra vitae congue eu consequat ac felis donec. Sed felis eget velit aliquet sagittis id consectetur purus ut. Enim sit amet venenatis urna cursus eget nunc scelerisque. Orci eu lobortis elementum nibh tellus molestie. Arcu cursus euismod quis viverra nibh cras pulvinar mattis. Amet aliquam id diam maecenas ultricies mi eget mauris. Vulputate mi sit amet mauris. Cursus metus aliquam eleifend mi. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan sit. Porta nibh venenatis cras sed felis eget velit aliquet sagittis. Volutpat lacus laoreet non curabitur gravida arcu ac tortor dignissim. Turpis egestas pretium aenean pharetra magna ac placerat vestibulum lectus. Sed risus ultricies tristique nulla aliquet enim tortor at auctor. Integer feugiat scelerisque varius morbi. Lobortis mattis aliquam faucibus purus. Ultricies mi quis hendrerit dolor. Fusce id velit ut tortor pretium viverra suspendisse potenti. Massa id neque aliquam vestibulum morbi blandit cursus. Sit amet porttitor eget dolor morbi non arcu risus quis. - -Tincidunt dui ut ornare lectus. Arcu vitae elementum curabitur vitae. Ultricies integer quis auctor elit sed vulputate. Vitae sapien pellentesque habitant morbi tristique. Rhoncus dolor purus non enim praesent elementum. Quis commodo odio aenean sed adipiscing diam. Malesuada fames ac turpis egestas. Risus viverra adipiscing at in tellus integer. Elementum integer enim neque volutpat ac tincidunt. Enim praesent elementum facilisis leo. Egestas maecenas pharetra convallis posuere morbi leo urna molestie at. Porttitor eget dolor morbi non arcu risus quis varius quam. Ut aliquam purus sit amet luctus venenatis lectus. Nisi scelerisque eu ultrices vitae auctor eu augue ut. Diam in arcu cursus euismod quis. Mattis vulputate enim nulla aliquet porttitor lacus luctus accumsan tortor. - -Semper risus in hendrerit gravida rutrum quisque non tellus orci. Risus viverra adipiscing at in tellus integer. Sodales ut eu sem integer vitae justo eget. Est sit amet facilisis magna etiam tempor orci eu lobortis. Tristique risus nec feugiat in fermentum posuere. Odio euismod lacinia at quis. At elementum eu facilisis sed odio morbi quis. Sit amet justo donec enim diam vulputate ut pharetra sit. Habitant morbi tristique senectus et netus et. Pellentesque sit amet porttitor eget dolor morbi. Urna neque viverra justo nec ultrices dui sapien. - -Sed sed risus pretium quam vulputate dignissim. Nisi est sit amet facilisis magna etiam. Tortor posuere ac ut consequat semper viverra nam libero justo. Scelerisque purus semper eget duis at tellus at urna condimentum. Eget nulla facilisi etiam dignissim diam quis enim lobortis scelerisque. Non consectetur a erat nam at lectus urna duis convallis. Odio ut enim blandit volutpat maecenas. Pulvinar mattis nunc sed blandit libero volutpat. Porttitor massa id neque aliquam vestibulum morbi blandit cursus. Est sit amet facilisis magna. Dignissim sodales ut eu sem integer vitae justo eget. Aliquam purus sit amet luctus venenatis. Fermentum iaculis eu non diam phasellus vestibulum lorem sed. Id diam vel quam elementum pulvinar etiam non quam. Augue mauris augue neque gravida in fermentum et sollicitudin. Est velit egestas dui id. Eu nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Sapien eget mi proin sed. Est ante in nibh mauris cursus. - -Odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Volutpat maecenas volutpat blandit aliquam etiam. Suspendisse faucibus interdum posuere lorem ipsum dolor. Magna sit amet purus gravida. Tincidunt dui ut ornare lectus sit amet est. Sagittis aliquam malesuada bibendum arcu vitae elementum curabitur. Ac placerat vestibulum lectus mauris ultrices eros in cursus. Tellus pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum. Adipiscing commodo elit at imperdiet dui accumsan sit. Sollicitudin nibh sit amet commodo nulla facilisi nullam. Pretium viverra suspendisse potenti nullam ac. Feugiat scelerisque varius morbi enim nunc faucibus a. Habitasse platea dictumst quisque sagittis purus sit amet volutpat consequat. Habitant morbi tristique senectus et netus et. Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Egestas congue quisque egestas diam in arcu. Imperdiet sed euismod nisi porta lorem mollis aliquam. Dui nunc mattis enim ut. Nec sagittis aliquam malesuada bibendum arcu vitae elementum curabitur vitae. Ipsum consequat nisl vel pretium lectus quam id leo. - -Cras pulvinar mattis nunc sed. Ante in nibh mauris cursus. Ac tortor dignissim convallis aenean et. At imperdiet dui accumsan sit. Fermentum posuere urna nec tincidunt praesent. Fringilla est ullamcorper eget nulla facilisi etiam dignissim. Enim facilisis gravida neque convallis a cras semper. Facilisi morbi tempus iaculis urna. Tempus egestas sed sed risus pretium quam. Morbi tempus iaculis urna id volutpat lacus laoreet non. Vitae congue mauris rhoncus aenean vel. Facilisis leo vel fringilla est. A arcu cursus vitae congue mauris rhoncus. Pellentesque dignissim enim sit amet. - -Ut faucibus pulvinar elementum integer enim neque volutpat. In ante metus dictum at tempor commodo ullamcorper a. Egestas sed tempus urna et pharetra. Leo in vitae turpis massa sed elementum tempus egestas. Vitae nunc sed velit dignissim sodales ut eu. Lacinia at quis risus sed vulputate odio ut. Dignissim cras tincidunt lobortis feugiat vivamus at augue. Quisque sagittis purus sit amet volutpat consequat. Nullam ac tortor vitae purus. Sit amet justo donec enim diam. Id velit ut tortor pretium viverra suspendisse. Sed adipiscing diam donec adipiscing tristique risus nec. Arcu dictum varius duis at consectetur lorem donec massa sapien. Interdum velit euismod in pellentesque massa placerat. Malesuada fames ac turpis egestas maecenas pharetra. Velit ut tortor pretium viverra suspendisse potenti nullam ac tortor. Nam libero justo laoreet sit amet cursus. - -A pellentesque sit amet porttitor eget dolor. Eget arcu dictum varius duis at consectetur lorem donec massa. Et sollicitudin ac orci phasellus egestas tellus rutrum. Facilisi nullam vehicula ipsum a. Risus in hendrerit gravida rutrum quisque non tellus orci ac. Blandit volutpat maecenas volutpat blandit aliquam. Viverra orci sagittis eu volutpat odio facilisis mauris sit. Tristique et egestas quis ipsum suspendisse ultrices gravida dictum. Ac tortor dignissim convallis aenean et tortor. Interdum varius sit amet mattis vulputate enim nulla aliquet porttitor. Nec feugiat in fermentum posuere urna nec tincidunt. - -Viverra justo nec ultrices dui sapien eget. Adipiscing elit pellentesque habitant morbi tristique senectus et. In nisl nisi scelerisque eu ultrices vitae auctor eu augue. Faucibus et molestie ac feugiat. Amet nisl purus in mollis nunc. Elementum nibh tellus molestie nunc non blandit. Dui nunc mattis enim ut tellus elementum. Blandit massa enim nec dui nunc mattis enim. Velit ut tortor pretium viverra suspendisse potenti nullam ac. Urna molestie at elementum eu facilisis sed odio morbi. Magna sit amet purus gravida quis blandit turpis. Viverra nam libero justo laoreet sit amet cursus sit amet. Et malesuada fames ac turpis egestas integer. Facilisis magna etiam tempor orci. Vitae elementum curabitur vitae nunc sed. Vitae ultricies leo integer malesuada nunc vel risus commodo. Ultrices tincidunt arcu non sodales neque sodales. Dui vivamus arcu felis bibendum ut tristique et egestas quis. Tortor dignissim convallis aenean et tortor. - -Morbi tristique senectus et netus et malesuada fames. Viverra maecenas accumsan lacus vel facilisis volutpat est. Pulvinar mattis nunc sed blandit libero volutpat sed. Proin sagittis nisl rhoncus mattis rhoncus urna. Mauris cursus mattis molestie a iaculis. Est placerat in egestas erat imperdiet sed euismod nisi. A diam sollicitudin tempor id. Mauris cursus mattis molestie a iaculis. Pellentesque adipiscing commodo elit at imperdiet dui accumsan. Pellentesque id nibh tortor id. Mi bibendum neque egestas congue quisque egestas diam in arcu. Id faucibus nisl tincidunt eget nullam non nisi. Cras fermentum odio eu feugiat pretium nibh ipsum. A iaculis at erat pellentesque. Porta non pulvinar neque laoreet. Arcu felis bibendum ut tristique et egestas. - -Donec pretium vulputate sapien nec sagittis aliquam. Lobortis scelerisque fermentum dui faucibus in ornare quam viverra. Quis viverra nibh cras pulvinar mattis nunc. Ipsum a arcu cursus vitae. Ut sem viverra aliquet eget sit amet tellus cras adipiscing. Pretium fusce id velit ut tortor pretium viverra suspendisse potenti. Urna duis convallis convallis tellus id interdum velit laoreet. Urna condimentum mattis pellentesque id nibh tortor. Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. Ut placerat orci nulla pellentesque. Vestibulum lorem sed risus ultricies tristique. Posuere urna nec tincidunt praesent. Nibh mauris cursus mattis molestie. Posuere sollicitudin aliquam ultrices sagittis orci a. Nunc mattis enim ut tellus elementum sagittis. Luctus venenatis lectus magna fringilla urna porttitor. - -Fermentum dui faucibus in ornare quam viverra orci sagittis eu. Faucibus pulvinar elementum integer enim. Scelerisque fermentum dui faucibus in ornare quam viverra orci sagittis. Tristique senectus et netus et malesuada fames ac turpis egestas. Urna id volutpat lacus laoreet non curabitur gravida. Sed turpis tincidunt id aliquet risus feugiat in. Egestas purus viverra accumsan in nisl nisi scelerisque eu ultrices. Sed euismod nisi porta lorem mollis. Massa sed elementum tempus egestas sed sed. Mi tempus imperdiet nulla malesuada pellentesque elit eget gravida cum. Tortor dignissim convallis aenean et. Et malesuada fames ac turpis egestas. Purus sit amet luctus venenatis. Nunc consequat interdum varius sit amet mattis vulputate enim. Mattis molestie a iaculis at. At auctor urna nunc id cursus metus aliquam eleifend mi. Ut etiam sit amet nisl purus in mollis nunc sed. Diam vulputate ut pharetra sit amet. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque elit. - -Elit eget gravida cum sociis. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Ipsum a arcu cursus vitae congue mauris rhoncus. In nibh mauris cursus mattis molestie. Commodo sed egestas egestas fringilla phasellus faucibus. Porttitor lacus luctus accumsan tortor posuere ac ut. Imperdiet proin fermentum leo vel orci porta non. Gravida dictum fusce ut placerat orci. Consequat id porta nibh venenatis cras sed felis eget. Ultrices dui sapien eget mi proin sed libero. - -Lacus vestibulum sed arcu non odio. Dictum varius duis at consectetur lorem. Lobortis mattis aliquam faucibus purus in. Tristique senectus et netus et malesuada fames ac. Turpis massa tincidunt dui ut ornare lectus sit amet. Semper viverra nam libero justo laoreet sit. Sit amet aliquam id diam maecenas ultricies mi. Lacinia quis vel eros donec. Orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Neque egestas congue quisque egestas diam in arcu cursus. Aliquam nulla facilisi cras fermentum odio. Urna neque viverra justo nec. Elementum curabitur vitae nunc sed velit dignissim sodales ut. Enim ut tellus elementum sagittis vitae et leo duis. Eget mauris pharetra et ultrices neque. Nullam ac tortor vitae purus faucibus ornare suspendisse. A pellentesque sit amet porttitor eget. Neque volutpat ac tincidunt vitae semper quis lectus nulla. Faucibus vitae aliquet nec ullamcorper. - -Dis parturient montes nascetur ridiculus mus. Leo in vitae turpis massa sed elementum tempus egestas sed. Accumsan lacus vel facilisis volutpat est velit. Lectus quam id leo in vitae turpis massa. Turpis massa tincidunt dui ut. Pellentesque habitant morbi tristique senectus et netus et malesuada. Aliquam ut porttitor leo a diam sollicitudin tempor id. Ullamcorper malesuada proin libero nunc. Purus gravida quis blandit turpis. Maecenas accumsan lacus vel facilisis volutpat est velit egestas dui. Odio eu feugiat pretium nibh. Molestie a iaculis at erat. Id faucibus nisl tincidunt eget nullam non nisi est. Dui ut ornare lectus sit amet est placerat. Pellentesque elit eget gravida cum sociis natoque penatibus. Ut sem nulla pharetra diam sit amet. - -Sed sed risus pretium quam vulputate dignissim. Lorem dolor sed viverra ipsum nunc aliquet bibendum. Non enim praesent elementum facilisis leo vel fringilla est. Duis convallis convallis tellus id interdum. Orci a scelerisque purus semper eget duis at tellus at. Tincidunt arcu non sodales neque sodales ut etiam sit. Mauris ultrices eros in cursus turpis massa. Neque viverra justo nec ultrices dui sapien eget. Leo in vitae turpis massa. Proin fermentum leo vel orci porta non pulvinar. Donec ultrices tincidunt arcu non sodales neque. Et tortor at risus viverra. Rutrum tellus pellentesque eu tincidunt tortor. Etiam non quam lacus suspendisse. Tellus at urna condimentum mattis pellentesque id nibh. Arcu cursus euismod quis viverra nibh cras. Pellentesque habitant morbi tristique senectus et netus et. Quam quisque id diam vel quam. - -Mi ipsum faucibus vitae aliquet nec. Hendrerit dolor magna eget est lorem ipsum. Nisi vitae suscipit tellus mauris a diam maecenas sed. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Congue quisque egestas diam in arcu cursus. Dolor sit amet consectetur adipiscing elit. Quam quisque id diam vel quam elementum pulvinar. Pulvinar mattis nunc sed blandit libero volutpat sed cras ornare. Cursus euismod quis viverra nibh cras pulvinar. Turpis nunc eget lorem dolor sed viverra ipsum. Integer feugiat scelerisque varius morbi enim nunc. Egestas sed sed risus pretium. Tellus in hac habitasse platea dictumst vestibulum. Eget mauris pharetra et ultrices neque ornare aenean euismod elementum. - -Ac tincidunt vitae semper quis lectus nulla at volutpat. Arcu cursus euismod quis viverra nibh cras pulvinar mattis nunc. Risus sed vulputate odio ut enim blandit volutpat. Nisi scelerisque eu ultrices vitae auctor eu augue. Ultrices vitae auctor eu augue ut lectus. Nec feugiat in fermentum posuere urna. Euismod quis viverra nibh cras pulvinar mattis nunc sed blandit. Odio tempor orci dapibus ultrices in iaculis nunc sed augue. Proin libero nunc consequat interdum varius sit. Sed velit dignissim sodales ut eu sem integer vitae justo. Leo vel fringilla est ullamcorper eget nulla facilisi etiam. Enim nec dui nunc mattis. Duis tristique sollicitudin nibh sit amet commodo nulla. Vitae elementum curabitur vitae nunc sed velit. Lacus luctus accumsan tortor posuere ac ut. Nunc faucibus a pellentesque sit amet porttitor eget dolor morbi. Nibh nisl condimentum id venenatis. - -Volutpat diam ut venenatis tellus in metus vulputate. Ornare aenean euismod elementum nisi. Diam donec adipiscing tristique risus nec feugiat in fermentum. Sodales ut etiam sit amet nisl purus in mollis nunc. Semper viverra nam libero justo laoreet sit amet. Aliquet bibendum enim facilisis gravida neque convallis a cras. Adipiscing diam donec adipiscing tristique risus nec feugiat in. Aenean euismod elementum nisi quis eleifend quam adipiscing vitae proin. Eget magna fermentum iaculis eu. Pellentesque habitant morbi tristique senectus et netus et. Senectus et netus et malesuada fames ac. Nulla facilisi morbi tempus iaculis urna id volutpat. Id faucibus nisl tincidunt eget. Faucibus a pellentesque sit amet porttitor eget dolor. Integer malesuada nunc vel risus commodo viverra. Dolor sit amet consectetur adipiscing elit duis. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Vestibulum mattis ullamcorper velit sed ullamcorper. Luctus venenatis lectus magna fringilla urna porttitor rhoncus dolor. - -Blandit massa enim nec dui. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Velit euismod in pellentesque massa placerat. Vitae proin sagittis nisl rhoncus. Quam lacus suspendisse faucibus interdum posuere. Aliquam sem et tortor consequat. Mi bibendum neque egestas congue quisque egestas diam. Dui vivamus arcu felis bibendum ut tristique. Urna condimentum mattis pellentesque id. Quisque id diam vel quam elementum pulvinar. Et netus et malesuada fames ac turpis egestas maecenas. Bibendum est ultricies integer quis auctor elit. Fermentum posuere urna nec tincidunt. Adipiscing at in tellus integer feugiat. Tincidunt nunc pulvinar sapien et ligula ullamcorper malesuada proin. Erat imperdiet sed euismod nisi porta lorem. Felis eget velit aliquet sagittis id. Placerat duis ultricies lacus sed. - -Sed risus pretium quam vulputate dignissim. Amet tellus cras adipiscing enim eu turpis egestas. Sem viverra aliquet eget sit amet tellus cras. Faucibus in ornare quam viverra orci sagittis. Odio facilisis mauris sit amet massa. Massa eget egestas purus viverra accumsan. Eu mi bibendum neque egestas congue quisque. Malesuada nunc vel risus commodo viverra maecenas accumsan lacus. Enim facilisis gravida neque convallis a cras semper auctor neque. At elementum eu facilisis sed odio morbi. - -Aliquam nulla facilisi cras fermentum odio. Enim eu turpis egestas pretium aenean pharetra magna ac. Aliquam vestibulum morbi blandit cursus risus at ultrices mi tempus. Consectetur adipiscing elit duis tristique sollicitudin nibh sit amet commodo. Volutpat commodo sed egestas egestas fringilla phasellus. Risus nullam eget felis eget nunc. Scelerisque in dictum non consectetur a. Lorem ipsum dolor sit amet consectetur adipiscing elit ut. Libero enim sed faucibus turpis in. Laoreet non curabitur gravida arcu ac tortor dignissim. Blandit volutpat maecenas volutpat blandit aliquam etiam erat. Lorem dolor sed viverra ipsum nunc. Nibh sit amet commodo nulla facilisi nullam vehicula. Maecenas accumsan lacus vel facilisis volutpat est. Tortor at auctor urna nunc id cursus metus aliquam eleifend. Euismod quis viverra nibh cras pulvinar mattis. Praesent semper feugiat nibh sed pulvinar proin gravida. Magna ac placerat vestibulum lectus mauris ultrices. Eget felis eget nunc lobortis mattis aliquam faucibus. - -Id velit ut tortor pretium viverra suspendisse potenti nullam ac. Suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Leo in vitae turpis massa sed. Egestas purus viverra accumsan in nisl nisi. Nisl purus in mollis nunc sed id semper. Lorem dolor sed viverra ipsum nunc. Quis hendrerit dolor magna eget est lorem ipsum dolor. Est ultricies integer quis auctor elit sed vulputate mi. Varius morbi enim nunc faucibus. Feugiat in ante metus dictum at tempor commodo. Eget nunc lobortis mattis aliquam faucibus purus in. Iaculis nunc sed augue lacus viverra vitae congue eu. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Eu nisl nunc mi ipsum faucibus vitae aliquet nec ullamcorper. In hendrerit gravida rutrum quisque. - -Fringilla ut morbi tincidunt augue interdum velit euismod. Maecenas accumsan lacus vel facilisis. Diam donec adipiscing tristique risus nec feugiat in. Quis lectus nulla at volutpat diam ut venenatis tellus in. Quam lacus suspendisse faucibus interdum posuere lorem ipsum. Eget arcu dictum varius duis at consectetur lorem. Diam vulputate ut pharetra sit. Risus at ultrices mi tempus. Faucibus a pellentesque sit amet porttitor eget dolor morbi non. Gravida quis blandit turpis cursus. Eget dolor morbi non arcu risus. Non sodales neque sodales ut etiam sit. Urna condimentum mattis pellentesque id nibh. Semper eget duis at tellus at urna. Dis parturient montes nascetur ridiculus mus mauris. Vel pharetra vel turpis nunc. Senectus et netus et malesuada fames. Morbi tristique senectus et netus et malesuada. - -Ornare arcu odio ut sem nulla. Justo laoreet sit amet cursus sit. Lorem ipsum dolor sit amet consectetur adipiscing elit ut aliquam. Non diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Nulla at volutpat diam ut venenatis tellus in metus vulputate. Gravida cum sociis natoque penatibus et magnis dis parturient montes. Nunc mattis enim ut tellus. Nulla malesuada pellentesque elit eget gravida cum sociis. Massa enim nec dui nunc mattis enim ut tellus elementum. Nec dui nunc mattis enim ut. Neque ornare aenean euismod elementum nisi quis eleifend. Tortor condimentum lacinia quis vel eros. Posuere ac ut consequat semper viverra. Scelerisque eleifend donec pretium vulputate. Sit amet consectetur adipiscing elit ut aliquam. Felis eget nunc lobortis mattis aliquam. Proin sed libero enim sed faucibus turpis. Ultrices gravida dictum fusce ut. - -Dictum non consectetur a erat. At auctor urna nunc id cursus metus aliquam eleifend mi. Nisi lacus sed viverra tellus in hac habitasse. Donec enim diam vulputate ut. Erat imperdiet sed euismod nisi. Faucibus interdum posuere lorem ipsum dolor sit amet. Amet purus gravida quis blandit turpis cursus in hac habitasse. Massa tincidunt dui ut ornare lectus. Duis ultricies lacus sed turpis tincidunt id. Volutpat odio facilisis mauris sit amet massa vitae tortor. - -At quis risus sed vulputate odio ut enim. Neque laoreet suspendisse interdum consectetur libero. Et netus et malesuada fames ac turpis. Gravida neque convallis a cras semper auctor neque. Vulputate ut pharetra sit amet aliquam id. Nisl suscipit adipiscing bibendum est ultricies integer quis auctor elit. Luctus venenatis lectus magna fringilla. Dui accumsan sit amet nulla. Sed risus ultricies tristique nulla aliquet enim. Neque gravida in fermentum et sollicitudin ac orci. Ipsum dolor sit amet consectetur adipiscing elit duis. - -At ultrices mi tempus imperdiet nulla malesuada pellentesque elit eget. Velit scelerisque in dictum non consectetur a. Elit duis tristique sollicitudin nibh sit amet. Et netus et malesuada fames ac turpis egestas integer eget. Ullamcorper malesuada proin libero nunc. Magna fringilla urna porttitor rhoncus dolor purus. Massa ultricies mi quis hendrerit dolor magna eget. Quis varius quam quisque id diam vel quam elementum pulvinar. Faucibus pulvinar elementum integer enim neque. Sed enim ut sem viverra aliquet eget sit. Elementum tempus egestas sed sed. Mattis rhoncus urna neque viverra justo nec ultrices dui sapien. Purus viverra accumsan in nisl nisi scelerisque eu ultrices. Quis vel eros donec ac. Morbi tristique senectus et netus et malesuada. Ut porttitor leo a diam. Sed enim ut sem viverra aliquet eget sit. - -Odio euismod lacinia at quis risus sed. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Pellentesque nec nam aliquam sem et tortor consequat id porta. Sit amet nulla facilisi morbi. Faucibus turpis in eu mi bibendum neque egestas congue quisque. Praesent semper feugiat nibh sed pulvinar proin gravida hendrerit. Sagittis id consectetur purus ut. Ut lectus arcu bibendum at. Eget nullam non nisi est sit amet facilisis magna. Commodo viverra maecenas accumsan lacus vel facilisis volutpat est velit. Et leo duis ut diam quam nulla porttitor massa id. Odio ut sem nulla pharetra diam sit amet. Neque convallis a cras semper. Diam vulputate ut pharetra sit amet aliquam id diam maecenas. Ac turpis egestas integer eget aliquet. Nulla aliquet porttitor lacus luctus accumsan tortor posuere ac. Id faucibus nisl tincidunt eget nullam non nisi. Nec ullamcorper sit amet risus nullam eget felis eget nunc. - -Et ultrices neque ornare aenean euismod elementum nisi quis eleifend. Adipiscing commodo elit at imperdiet dui accumsan sit. Parturient montes nascetur ridiculus mus mauris vitae ultricies. Ut tristique et egestas quis ipsum suspendisse ultrices gravida dictum. Viverra justo nec ultrices dui sapien eget mi proin. Lectus mauris ultrices eros in cursus turpis massa. Posuere morbi leo urna molestie at elementum eu facilisis. Aliquam ut porttitor leo a diam sollicitudin. Pharetra diam sit amet nisl suscipit adipiscing bibendum. Rutrum tellus pellentesque eu tincidunt tortor aliquam nulla. Rhoncus mattis rhoncus urna neque viverra. Leo vel orci porta non pulvinar neque laoreet. Eget lorem dolor sed viverra. Egestas tellus rutrum tellus pellentesque eu tincidunt. Viverra accumsan in nisl nisi scelerisque eu. Neque convallis a cras semper auctor neque vitae tempus quam. Amet mattis vulputate enim nulla aliquet. - -Eget mauris pharetra et ultrices neque ornare aenean euismod. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Eu facilisis sed odio morbi quis commodo odio aenean. Mattis molestie a iaculis at erat pellentesque adipiscing. Lectus nulla at volutpat diam ut venenatis tellus. Amet volutpat consequat mauris nunc congue nisi vitae suscipit tellus. At consectetur lorem donec massa sapien. Et egestas quis ipsum suspendisse. Donec ac odio tempor orci dapibus ultrices in iaculis. Laoreet non curabitur gravida arcu ac tortor. Vitae ultricies leo integer malesuada. Egestas integer eget aliquet nibh praesent tristique magna. Egestas sed tempus urna et pharetra pharetra massa massa ultricies. Elementum integer enim neque volutpat ac tincidunt. Morbi tristique senectus et netus. Iaculis nunc sed augue lacus viverra. Nulla pellentesque dignissim enim sit amet venenatis urna cursus. Magna fermentum iaculis eu non diam phasellus vestibulum lorem. Id ornare arcu odio ut sem nulla pharetra. - -Molestie a iaculis at erat pellentesque adipiscing commodo elit. Facilisis gravida neque convallis a. Nisi scelerisque eu ultrices vitae auctor eu augue. Sed viverra tellus in hac habitasse platea dictumst vestibulum. Commodo nulla facilisi nullam vehicula ipsum a arcu cursus vitae. Nullam vehicula ipsum a arcu cursus vitae. In metus vulputate eu scelerisque. Odio facilisis mauris sit amet massa vitae tortor condimentum lacinia. Neque volutpat ac tincidunt vitae. In eu mi bibendum neque. Turpis egestas maecenas pharetra convallis. Senectus et netus et malesuada. Dignissim convallis aenean et tortor at risus viverra. Leo urna molestie at elementum eu facilisis sed odio morbi. In fermentum posuere urna nec tincidunt praesent semper feugiat nibh. Dignissim enim sit amet venenatis urna cursus eget. Faucibus interdum posuere lorem ipsum dolor sit amet consectetur. Massa massa ultricies mi quis hendrerit dolor magna. - -Sit amet dictum sit amet justo. Eu ultrices vitae auctor eu augue ut lectus arcu bibendum. Sodales neque sodales ut etiam sit amet. In egestas erat imperdiet sed. Pharetra vel turpis nunc eget lorem dolor sed. Praesent semper feugiat nibh sed pulvinar. At tempor commodo ullamcorper a lacus vestibulum. Eu scelerisque felis imperdiet proin fermentum leo vel. Massa massa ultricies mi quis hendrerit dolor magna eget. Nibh venenatis cras sed felis eget. Vitae sapien pellentesque habitant morbi. Urna nunc id cursus metus. Morbi leo urna molestie at elementum eu facilisis. Duis at tellus at urna condimentum mattis pellentesque. Convallis a cras semper auctor neque. Ante metus dictum at tempor commodo ullamcorper a lacus. In tellus integer feugiat scelerisque varius. Suspendisse sed nisi lacus sed. Arcu dui vivamus arcu felis bibendum ut tristique. Quisque non tellus orci ac auctor augue mauris augue neque. - -Pellentesque dignissim enim sit amet venenatis urna cursus. Est ultricies integer quis auctor elit sed vulputate. Et netus et malesuada fames ac turpis egestas. Tortor vitae purus faucibus ornare suspendisse sed nisi lacus. Diam maecenas sed enim ut sem viverra aliquet eget sit. Sit amet mattis vulputate enim nulla. Morbi tristique senectus et netus et. Et leo duis ut diam. Elit ullamcorper dignissim cras tincidunt lobortis. Enim ut sem viverra aliquet eget sit. Dignissim convallis aenean et tortor at risus viverra adipiscing. - -Vel pretium lectus quam id. Mauris rhoncus aenean vel elit. Viverra tellus in hac habitasse platea dictumst. Diam volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. A scelerisque purus semper eget duis at tellus at. Turpis egestas maecenas pharetra convallis posuere morbi leo urna molestie. Massa placerat duis ultricies lacus sed turpis tincidunt. Neque aliquam vestibulum morbi blandit cursus. Diam quis enim lobortis scelerisque. Aliquam ultrices sagittis orci a scelerisque. Amet venenatis urna cursus eget nunc scelerisque viverra. Fermentum odio eu feugiat pretium nibh ipsum consequat nisl. Amet consectetur adipiscing elit pellentesque habitant morbi. Purus sit amet luctus venenatis lectus magna fringilla urna. Tincidunt eget nullam non nisi. - -Faucibus interdum posuere lorem ipsum. Non tellus orci ac auctor augue mauris. Elit sed vulputate mi sit. Laoreet id donec ultrices tincidunt. Elementum integer enim neque volutpat ac. Facilisi cras fermentum odio eu feugiat pretium nibh. Orci porta non pulvinar neque laoreet. Dignissim diam quis enim lobortis. Dignissim diam quis enim lobortis scelerisque fermentum dui. Iaculis urna id volutpat lacus laoreet non curabitur gravida. Placerat vestibulum lectus mauris ultrices eros in. Facilisis leo vel fringilla est. Accumsan lacus vel facilisis volutpat est velit egestas dui. Elit pellentesque habitant morbi tristique senectus et netus et malesuada. - -Auctor elit sed vulputate mi sit amet. Ut faucibus pulvinar elementum integer enim neque. Risus feugiat in ante metus dictum at tempor. Ultricies mi eget mauris pharetra. A diam maecenas sed enim. Augue mauris augue neque gravida in. Leo a diam sollicitudin tempor id. Imperdiet sed euismod nisi porta lorem mollis aliquam. Ornare lectus sit amet est placerat. Lacus suspendisse faucibus interdum posuere lorem ipsum dolor sit amet. Et odio pellentesque diam volutpat. Feugiat vivamus at augue eget arcu dictum varius. Eros in cursus turpis massa tincidunt. Sed odio morbi quis commodo odio aenean sed. Id neque aliquam vestibulum morbi. Convallis posuere morbi leo urna molestie. Rhoncus urna neque viverra justo. Duis ut diam quam nulla porttitor massa id neque. Ac turpis egestas sed tempus urna et pharetra pharetra massa. Commodo odio aenean sed adipiscing. - -Fringilla est ullamcorper eget nulla facilisi etiam. Placerat duis ultricies lacus sed turpis tincidunt id aliquet. Semper viverra nam libero justo laoreet sit. Leo vel fringilla est ullamcorper eget nulla. Diam ut venenatis tellus in metus vulputate. Venenatis a condimentum vitae sapien pellentesque. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar. Vel facilisis volutpat est velit. Vulputate odio ut enim blandit volutpat maecenas volutpat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames. Semper eget duis at tellus at urna condimentum mattis pellentesque. Et molestie ac feugiat sed lectus vestibulum. Magna etiam tempor orci eu lobortis elementum nibh tellus. - -In dictum non consectetur a. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Tortor dignissim convallis aenean et tortor. Mauris in aliquam sem fringilla ut morbi. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant morbi. Placerat vestibulum lectus mauris ultrices. Dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Vitae semper quis lectus nulla at volutpat. Tellus elementum sagittis vitae et leo duis ut diam. Integer malesuada nunc vel risus. Ut placerat orci nulla pellentesque dignissim enim sit amet venenatis. Faucibus et molestie ac feugiat sed lectus vestibulum mattis ullamcorper. - -Turpis massa tincidunt dui ut ornare. Nisi scelerisque eu ultrices vitae auctor eu augue ut lectus. Massa tempor nec feugiat nisl pretium fusce. Nisi est sit amet facilisis magna etiam tempor. Scelerisque varius morbi enim nunc faucibus a pellentesque. In fermentum posuere urna nec tincidunt praesent semper feugiat. Tristique magna sit amet purus gravida quis blandit. Vulputate odio ut enim blandit volutpat maecenas volutpat. Vulputate odio ut enim blandit volutpat maecenas volutpat blandit aliquam. Lacus sed viverra tellus in hac habitasse platea dictumst vestibulum. Elementum pulvinar etiam non quam lacus suspendisse. At auctor urna nunc id. Eleifend quam adipiscing vitae proin sagittis nisl rhoncus. Et odio pellentesque diam volutpat commodo sed egestas. Blandit cursus risus at ultrices mi tempus. Integer quis auctor elit sed vulputate mi sit amet mauris. Blandit aliquam etiam erat velit scelerisque in. Malesuada fames ac turpis egestas integer eget aliquet nibh. - -A scelerisque purus semper eget duis at. Parturient montes nascetur ridiculus mus. Elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi. Potenti nullam ac tortor vitae purus faucibus ornare. Eget felis eget nunc lobortis mattis aliquam faucibus purus. Amet mauris commodo quis imperdiet massa. Scelerisque varius morbi enim nunc faucibus a pellentesque. Pellentesque nec nam aliquam sem et tortor consequat id. Habitasse platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper. Mollis nunc sed id semper risus in hendrerit. Eget mauris pharetra et ultrices neque ornare aenean euismod. Iaculis nunc sed augue lacus viverra vitae congue eu. Cursus turpis massa tincidunt dui ut ornare lectus. Netus et malesuada fames ac turpis egestas integer. Massa placerat duis ultricies lacus sed turpis tincidunt id aliquet. Elementum curabitur vitae nunc sed velit dignissim sodales ut. Viverra aliquet eget sit amet. Dictum non consectetur a erat nam at lectus. Laoreet non curabitur gravida arcu ac. Iaculis urna id volutpat lacus laoreet non. - -Sit amet est placerat in egestas erat imperdiet. Tortor consequat id porta nibh. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus. Sit amet cursus sit amet dictum sit amet justo. Ultrices vitae auctor eu augue. Magna ac placerat vestibulum lectus mauris ultrices eros in cursus. Fringilla ut morbi tincidunt augue interdum velit euismod in pellentesque. Tempor orci eu lobortis elementum nibh tellus. Neque ornare aenean euismod elementum nisi quis eleifend quam. Et netus et malesuada fames ac turpis egestas maecenas pharetra. Malesuada bibendum arcu vitae elementum curabitur vitae. Tincidunt dui ut ornare lectus. - -Consequat ac felis donec et odio pellentesque diam volutpat commodo. In nulla posuere sollicitudin aliquam ultrices sagittis orci a scelerisque. Nisi quis eleifend quam adipiscing. Sit amet porttitor eget dolor morbi non arcu risus. Sagittis orci a scelerisque purus semper eget duis. Nunc sed augue lacus viverra vitae congue eu consequat. Diam phasellus vestibulum lorem sed risus. Platea dictumst vestibulum rhoncus est pellentesque elit. Vehicula ipsum a arcu cursus vitae congue. Ornare aenean euismod elementum nisi quis eleifend quam adipiscing vitae. In nisl nisi scelerisque eu ultrices vitae auctor eu. Quis varius quam quisque id diam vel quam elementum. Cras adipiscing enim eu turpis egestas. Dictum varius duis at consectetur lorem donec massa sapien. Quis imperdiet massa tincidunt nunc pulvinar sapien et ligula. Tortor at risus viverra adipiscing at in tellus integer. Viverra justo nec ultrices dui sapien eget mi proin. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus quam. Massa placerat duis ultricies lacus sed turpis tincidunt id. Orci a scelerisque purus semper eget duis. - -At volutpat diam ut venenatis tellus in metus vulputate. Faucibus interdum posuere lorem ipsum dolor. Arcu vitae elementum curabitur vitae nunc. Tortor dignissim convallis aenean et tortor at. Orci dapibus ultrices in iaculis nunc sed augue lacus. Facilisis gravida neque convallis a cras semper. Felis eget velit aliquet sagittis id consectetur purus ut faucibus. Arcu risus quis varius quam quisque id diam. Diam sit amet nisl suscipit adipiscing bibendum est ultricies. Etiam dignissim diam quis enim. At in tellus integer feugiat scelerisque varius morbi enim nunc. Egestas pretium aenean pharetra magna ac. Aliquet lectus proin nibh nisl condimentum id venenatis a condimentum. Massa vitae tortor condimentum lacinia quis. Malesuada fames ac turpis egestas sed. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Quis risus sed vulputate odio ut enim. Blandit turpis cursus in hac habitasse platea dictumst quisque. - -Ut sem nulla pharetra diam sit. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit. A diam sollicitudin tempor id eu. Lectus proin nibh nisl condimentum id. In ornare quam viverra orci sagittis eu. Lobortis elementum nibh tellus molestie nunc non blandit massa enim. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Pretium fusce id velit ut tortor pretium viverra. Sed adipiscing diam donec adipiscing tristique risus. Parturient montes nascetur ridiculus mus. Duis tristique sollicitudin nibh sit amet commodo. Mi sit amet mauris commodo quis. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend. Purus gravida quis blandit turpis cursus. Consectetur purus ut faucibus pulvinar elementum. - -Velit aliquet sagittis id consectetur purus ut. Dignissim suspendisse in est ante in nibh mauris. Sollicitudin ac orci phasellus egestas tellus. Tristique risus nec feugiat in fermentum posuere urna nec tincidunt. Facilisi nullam vehicula ipsum a arcu cursus vitae. Porttitor massa id neque aliquam vestibulum morbi blandit cursus risus. Mollis aliquam ut porttitor leo a diam sollicitudin tempor. Viverra aliquet eget sit amet tellus. Eu scelerisque felis imperdiet proin fermentum. Ornare arcu dui vivamus arcu felis bibendum ut. Donec adipiscing tristique risus nec feugiat. Vestibulum morbi blandit cursus risus at. Pellentesque massa placerat duis ultricies. Elementum nibh tellus molestie nunc non blandit. - -Elit at imperdiet dui accumsan sit amet. Morbi tristique senectus et netus et malesuada fames ac turpis. Faucibus in ornare quam viverra. Quis risus sed vulputate odio ut enim blandit volutpat maecenas. Non odio euismod lacinia at quis. Enim ut tellus elementum sagittis vitae. Elit ut aliquam purus sit amet luctus venenatis lectus. Vestibulum morbi blandit cursus risus. Tellus cras adipiscing enim eu turpis egestas pretium aenean. Tortor condimentum lacinia quis vel eros donec ac. Arcu vitae elementum curabitur vitae nunc sed velit. Massa vitae tortor condimentum lacinia. In nisl nisi scelerisque eu ultrices vitae auctor eu. - -Condimentum lacinia quis vel eros donec ac odio. Semper quis lectus nulla at volutpat. Parturient montes nascetur ridiculus mus mauris vitae. Nibh praesent tristique magna sit amet purus. Et pharetra pharetra massa massa ultricies mi. Egestas sed tempus urna et pharetra pharetra massa massa. Lorem mollis aliquam ut porttitor. Aliquam ultrices sagittis orci a. Consequat ac felis donec et. Elementum facilisis leo vel fringilla est. Mauris nunc congue nisi vitae suscipit tellus mauris a diam. Ac turpis egestas sed tempus. Ultricies leo integer malesuada nunc. Amet cursus sit amet dictum sit amet justo donec enim. Egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. At tellus at urna condimentum mattis pellentesque id nibh. Vitae turpis massa sed elementum. Dictumst quisque sagittis purus sit amet. Morbi leo urna molestie at elementum. - -Aliquam id diam maecenas ultricies mi eget mauris pharetra et. Tempus imperdiet nulla malesuada pellentesque elit. Augue mauris augue neque gravida in fermentum et. Sed felis eget velit aliquet. Senectus et netus et malesuada fames ac turpis egestas sed. Ante metus dictum at tempor commodo ullamcorper. Rhoncus mattis rhoncus urna neque viverra justo nec ultrices dui. Quam vulputate dignissim suspendisse in est ante. Odio tempor orci dapibus ultrices in iaculis. Semper eget duis at tellus at urna. Malesuada fames ac turpis egestas maecenas pharetra. Tellus id interdum velit laoreet id donec. Non arcu risus quis varius quam quisque id. Adipiscing enim eu turpis egestas pretium. Vitae auctor eu augue ut lectus arcu bibendum. Risus sed vulputate odio ut enim blandit volutpat. - -Sit amet est placerat in. Elementum nisi quis eleifend quam adipiscing. Eget nulla facilisi etiam dignissim diam quis. Lacus luctus accumsan tortor posuere ac ut consequat. Dui ut ornare lectus sit amet est placerat. Hac habitasse platea dictumst vestibulum rhoncus est pellentesque elit. Enim facilisis gravida neque convallis a cras semper auctor. Sed enim ut sem viverra aliquet eget. Rutrum tellus pellentesque eu tincidunt tortor aliquam nulla facilisi. Elit duis tristique sollicitudin nibh sit amet commodo nulla facilisi. Sagittis purus sit amet volutpat consequat mauris nunc congue. Pharetra et ultrices neque ornare aenean. Faucibus pulvinar elementum integer enim neque volutpat. Odio ut sem nulla pharetra diam sit amet. Orci ac auctor augue mauris augue neque gravida in. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Lacus vel facilisis volutpat est velit egestas dui id ornare. Auctor urna nunc id cursus metus. Quam quisque id diam vel quam elementum pulvinar etiam non. Pellentesque diam volutpat commodo sed egestas egestas. - -Arcu bibendum at varius vel pharetra vel. Morbi enim nunc faucibus a pellentesque sit amet porttitor. Commodo viverra maecenas accumsan lacus vel facilisis. Porttitor leo a diam sollicitudin tempor id. Odio ut enim blandit volutpat maecenas volutpat blandit. Sem integer vitae justo eget magna fermentum iaculis eu. Platea dictumst quisque sagittis purus sit amet volutpat. Varius morbi enim nunc faucibus. Egestas congue quisque egestas diam in arcu cursus. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit. Elit pellentesque habitant morbi tristique senectus et netus et malesuada. Sollicitudin aliquam ultrices sagittis orci a scelerisque. Vulputate odio ut enim blandit volutpat. Mauris sit amet massa vitae tortor condimentum lacinia quis. Nisi quis eleifend quam adipiscing vitae proin sagittis nisl. - -Porttitor massa id neque aliquam vestibulum morbi blandit cursus. Libero nunc consequat interdum varius sit. Duis ut diam quam nulla. Mi proin sed libero enim sed faucibus turpis in. Massa sapien faucibus et molestie ac feugiat sed. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Mi tempus imperdiet nulla malesuada pellentesque elit eget. Proin sagittis nisl rhoncus mattis rhoncus urna neque viverra. Dictum varius duis at consectetur lorem donec massa sapien. Proin libero nunc consequat interdum varius sit amet. Neque sodales ut etiam sit amet nisl purus in mollis. Libero volutpat sed cras ornare arcu. Massa placerat duis ultricies lacus sed. Dui nunc mattis enim ut tellus elementum sagittis vitae et. Massa vitae tortor condimentum lacinia. Nullam ac tortor vitae purus faucibus ornare suspendisse sed nisi. Tristique et egestas quis ipsum. - -Montes nascetur ridiculus mus mauris vitae ultricies leo integer malesuada. At elementum eu facilisis sed odio morbi quis. Neque ornare aenean euismod elementum nisi. Amet est placerat in egestas erat imperdiet sed. Ut sem viverra aliquet eget. Tortor condimentum lacinia quis vel eros donec ac. Nunc eget lorem dolor sed viverra ipsum. Non quam lacus suspendisse faucibus interdum. Malesuada proin libero nunc consequat interdum. Elementum tempus egestas sed sed risus pretium quam vulputate dignissim. Tristique magna sit amet purus gravida. Duis at tellus at urna condimentum mattis. Lectus urna duis convallis convallis tellus id interdum velit laoreet. Tempus quam pellentesque nec nam aliquam sem. Placerat vestibulum lectus mauris ultrices eros in cursus turpis. Id semper risus in hendrerit gravida rutrum quisque non. Odio morbi quis commodo odio aenean. Diam quis enim lobortis scelerisque fermentum dui faucibus in ornare. Augue eget arcu dictum varius. - -Ut etiam sit amet nisl purus in mollis nunc sed. Porttitor leo a diam sollicitudin tempor id eu. Imperdiet dui accumsan sit amet nulla facilisi morbi tempus. Urna nunc id cursus metus aliquam eleifend mi. Interdum velit laoreet id donec ultrices tincidunt arcu. Neque aliquam vestibulum morbi blandit cursus risus at. Cursus metus aliquam eleifend mi in. Fermentum odio eu feugiat pretium nibh ipsum. Dapibus ultrices in iaculis nunc sed augue lacus viverra vitae. Est ullamcorper eget nulla facilisi etiam dignissim diam. Felis eget nunc lobortis mattis aliquam faucibus purus in massa. Praesent semper feugiat nibh sed pulvinar. Amet mauris commodo quis imperdiet massa. Vel pharetra vel turpis nunc eget lorem dolor. Cursus euismod quis viverra nibh cras. Tincidunt ornare massa eget egestas purus viverra accumsan in. - -Purus non enim praesent elementum facilisis leo vel. Ipsum dolor sit amet consectetur. Sagittis eu volutpat odio facilisis mauris sit amet massa. In arcu cursus euismod quis viverra nibh cras pulvinar mattis. Et netus et malesuada fames ac turpis egestas sed tempus. Ac felis donec et odio pellentesque diam volutpat commodo sed. In metus vulputate eu scelerisque felis imperdiet proin fermentum leo. Sit amet risus nullam eget felis eget. Etiam dignissim diam quis enim lobortis scelerisque. Ipsum faucibus vitae aliquet nec ullamcorper. Ac placerat vestibulum lectus mauris ultrices eros. In iaculis nunc sed augue lacus viverra. Ut morbi tincidunt augue interdum velit euismod in pellentesque massa. Adipiscing elit pellentesque habitant morbi tristique senectus. Felis donec et odio pellentesque diam. Non enim praesent elementum facilisis. Arcu ac tortor dignissim convallis. Etiam tempor orci eu lobortis elementum nibh tellus molestie nunc. Netus et malesuada fames ac. Urna nunc id cursus metus aliquam eleifend mi in nulla. - -Morbi tempus iaculis urna id volutpat lacus. Ac ut consequat semper viverra. Aliquam id diam maecenas ultricies mi eget. Ornare arcu odio ut sem. At consectetur lorem donec massa sapien faucibus. Massa vitae tortor condimentum lacinia quis vel eros donec ac. Sed viverra ipsum nunc aliquet bibendum. Velit laoreet id donec ultrices tincidunt. Aenean pharetra magna ac placerat vestibulum lectus mauris. Sed felis eget velit aliquet sagittis id consectetur. Ipsum dolor sit amet consectetur adipiscing elit duis tristique. Mattis aliquam faucibus purus in massa tempor nec feugiat nisl. Integer feugiat scelerisque varius morbi enim nunc faucibus a. Quis blandit turpis cursus in hac habitasse. Justo eget magna fermentum iaculis eu non. Facilisis volutpat est velit egestas dui. Cras sed felis eget velit aliquet sagittis id consectetur purus. - -Hendrerit gravida rutrum quisque non tellus orci ac. Aenean pharetra magna ac placerat vestibulum lectus mauris ultrices eros. Sit amet luctus venenatis lectus magna fringilla urna. Ultricies lacus sed turpis tincidunt. Euismod nisi porta lorem mollis aliquam. Quis varius quam quisque id diam vel. Volutpat consequat mauris nunc congue nisi vitae. Luctus venenatis lectus magna fringilla urna porttitor rhoncus. Dictum varius duis at consectetur lorem donec massa. Congue nisi vitae suscipit tellus mauris a. Turpis cursus in hac habitasse platea dictumst quisque sagittis. - -Ut sem nulla pharetra diam sit amet nisl suscipit. A cras semper auctor neque vitae tempus quam pellentesque. Ut ornare lectus sit amet est placerat. Vulputate mi sit amet mauris. Lacus vel facilisis volutpat est velit egestas dui id ornare. Facilisi etiam dignissim diam quis. Proin sed libero enim sed faucibus turpis in eu. Sed euismod nisi porta lorem mollis aliquam ut porttitor. Senectus et netus et malesuada fames. Adipiscing diam donec adipiscing tristique risus nec feugiat in fermentum. Sagittis eu volutpat odio facilisis mauris sit amet massa. Vitae auctor eu augue ut lectus. Pharetra magna ac placerat vestibulum lectus mauris ultrices eros in. Accumsan lacus vel facilisis volutpat est velit egestas dui id. Eu mi bibendum neque egestas congue quisque. Nulla facilisi morbi tempus iaculis urna id volutpat lacus laoreet. Etiam tempor orci eu lobortis elementum. Quisque id diam vel quam elementum. - -Donec et odio pellentesque diam. Ullamcorper morbi tincidunt ornare massa eget egestas. Aliquet bibendum enim facilisis gravida neque convallis a cras semper. Habitant morbi tristique senectus et netus et malesuada fames ac. Et leo duis ut diam quam nulla. Sit amet luctus venenatis lectus. Integer enim neque volutpat ac tincidunt vitae. Quam elementum pulvinar etiam non quam. Neque aliquam vestibulum morbi blandit cursus risus at. Tempus egestas sed sed risus pretium quam vulputate. Tortor aliquam nulla facilisi cras. - -Lorem mollis aliquam ut porttitor leo a diam sollicitudin. Eget mauris pharetra et ultrices neque ornare aenean euismod elementum. At ultrices mi tempus imperdiet nulla malesuada pellentesque elit. Nunc non blandit massa enim nec. Velit euismod in pellentesque massa placerat duis ultricies lacus. Massa vitae tortor condimentum lacinia quis vel eros. Vel eros donec ac odio tempor orci dapibus. Accumsan lacus vel facilisis volutpat est velit egestas dui id. Platea dictumst vestibulum rhoncus est pellentesque elit ullamcorper dignissim. Nibh cras pulvinar mattis nunc. Commodo elit at imperdiet dui accumsan sit. Velit scelerisque in dictum non consectetur a erat. - -Gravida cum sociis natoque penatibus et magnis. Sodales neque sodales ut etiam sit amet nisl purus in. Nulla malesuada pellentesque elit eget gravida. In ante metus dictum at. Et ultrices neque ornare aenean euismod elementum nisi. Ornare suspendisse sed nisi lacus sed viverra. Non pulvinar neque laoreet suspendisse interdum consectetur libero id faucibus. Interdum varius sit amet mattis vulputate enim nulla aliquet porttitor. Libero enim sed faucibus turpis. Lorem ipsum dolor sit amet consectetur. Urna molestie at elementum eu facilisis sed odio morbi quis. Urna id volutpat lacus laoreet non curabitur. Massa massa ultricies mi quis hendrerit dolor magna. Eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Porttitor rhoncus dolor purus non enim praesent elementum facilisis. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet dui. Dictum at tempor commodo ullamcorper. Viverra vitae congue eu consequat ac felis donec et odio. Habitant morbi tristique senectus et netus et malesuada fames. - -Odio ut sem nulla pharetra diam sit. Scelerisque eleifend donec pretium vulputate sapien nec. Congue nisi vitae suscipit tellus mauris a diam. Sit amet justo donec enim diam vulputate ut. Tortor aliquam nulla facilisi cras fermentum odio. Venenatis a condimentum vitae sapien pellentesque habitant morbi tristique senectus. Quis commodo odio aenean sed adipiscing diam donec adipiscing. Quam id leo in vitae turpis massa. Amet consectetur adipiscing elit ut aliquam purus sit. Ullamcorper velit sed ullamcorper morbi. Tristique magna sit amet purus gravida quis blandit turpis cursus. Aliquet enim tortor at auctor. Sed vulputate odio ut enim blandit volutpat maecenas. Aliquam ultrices sagittis orci a scelerisque purus semper eget. Felis donec et odio pellentesque diam. Cum sociis natoque penatibus et magnis dis parturient. Parturient montes nascetur ridiculus mus. - -Feugiat vivamus at augue eget arcu dictum. Lorem sed risus ultricies tristique nulla aliquet enim tortor at. Ipsum dolor sit amet consectetur adipiscing elit pellentesque. Adipiscing bibendum est ultricies integer quis. Nibh tortor id aliquet lectus proin nibh nisl condimentum id. Egestas tellus rutrum tellus pellentesque. Facilisi nullam vehicula ipsum a arcu cursus vitae. Mattis molestie a iaculis at erat pellentesque adipiscing commodo elit. Quam pellentesque nec nam aliquam sem et tortor consequat id. Enim ut sem viverra aliquet. Urna condimentum mattis pellentesque id nibh. Neque laoreet suspendisse interdum consectetur libero id faucibus nisl. Vel elit scelerisque mauris pellentesque pulvinar pellentesque habitant morbi tristique. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida neque. Mattis rhoncus urna neque viverra justo nec. Ac feugiat sed lectus vestibulum mattis ullamcorper. A scelerisque purus semper eget duis at tellus at. Diam sollicitudin tempor id eu nisl nunc mi ipsum faucibus. Sed enim ut sem viverra. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant morbi. - -Sed enim ut sem viverra aliquet eget sit amet tellus. Morbi tristique senectus et netus et malesuada fames. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. Felis eget nunc lobortis mattis aliquam faucibus purus in. Risus sed vulputate odio ut enim blandit volutpat maecenas. Mauris augue neque gravida in fermentum et sollicitudin ac. Nec ullamcorper sit amet risus nullam eget felis. Augue neque gravida in fermentum et sollicitudin ac orci phasellus. Porttitor rhoncus dolor purus non enim praesent elementum facilisis leo. In vitae turpis massa sed elementum tempus egestas. In mollis nunc sed id semper risus in. Eu non diam phasellus vestibulum lorem sed. Tincidunt augue interdum velit euismod in pellentesque massa. Et netus et malesuada fames ac. Amet luctus venenatis lectus magna fringilla urna. Vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Cras sed felis eget velit aliquet sagittis id consectetur purus. Venenatis cras sed felis eget velit aliquet sagittis id. Vestibulum lorem sed risus ultricies. - -Lectus nulla at volutpat diam ut venenatis. Eu augue ut lectus arcu bibendum at varius vel pharetra. Aliquet bibendum enim facilisis gravida neque. Vitae congue eu consequat ac felis donec et odio pellentesque. Ac turpis egestas maecenas pharetra convallis posuere morbi. Id semper risus in hendrerit gravida. Facilisi etiam dignissim diam quis. Lorem ipsum dolor sit amet. Fermentum dui faucibus in ornare quam viverra orci. Vestibulum rhoncus est pellentesque elit. Fames ac turpis egestas integer eget aliquet nibh praesent. Molestie at elementum eu facilisis sed. - -Tortor at auctor urna nunc id cursus metus. Non sodales neque sodales ut etiam sit amet nisl purus. Duis tristique sollicitudin nibh sit amet commodo nulla. At volutpat diam ut venenatis tellus in metus vulputate. Amet consectetur adipiscing elit pellentesque habitant morbi. Neque convallis a cras semper auctor. Nisi scelerisque eu ultrices vitae. Eget mauris pharetra et ultrices neque ornare aenean euismod elementum. Eu volutpat odio facilisis mauris sit amet massa vitae tortor. Mattis aliquam faucibus purus in massa tempor. Congue nisi vitae suscipit tellus mauris a. Amet facilisis magna etiam tempor orci eu. Leo duis ut diam quam nulla. - -Habitant morbi tristique senectus et netus et. Quis risus sed vulputate odio. Convallis aenean et tortor at. Vulputate eu scelerisque felis imperdiet proin. At ultrices mi tempus imperdiet nulla. Nisi porta lorem mollis aliquam ut porttitor. Potenti nullam ac tortor vitae purus faucibus. Nunc sed blandit libero volutpat sed. In dictum non consectetur a erat nam at lectus. Tellus pellentesque eu tincidunt tortor. Ac turpis egestas sed tempus urna et pharetra pharetra. Iaculis nunc sed augue lacus viverra vitae. - -Nunc mi ipsum faucibus vitae aliquet nec ullamcorper sit amet. Fusce id velit ut tortor pretium viverra suspendisse potenti nullam. Sit amet nisl suscipit adipiscing bibendum est ultricies integer quis. Nunc congue nisi vitae suscipit. Ultrices tincidunt arcu non sodales. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant morbi. Risus nullam eget felis eget nunc lobortis mattis. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Pellentesque diam volutpat commodo sed egestas egestas fringilla phasellus faucibus. Convallis a cras semper auctor neque vitae tempus quam pellentesque. Sodales ut eu sem integer vitae justo eget magna fermentum. Vel pharetra vel turpis nunc eget lorem dolor sed viverra. Dolor morbi non arcu risus quis varius. Morbi quis commodo odio aenean sed. Amet luctus venenatis lectus magna fringilla urna porttitor. Enim facilisis gravida neque convallis a cras. Dolor magna eget est lorem ipsum dolor sit. - -Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. Id aliquet lectus proin nibh. Lacus sed turpis tincidunt id aliquet risus feugiat. Aenean euismod elementum nisi quis eleifend. Eu augue ut lectus arcu bibendum. Pharetra sit amet aliquam id diam maecenas. Senectus et netus et malesuada fames ac. Massa tincidunt dui ut ornare lectus sit amet. Vehicula ipsum a arcu cursus vitae congue mauris rhoncus aenean. Mi quis hendrerit dolor magna eget est. Varius morbi enim nunc faucibus. Vulputate sapien nec sagittis aliquam malesuada bibendum. Odio eu feugiat pretium nibh ipsum. Sed libero enim sed faucibus turpis in. Et netus et malesuada fames ac turpis egestas. Dolor morbi non arcu risus quis varius quam. Sit amet tellus cras adipiscing enim eu turpis egestas pretium. Dolor sit amet consectetur adipiscing elit. Ac turpis egestas maecenas pharetra. Sed blandit libero volutpat sed cras ornare arcu dui. - -Bibendum est ultricies integer quis auctor elit sed vulputate mi. Neque volutpat ac tincidunt vitae semper. Viverra ipsum nunc aliquet bibendum enim facilisis gravida. Odio euismod lacinia at quis risus sed. Sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Arcu risus quis varius quam. Interdum velit laoreet id donec. Quam lacus suspendisse faucibus interdum posuere lorem ipsum dolor. Enim facilisis gravida neque convallis. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus a. Quam adipiscing vitae proin sagittis nisl rhoncus mattis rhoncus. Turpis in eu mi bibendum neque. - -Lacus sed turpis tincidunt id aliquet risus feugiat. Et malesuada fames ac turpis egestas. Nunc sed id semper risus in. Diam donec adipiscing tristique risus nec. Cursus mattis molestie a iaculis at erat. Elementum eu facilisis sed odio morbi quis commodo odio. Ipsum suspendisse ultrices gravida dictum. Nisi scelerisque eu ultrices vitae auctor eu augue. Commodo elit at imperdiet dui accumsan sit. Pellentesque dignissim enim sit amet venenatis urna cursus eget nunc. Faucibus vitae aliquet nec ullamcorper sit amet risus nullam. Malesuada pellentesque elit eget gravida cum sociis natoque penatibus. Sed arcu non odio euismod lacinia at quis. - -Elementum nisi quis eleifend quam adipiscing vitae. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Ac ut consequat semper viverra nam. Sed adipiscing diam donec adipiscing tristique risus nec. Suspendisse sed nisi lacus sed viverra tellus in hac habitasse. Sed lectus vestibulum mattis ullamcorper. Non quam lacus suspendisse faucibus interdum posuere lorem ipsum dolor. Donec pretium vulputate sapien nec sagittis. Sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor. - -Blandit libero volutpat sed cras ornare arcu dui. Massa massa ultricies mi quis hendrerit dolor. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam. Massa massa ultricies mi quis hendrerit dolor magna. Porttitor leo a diam sollicitudin. Nunc mattis enim ut tellus elementum sagittis. Massa massa ultricies mi quis hendrerit dolor magna. Urna porttitor rhoncus dolor purus. Parturient montes nascetur ridiculus mus mauris vitae ultricies leo integer. Lectus urna duis convallis convallis. Cursus turpis massa tincidunt dui ut ornare lectus sit amet. Non odio euismod lacinia at quis. Massa id neque aliquam vestibulum morbi. Risus pretium quam vulputate dignissim suspendisse in. - -Quis lectus nulla at volutpat diam ut. Diam phasellus vestibulum lorem sed risus. Cum sociis natoque penatibus et magnis dis parturient montes. Mauris a diam maecenas sed enim ut sem. Molestie a iaculis at erat pellentesque. Nascetur ridiculus mus mauris vitae ultricies. Auctor eu augue ut lectus arcu bibendum at varius. Nisl pretium fusce id velit. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Pellentesque adipiscing commodo elit at. Tempus quam pellentesque nec nam aliquam. Amet porttitor eget dolor morbi. Sagittis orci a scelerisque purus. Mattis rhoncus urna neque viverra justo nec ultrices dui sapien. Arcu non sodales neque sodales. Blandit massa enim nec dui nunc mattis enim ut tellus. - -Dui vivamus arcu felis bibendum ut tristique et. Adipiscing at in tellus integer feugiat scelerisque varius. Vel facilisis volutpat est velit egestas dui id ornare arcu. Cras semper auctor neque vitae tempus. Posuere lorem ipsum dolor sit amet consectetur adipiscing. Sit amet mattis vulputate enim nulla. Nisl nisi scelerisque eu ultrices vitae auctor eu augue ut. Vitae suscipit tellus mauris a diam maecenas. Quis ipsum suspendisse ultrices gravida dictum fusce ut placerat orci. Tortor pretium viverra suspendisse potenti nullam ac tortor. Commodo nulla facilisi nullam vehicula. Neque volutpat ac tincidunt vitae semper quis lectus. Quis hendrerit dolor magna eget est lorem ipsum dolor sit. Adipiscing tristique risus nec feugiat in fermentum. - -Volutpat commodo sed egestas egestas. Lectus mauris ultrices eros in cursus turpis massa tincidunt. Nunc faucibus a pellentesque sit amet porttitor eget dolor. In ante metus dictum at. Egestas dui id ornare arcu. Magna etiam tempor orci eu lobortis elementum nibh. Odio tempor orci dapibus ultrices in. Id interdum velit laoreet id donec ultrices tincidunt arcu. Mi quis hendrerit dolor magna. Ultricies tristique nulla aliquet enim tortor at auctor urna. Amet dictum sit amet justo donec enim. Iaculis urna id volutpat lacus laoreet non curabitur gravida arcu. Quis enim lobortis scelerisque fermentum dui faucibus in ornare. Adipiscing bibendum est ultricies integer quis auctor elit sed vulputate. Lectus proin nibh nisl condimentum id venenatis. Sit amet venenatis urna cursus eget nunc. Et molestie ac feugiat sed lectus. Adipiscing bibendum est ultricies integer quis auctor elit sed. Porttitor eget dolor morbi non. Tellus integer feugiat scelerisque varius morbi. - -Sed cras ornare arcu dui vivamus arcu felis. Diam maecenas sed enim ut sem. Magna fermentum iaculis eu non diam phasellus. Suspendisse faucibus interdum posuere lorem ipsum dolor sit amet. In aliquam sem fringilla ut morbi tincidunt augue. Lacus suspendisse faucibus interdum posuere. Faucibus turpis in eu mi bibendum. Ut tortor pretium viverra suspendisse. In dictum non consectetur a erat nam at lectus urna. Netus et malesuada fames ac turpis egestas maecenas pharetra. Sit amet risus nullam eget felis eget nunc lobortis. Dolor purus non enim praesent elementum. Varius duis at consectetur lorem donec massa sapien. - -Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. Dui accumsan sit amet nulla facilisi morbi tempus. Vitae suscipit tellus mauris a diam maecenas sed enim. Diam quam nulla porttitor massa id. Ornare lectus sit amet est placerat in egestas erat imperdiet. Laoreet non curabitur gravida arcu ac tortor. Aliquet nibh praesent tristique magna. Non curabitur gravida arcu ac tortor dignissim convallis aenean et. Pretium vulputate sapien nec sagittis aliquam. Nulla facilisi etiam dignissim diam quis. Viverra vitae congue eu consequat. Ornare aenean euismod elementum nisi. Viverra accumsan in nisl nisi. Placerat in egestas erat imperdiet sed. Consectetur lorem donec massa sapien. Sed id semper risus in hendrerit. Hendrerit gravida rutrum quisque non tellus orci ac auctor augue. Cursus euismod quis viverra nibh cras. - -Eget gravida cum sociis natoque penatibus et. Semper quis lectus nulla at volutpat diam ut. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Vehicula ipsum a arcu cursus vitae congue. Nulla facilisi etiam dignissim diam quis enim. Integer quis auctor elit sed vulputate mi sit amet mauris. Nibh sed pulvinar proin gravida. Ornare lectus sit amet est placerat in egestas erat. At volutpat diam ut venenatis tellus. Vulputate eu scelerisque felis imperdiet proin. Lacus luctus accumsan tortor posuere ac ut consequat. Egestas tellus rutrum tellus pellentesque eu. Eget mauris pharetra et ultrices neque ornare aenean. Morbi leo urna molestie at elementum. Enim ut tellus elementum sagittis vitae et. Massa tincidunt dui ut ornare lectus sit amet est placerat. Eget est lorem ipsum dolor sit amet consectetur adipiscing elit. Sed sed risus pretium quam vulputate. Sagittis nisl rhoncus mattis rhoncus urna. Vestibulum rhoncus est pellentesque elit. - -Elementum eu facilisis sed odio. Ultricies leo integer malesuada nunc vel risus commodo viverra maecenas. Vitae nunc sed velit dignissim sodales ut. Imperdiet proin fermentum leo vel orci porta non pulvinar. Non curabitur gravida arcu ac tortor dignissim convallis aenean. In pellentesque massa placerat duis ultricies lacus sed turpis tincidunt. Scelerisque eu ultrices vitae auctor eu augue ut lectus. Sit amet nisl purus in mollis nunc sed id semper. Ullamcorper a lacus vestibulum sed arcu non odio euismod lacinia. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Egestas egestas fringilla phasellus faucibus scelerisque. Scelerisque purus semper eget duis. - -Nullam eget felis eget nunc lobortis. Non curabitur gravida arcu ac tortor dignissim convallis aenean et. Neque egestas congue quisque egestas diam. Quis hendrerit dolor magna eget est lorem ipsum. Sit amet mattis vulputate enim. Lorem donec massa sapien faucibus et molestie ac feugiat. Orci dapibus ultrices in iaculis nunc sed. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Quis hendrerit dolor magna eget est lorem ipsum dolor. Vel pharetra vel turpis nunc eget lorem dolor sed viverra. Neque sodales ut etiam sit amet nisl purus in mollis. Fermentum leo vel orci porta non pulvinar. Maecenas pharetra convallis posuere morbi. Leo duis ut diam quam. Donec ac odio tempor orci dapibus ultrices. - -Tincidunt vitae semper quis lectus nulla at. Id volutpat lacus laoreet non curabitur gravida arcu. Purus ut faucibus pulvinar elementum integer enim neque volutpat. Velit scelerisque in dictum non consectetur. Quis ipsum suspendisse ultrices gravida dictum fusce. Lacinia at quis risus sed vulputate odio ut enim. Blandit cursus risus at ultrices. Adipiscing elit pellentesque habitant morbi tristique senectus. Elementum facilisis leo vel fringilla est ullamcorper eget. Nibh nisl condimentum id venenatis a. - -Non sodales neque sodales ut etiam sit amet. Mauris pharetra et ultrices neque. Ac ut consequat semper viverra nam libero justo. Nibh tortor id aliquet lectus proin nibh nisl condimentum id. At ultrices mi tempus imperdiet nulla malesuada. Metus aliquam eleifend mi in nulla posuere sollicitudin aliquam. Massa tincidunt dui ut ornare. Nam at lectus urna duis convallis convallis tellus. Sed risus ultricies tristique nulla aliquet enim tortor. Odio aenean sed adipiscing diam donec adipiscing tristique risus. Eget magna fermentum iaculis eu non diam. Fames ac turpis egestas maecenas pharetra convallis posuere morbi leo. Quam nulla porttitor massa id neque. Tellus cras adipiscing enim eu turpis egestas pretium. Et tortor consequat id porta. - -Rhoncus est pellentesque elit ullamcorper dignissim. Semper feugiat nibh sed pulvinar proin gravida. Eget nulla facilisi etiam dignissim diam quis enim lobortis scelerisque. Nunc scelerisque viverra mauris in aliquam sem. Risus nullam eget felis eget nunc lobortis. Nulla porttitor massa id neque aliquam vestibulum morbi blandit. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui. Volutpat blandit aliquam etiam erat velit scelerisque. Ante metus dictum at tempor commodo ullamcorper a lacus. Sed tempus urna et pharetra pharetra massa massa. Urna et pharetra pharetra massa massa ultricies mi. Turpis in eu mi bibendum neque. Nulla malesuada pellentesque elit eget gravida cum. Faucibus turpis in eu mi bibendum neque egestas. Sit amet consectetur adipiscing elit ut aliquam purus sit. Donec pretium vulputate sapien nec. Volutpat odio facilisis mauris sit amet. Velit egestas dui id ornare arcu odio ut sem nulla. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien nec. - -Praesent elementum facilisis leo vel fringilla est ullamcorper eget. In vitae turpis massa sed elementum tempus. Morbi enim nunc faucibus a pellentesque. Laoreet sit amet cursus sit amet. Libero id faucibus nisl tincidunt eget nullam non nisi est. Semper quis lectus nulla at volutpat diam ut. Quisque sagittis purus sit amet volutpat consequat mauris nunc congue. Sit amet luctus venenatis lectus magna fringilla. Erat imperdiet sed euismod nisi porta lorem mollis aliquam. Sed euismod nisi porta lorem mollis aliquam ut. Eu augue ut lectus arcu. Ipsum a arcu cursus vitae congue mauris rhoncus aenean vel. Eget arcu dictum varius duis at consectetur lorem. Turpis massa tincidunt dui ut ornare lectus sit amet est. Facilisis magna etiam tempor orci eu lobortis elementum. Gravida arcu ac tortor dignissim convallis aenean. Ut pharetra sit amet aliquam. - -Pharetra convallis posuere morbi leo urna. Placerat duis ultricies lacus sed. Vitae elementum curabitur vitae nunc sed velit. Tempor orci eu lobortis elementum nibh tellus molestie nunc non. Feugiat scelerisque varius morbi enim nunc faucibus a. Sed faucibus turpis in eu mi bibendum neque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. Eu sem integer vitae justo eget magna. Orci porta non pulvinar neque laoreet suspendisse. Dictum non consectetur a erat. Est placerat in egestas erat imperdiet sed euismod. Tempus imperdiet nulla malesuada pellentesque elit. Sed augue lacus viverra vitae. Bibendum at varius vel pharetra. Aliquet bibendum enim facilisis gravida neque convallis a cras semper. Quis vel eros donec ac odio tempor orci. Varius vel pharetra vel turpis nunc eget. Nibh mauris cursus mattis molestie. - -Rutrum quisque non tellus orci ac. Id diam vel quam elementum pulvinar. Sem fringilla ut morbi tincidunt. Fermentum posuere urna nec tincidunt praesent semper feugiat nibh sed. Donec et odio pellentesque diam volutpat commodo sed egestas egestas. Augue mauris augue neque gravida in fermentum et sollicitudin. Arcu risus quis varius quam quisque id. Viverra mauris in aliquam sem. Suspendisse in est ante in nibh mauris cursus. Sed turpis tincidunt id aliquet risus feugiat in. Euismod lacinia at quis risus sed vulputate odio. \ No newline at end of file diff --git a/packages/storage/tests/resources/disk-b/appwrite.svg b/packages/storage/tests/resources/disk-b/appwrite.svg deleted file mode 100644 index aa591c949..000000000 --- a/packages/storage/tests/resources/disk-b/appwrite.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/storage/tests/resources/disk-b/kitten-1.png b/packages/storage/tests/resources/disk-b/kitten-1.png deleted file mode 100644 index 25df7c343..000000000 Binary files a/packages/storage/tests/resources/disk-b/kitten-1.png and /dev/null differ diff --git a/packages/storage/tests/resources/disk-b/kitten-2.png b/packages/storage/tests/resources/disk-b/kitten-2.png deleted file mode 100644 index 8629a6a76..000000000 Binary files a/packages/storage/tests/resources/disk-b/kitten-2.png and /dev/null differ